@@ -38,9 +38,9 @@ def _hash_percent(s: str, seed: str = "") -> float:
3838
3939 This is not the most efficient hash function but it's stable.
4040 Stability of this hash function is CRUCIAL. It's used to hash feature flag
41- names and target IDs to ensure consistent evaluation of feature flags across
41+ names and split targets to ensure consistent evaluation of feature flags across
4242 time, different instances, different python versions, operating systems and
43- so on because the distribution of target IDs depend on it.
43+ so on because the distribution of split targets depend on it.
4444 """
4545 return (
4646 int .from_bytes (
@@ -361,7 +361,7 @@ class _CompiledFilter:
361361 __slots__ = ("eval" , "flag_refs" , "rule_refs" )
362362
363363 # The compiled filter function.
364- eval : Callable [[TargetID , Attributes ], bool ]
364+ eval : Callable [[Attributes ], bool ]
365365 # The set of flag names referenced in the filter.
366366 flag_refs : set [str ]
367367 # The set of rule names referenced in the filter.
@@ -564,7 +564,7 @@ def _pythonize(self, f: _ParsedFilter, defined_flags: dict[str, CompiledFlag], d
564564 # This will therefore never raise an exception.
565565 if self ._ignore_undefined_refs and sym_name not in defined_flags :
566566 return "False"
567- lhs = f"flags[{ sym_name !r} ].eval(target_id, attributes).variant"
567+ lhs = f"flags[{ sym_name !r} ].eval(attributes).variant"
568568 if op in {"IN" , "NOTIN" }:
569569 return f"{ lhs } { self ._py_op_map [op ]} sets[{ arg2 !r} ]"
570570 else :
@@ -598,7 +598,7 @@ def _pythonize(self, f: _ParsedFilter, defined_flags: dict[str, CompiledFlag], d
598598 # exists. This will therefore never raise an exception.
599599 if self ._ignore_undefined_refs and sym_name not in defined_rules :
600600 return "False"
601- lhs = f"rules[{ sym_name !r} ].eval(target_id, attributes)"
601+ lhs = f"rules[{ sym_name !r} ].eval(attributes)"
602602 return f"{ lhs } { self ._py_op_map [op ]} { arg2 !r} "
603603 case _: # pragma: no cover
604604 assert False , "unreachable" # pragma: no cover
@@ -622,7 +622,7 @@ def compile(self, name: str, flags: dict[str, CompiledFlag], rules: dict[str, _C
622622 optimized = self ._optimize (inlined )
623623 py_expr = self ._pythonize (optimized , flags , rules )
624624 code_str = f"""
625- def a(target_id, attributes):
625+ def a(attributes):
626626 return { py_expr }
627627"""
628628 py_code = compile (code_str , "" , "exec" )
@@ -645,9 +645,6 @@ def a(target_id, attributes):
645645 _config_schema = json .load (f )
646646
647647
648- type TargetID = str
649-
650-
651648class _CompiledRule :
652649 """
653650 Flag independent compiled rule that evaluates to a boolean indicating
@@ -656,7 +653,7 @@ class _CompiledRule:
656653
657654 __slots__ = ("name" , "eval" , "_compiled_filter" )
658655 name : str
659- eval : Callable [[TargetID , Attributes ], bool ]
656+ eval : Callable [[Attributes ], bool ]
660657 _compiled_filter : _CompiledFilter
661658
662659
@@ -668,7 +665,7 @@ class _CompiledFlagRule:
668665
669666 __slots__ = ("rule_name" , "eval" )
670667 rule_name : str
671- eval : Callable [[TargetID , Attributes ], Variant | None ]
668+ eval : Callable [[Attributes ], Variant | None ]
672669
673670
674671class CompiledFlag :
@@ -691,13 +688,12 @@ class CompiledFlag:
691688 _all_rules : dict [str , _CompiledRule ]
692689 _all_flags : dict [str , CompiledFlag ]
693690
694- def eval (self , target_id : TargetID , attributes : Attributes ) -> FlagEvaluation :
691+ def eval (self , attributes : Attributes ) -> FlagEvaluation :
695692 e = FlagEvaluation ()
696693 e .default = self .default
697694 e .flag = self .name
698- e .target_id = target_id
699695 for rule in self ._rules :
700- v = rule .eval (target_id , attributes )
696+ v = rule .eval (attributes )
701697 if v is not None :
702698 e .rule = rule .rule_name
703699 e .variant = v
@@ -861,11 +857,11 @@ def from_dict(c: DictConfig, ignore_undefined_refs: bool = False) -> CompiledCon
861857 compiled_rule ._compiled_filter = cf
862858 globals ["match" ] = cf .eval
863859 py_common += [f"attributes['__seed'] = { r .get ('split_group' , rule_name )!r} " ]
864- py_common += ["if not match(target_id, attributes): return None" ]
860+ py_common += ["if not match(attributes): return None" ]
865861
866862 # Compile the flag independent rule.
867863
868- lines = ["def a(target_id, attributes):" ]
864+ lines = ["def a(attributes):" ]
869865 for line in py_common :
870866 line = re .sub (r"return None$" , "return False" , line )
871867 lines .append (f" { line } " )
@@ -889,7 +885,7 @@ def from_dict(c: DictConfig, ignore_undefined_refs: bool = False) -> CompiledCon
889885 # Returns variant | None
890886 # - variant: The variant evaluated
891887 # - None: The rule does not apply
892- lines = ["def a(target_id, attributes):" ]
888+ lines = ["def a(attributes):" ]
893889 lines += list (f" { line } " for line in (py_common + py_lines ))
894890 lines += [" return None" ]
895891 lines_str = "\n " .join (lines )
@@ -972,15 +968,15 @@ class FlagEvaluation:
972968 "flag" ,
973969 "variant" ,
974970 "default" ,
975- "target_id " ,
971+ "attributes " ,
976972 "rule" ,
977973 "reason" ,
978974 "timestamp" ,
979975 )
980976 flag : str
981977 variant : Variant
982978 default : Variant
983- target_id : str
979+ attributes : Attributes
984980 rule : str | Literal ["" ]
985981 reason : Literal ["const_rule" , "default" ]
986982 timestamp : float
@@ -1042,14 +1038,12 @@ def _record_eval_metrics(self, e: FlagEvaluation, dur: float):
10421038 }
10431039 _prom_eval_duration .labels (** labels ).observe (dur )
10441040
1045- def detailed_evaluate_all (self , config : CompiledConfig , names : Iterable [str ], id : str , attributes : Attributes = {}) -> dict [str , FlagEvaluation ]:
1041+ def detailed_evaluate_all (self , config : CompiledConfig , names : Iterable [str ], attributes : Attributes = {}) -> dict [str , FlagEvaluation ]:
10461042 """
10471043 Evaluate all flags for the given id and attributes and return
10481044 FlagEvaluations. detailed_evaluate_all is thread-safe.
10491045 """
10501046 assert config ._feafea_checksum == _feafea_checksum , "incompatible config"
1051- if not isinstance (id , str ):
1052- raise TypeError (f"id must be a string, not { type (id ).__name__ } " )
10531047 self ._validate_attributes_type (attributes )
10541048 merged_attributes = {"__now" : time .time (), ** attributes }
10551049 now = merged_attributes ["__now" ]
@@ -1062,7 +1056,8 @@ def detailed_evaluate_all(self, config: CompiledConfig, names: Iterable[str], id
10621056 if flag is None :
10631057 raise ValueError (f"Flag { name } does not exist in the config" )
10641058 start = time .perf_counter ()
1065- e = flag .eval (id , merged_attributes )
1059+ e = flag .eval (merged_attributes )
1060+ e .attributes = merged_attributes
10661061 e .timestamp = now
10671062 dur = time .perf_counter () - start
10681063 self ._record_eval_metrics (e , dur )
@@ -1088,19 +1083,18 @@ def pop_evaluations(self) -> list[FlagEvaluation]:
10881083 self ._evaluations = []
10891084 return es
10901085
1091- def evaluate (self , config : CompiledConfig , name : str , id : str , attributes : Attributes = {}) -> Variant :
1086+ def evaluate (self , config : CompiledConfig , name : str , attributes : Attributes = {}) -> Variant :
10921087 """
10931088 Evaluate the given flag. evaluate is thread-safe.
10941089
10951090 name: The name of the flag.
1096- id: The id of the flag.
10971091 attributes: The attributes to evaluate the flag with.
10981092 """
1099- return next (iter (self .detailed_evaluate_all (config , [name ], id , attributes ).values ())).variant
1093+ return next (iter (self .detailed_evaluate_all (config , [name ], attributes ).values ())).variant
11001094
1101- def evaluate_all (self , config : CompiledConfig , names : Iterable [str ], id : str , attributes : Attributes = {}) -> dict [str , Variant ]:
1095+ def evaluate_all (self , config : CompiledConfig , names : Iterable [str ], attributes : Attributes = {}) -> dict [str , Variant ]:
11021096 """
11031097 Evaluate all flags for the given id and attributes. evaluate_all is
11041098 thread-safe.
11051099 """
1106- return {n : e .variant for n , e in self .detailed_evaluate_all (config , names , id , attributes ).items ()}
1100+ return {n : e .variant for n , e in self .detailed_evaluate_all (config , names , attributes ).items ()}
0 commit comments