4444 FlagsAndPayloads ,
4545 FlagsResponse ,
4646 FlagValue ,
47+ SendFeatureFlagsOptions ,
4748 normalize_flags_response ,
4849 to_flags_and_payloads ,
4950 to_payloads ,
@@ -313,6 +314,7 @@ def get_feature_variants(
313314 person_properties = None ,
314315 group_properties = None ,
315316 disable_geoip = None ,
317+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
316318 ) -> dict [str , Union [bool , str ]]:
317319 """
318320 Get feature flag variants for a user by calling decide.
@@ -323,12 +325,19 @@ def get_feature_variants(
323325 person_properties: A dictionary of person properties.
324326 group_properties: A dictionary of group properties.
325327 disable_geoip: Whether to disable GeoIP for this request.
328+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
329+ only these flags will be evaluated, improving performance.
326330
327331 Category:
328332 Feature Flags
329333 """
330334 resp_data = self .get_flags_decision (
331- distinct_id , groups , person_properties , group_properties , disable_geoip
335+ distinct_id ,
336+ groups ,
337+ person_properties ,
338+ group_properties ,
339+ disable_geoip ,
340+ flag_keys_to_evaluate ,
332341 )
333342 return to_values (resp_data ) or {}
334343
@@ -339,6 +348,7 @@ def get_feature_payloads(
339348 person_properties = None ,
340349 group_properties = None ,
341350 disable_geoip = None ,
351+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
342352 ) -> dict [str , str ]:
343353 """
344354 Get feature flag payloads for a user by calling decide.
@@ -349,6 +359,8 @@ def get_feature_payloads(
349359 person_properties: A dictionary of person properties.
350360 group_properties: A dictionary of group properties.
351361 disable_geoip: Whether to disable GeoIP for this request.
362+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
363+ only these flags will be evaluated, improving performance.
352364
353365 Examples:
354366 ```python
@@ -359,7 +371,12 @@ def get_feature_payloads(
359371 Feature Flags
360372 """
361373 resp_data = self .get_flags_decision (
362- distinct_id , groups , person_properties , group_properties , disable_geoip
374+ distinct_id ,
375+ groups ,
376+ person_properties ,
377+ group_properties ,
378+ disable_geoip ,
379+ flag_keys_to_evaluate ,
363380 )
364381 return to_payloads (resp_data ) or {}
365382
@@ -370,6 +387,7 @@ def get_feature_flags_and_payloads(
370387 person_properties = None ,
371388 group_properties = None ,
372389 disable_geoip = None ,
390+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
373391 ) -> FlagsAndPayloads :
374392 """
375393 Get feature flags and payloads for a user by calling decide.
@@ -380,6 +398,8 @@ def get_feature_flags_and_payloads(
380398 person_properties: A dictionary of person properties.
381399 group_properties: A dictionary of group properties.
382400 disable_geoip: Whether to disable GeoIP for this request.
401+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
402+ only these flags will be evaluated, improving performance.
383403
384404 Examples:
385405 ```python
@@ -390,7 +410,12 @@ def get_feature_flags_and_payloads(
390410 Feature Flags
391411 """
392412 resp = self .get_flags_decision (
393- distinct_id , groups , person_properties , group_properties , disable_geoip
413+ distinct_id ,
414+ groups ,
415+ person_properties ,
416+ group_properties ,
417+ disable_geoip ,
418+ flag_keys_to_evaluate ,
394419 )
395420 return to_flags_and_payloads (resp )
396421
@@ -401,6 +426,7 @@ def get_flags_decision(
401426 person_properties = None ,
402427 group_properties = None ,
403428 disable_geoip = None ,
429+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
404430 ) -> FlagsResponse :
405431 """
406432 Get feature flags decision.
@@ -411,6 +437,8 @@ def get_flags_decision(
411437 person_properties: A dictionary of person properties.
412438 group_properties: A dictionary of group properties.
413439 disable_geoip: Whether to disable GeoIP for this request.
440+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
441+ only these flags will be evaluated, improving performance.
414442
415443 Examples:
416444 ```python
@@ -441,6 +469,9 @@ def get_flags_decision(
441469 "geoip_disable" : disable_geoip ,
442470 }
443471
472+ if flag_keys_to_evaluate :
473+ request_data ["flag_keys_to_evaluate" ] = flag_keys_to_evaluate
474+
444475 resp_data = flags (
445476 self .api_key ,
446477 self .host ,
@@ -545,6 +576,7 @@ def capture(
545576 group_properties = flag_options ["group_properties" ],
546577 disable_geoip = disable_geoip ,
547578 only_evaluate_locally = True ,
579+ flag_keys_to_evaluate = flag_options ["flag_keys_filter" ],
548580 )
549581 else :
550582 # Default behavior - use remote evaluation
@@ -554,6 +586,7 @@ def capture(
554586 person_properties = flag_options ["person_properties" ],
555587 group_properties = flag_options ["group_properties" ],
556588 disable_geoip = disable_geoip ,
589+ flag_keys_to_evaluate = flag_options ["flag_keys_filter" ],
557590 )
558591 except Exception as e :
559592 self .log .exception (
@@ -586,16 +619,16 @@ def capture(
586619
587620 return self ._enqueue (msg , disable_geoip )
588621
589- def _parse_send_feature_flags (self , send_feature_flags ) -> dict :
622+ def _parse_send_feature_flags (self , send_feature_flags ) -> SendFeatureFlagsOptions :
590623 """
591624 Parse and normalize send_feature_flags parameter into a standard format.
592625
593626 Args:
594627 send_feature_flags: Either bool or SendFeatureFlagsOptions dict
595628
596629 Returns:
597- dict : Normalized options with keys: should_send, only_evaluate_locally,
598- person_properties, group_properties
630+ SendFeatureFlagsOptions : Normalized options with keys: should_send, only_evaluate_locally,
631+ person_properties, group_properties, flag_keys_filter
599632
600633 Raises:
601634 TypeError: If send_feature_flags is not bool or dict
@@ -608,13 +641,15 @@ def _parse_send_feature_flags(self, send_feature_flags) -> dict:
608641 ),
609642 "person_properties" : send_feature_flags .get ("person_properties" ),
610643 "group_properties" : send_feature_flags .get ("group_properties" ),
644+ "flag_keys_filter" : send_feature_flags .get ("flag_keys_filter" ),
611645 }
612646 elif isinstance (send_feature_flags , bool ):
613647 return {
614648 "should_send" : send_feature_flags ,
615649 "only_evaluate_locally" : None ,
616650 "person_properties" : None ,
617651 "group_properties" : None ,
652+ "flag_keys_filter" : None ,
618653 }
619654 else :
620655 raise TypeError (
@@ -1184,12 +1219,12 @@ def _compute_flag_locally(
11841219 self .log .warning (
11851220 f"[FEATURE FLAGS] Unknown group type index { aggregation_group_type_index } for feature flag { feature_flag ['key' ]} "
11861221 )
1187- # failover to `/decide/ `
1222+ # failover to `/flags `
11881223 raise InconclusiveMatchError ("Flag has unknown group type index" )
11891224
11901225 if group_name not in groups :
11911226 # Group flags are never enabled in `groups` aren't passed in
1192- # don't failover to `/decide/ `, since response will be the same
1227+ # don't failover to `/flags `, since response will be the same
11931228 if warn_on_unknown_groups :
11941229 self .log .warning (
11951230 f"[FEATURE FLAGS] Can't compute group feature flag: { feature_flag ['key' ]} without group names passed in"
@@ -1317,7 +1352,7 @@ def _get_feature_flag_result(
13171352 )
13181353 elif not only_evaluate_locally :
13191354 try :
1320- flag_details , request_id = self ._get_feature_flag_details_from_decide (
1355+ flag_details , request_id = self ._get_feature_flag_details_from_server (
13211356 key ,
13221357 distinct_id ,
13231358 groups ,
@@ -1557,7 +1592,7 @@ def get_feature_flag_payload(
15571592 )
15581593 return feature_flag_result .payload if feature_flag_result else None
15591594
1560- def _get_feature_flag_details_from_decide (
1595+ def _get_feature_flag_details_from_server (
15611596 self ,
15621597 key : str ,
15631598 distinct_id : ID_TYPES ,
@@ -1567,10 +1602,15 @@ def _get_feature_flag_details_from_decide(
15671602 disable_geoip : Optional [bool ],
15681603 ) -> tuple [Optional [FeatureFlag ], Optional [str ]]:
15691604 """
1570- Calls /decide and returns the flag details and request id
1605+ Calls /flags and returns the flag details and request id
15711606 """
15721607 resp_data = self .get_flags_decision (
1573- distinct_id , groups , person_properties , group_properties , disable_geoip
1608+ distinct_id ,
1609+ groups ,
1610+ person_properties ,
1611+ group_properties ,
1612+ disable_geoip ,
1613+ flag_keys_to_evaluate = [key ],
15741614 )
15751615 request_id = resp_data .get ("requestId" )
15761616 flags = resp_data .get ("flags" )
@@ -1686,6 +1726,7 @@ def get_all_flags(
16861726 group_properties = None ,
16871727 only_evaluate_locally = False ,
16881728 disable_geoip = None ,
1729+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
16891730 ) -> Optional [dict [str , Union [bool , str ]]]:
16901731 """
16911732 Get all feature flags for a user.
@@ -1697,6 +1738,8 @@ def get_all_flags(
16971738 group_properties: A dictionary of group properties.
16981739 only_evaluate_locally: Whether to only evaluate locally.
16991740 disable_geoip: Whether to disable GeoIP for this request.
1741+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
1742+ only these flags will be evaluated, improving performance.
17001743
17011744 Examples:
17021745 ```python
@@ -1713,6 +1756,7 @@ def get_all_flags(
17131756 group_properties = group_properties ,
17141757 only_evaluate_locally = only_evaluate_locally ,
17151758 disable_geoip = disable_geoip ,
1759+ flag_keys_to_evaluate = flag_keys_to_evaluate ,
17161760 )
17171761
17181762 return response ["featureFlags" ]
@@ -1726,6 +1770,7 @@ def get_all_flags_and_payloads(
17261770 group_properties = None ,
17271771 only_evaluate_locally = False ,
17281772 disable_geoip = None ,
1773+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
17291774 ) -> FlagsAndPayloads :
17301775 """
17311776 Get all feature flags and their payloads for a user.
@@ -1737,6 +1782,8 @@ def get_all_flags_and_payloads(
17371782 group_properties: A dictionary of group properties.
17381783 only_evaluate_locally: Whether to only evaluate locally.
17391784 disable_geoip: Whether to disable GeoIP for this request.
1785+ flag_keys_to_evaluate: A list of specific flag keys to evaluate. If provided,
1786+ only these flags will be evaluated, improving performance.
17401787
17411788 Examples:
17421789 ```python
@@ -1760,6 +1807,7 @@ def get_all_flags_and_payloads(
17601807 groups = groups ,
17611808 person_properties = person_properties ,
17621809 group_properties = group_properties ,
1810+ flag_keys_to_evaluate = flag_keys_to_evaluate ,
17631811 )
17641812
17651813 if fallback_to_decide and not only_evaluate_locally :
@@ -1770,6 +1818,7 @@ def get_all_flags_and_payloads(
17701818 person_properties = person_properties ,
17711819 group_properties = group_properties ,
17721820 disable_geoip = disable_geoip ,
1821+ flag_keys_to_evaluate = flag_keys_to_evaluate ,
17731822 )
17741823 return to_flags_and_payloads (decide_response )
17751824 except Exception as e :
@@ -1787,6 +1836,7 @@ def _get_all_flags_and_payloads_locally(
17871836 person_properties = None ,
17881837 group_properties = None ,
17891838 warn_on_unknown_groups = False ,
1839+ flag_keys_to_evaluate : Optional [list [str ]] = None ,
17901840 ) -> tuple [FlagsAndPayloads , bool ]:
17911841 person_properties = person_properties or {}
17921842 group_properties = group_properties or {}
@@ -1799,7 +1849,15 @@ def _get_all_flags_and_payloads_locally(
17991849 fallback_to_decide = False
18001850 # If loading in previous line failed
18011851 if self .feature_flags :
1802- for flag in self .feature_flags :
1852+ # Filter flags based on flag_keys_to_evaluate if provided
1853+ flags_to_process = self .feature_flags
1854+ if flag_keys_to_evaluate :
1855+ flag_keys_set = set (flag_keys_to_evaluate )
1856+ flags_to_process = [
1857+ flag for flag in self .feature_flags if flag ["key" ] in flag_keys_set
1858+ ]
1859+
1860+ for flag in flags_to_process :
18031861 try :
18041862 flags [flag ["key" ]] = self ._compute_flag_locally (
18051863 flag ,
@@ -1815,7 +1873,7 @@ def _get_all_flags_and_payloads_locally(
18151873 if matched_payload is not None :
18161874 payloads [flag ["key" ]] = matched_payload
18171875 except InconclusiveMatchError :
1818- # No need to log this, since it's just telling us to fall back to `/decide `
1876+ # No need to log this, since it's just telling us to fall back to `/flags `
18191877 fallback_to_decide = True
18201878 except Exception as e :
18211879 self .log .exception (
0 commit comments