1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ from cmath import log
1516from typing import List , Optional , Dict , TYPE_CHECKING
1617
1718from featureprobe .evaluation_result import EvaluationResult
1819from featureprobe .internal .json_decoder import json_decoder
1920from featureprobe .model .rule import Rule
2021from featureprobe .model .serve import Serve
22+ from featureprobe .model .prerequisite import Prerequisite , PrerequisiteError
23+ import json
24+
2125
2226if TYPE_CHECKING :
2327 from featureprobe .hit_result import HitResult
@@ -36,7 +40,8 @@ def __init__(self,
3640 variations : list ,
3741 for_client : bool ,
3842 track_access_events : bool ,
39- last_modified : int ):
43+ last_modified : int ,
44+ prerequisites : List ["Prerequisite" ]):
4045 self ._key = key
4146 self ._enabled = enabled
4247 self ._version = version
@@ -47,6 +52,7 @@ def __init__(self,
4752 self ._for_client = for_client
4853 self ._track_access_events = track_access_events
4954 self ._last_modified = last_modified
55+ self ._prerequisites = prerequisites
5056
5157 @classmethod
5258 @json_decoder
@@ -61,6 +67,9 @@ def from_json(cls, json: dict) -> "Toggle":
6167 for_client = json .get ('forClient' , False )
6268 track_access_events = json .get ('trackAccessEvents' , False )
6369 last_modified = json .get ('lastModified' , None )
70+ prerequisites = [
71+ Prerequisite .from_json (r ) for r in json .get (
72+ 'prerequisites' , [])]
6473
6574 return cls (
6675 key ,
@@ -72,7 +81,8 @@ def from_json(cls, json: dict) -> "Toggle":
7281 variations ,
7382 for_client ,
7483 track_access_events ,
75- last_modified )
84+ last_modified ,
85+ prerequisites )
7686
7787 @property
7888 def key (self ) -> str :
@@ -144,14 +154,36 @@ def for_client(self, value: bool):
144154
145155 def eval (self ,
146156 user : "User" ,
147- segments : Dict [str ,
148- "Segment" ],
149- default_value : object ) -> "EvaluationResult" :
157+ toggles : Dict [str , "Toggle" ],
158+ segments : Dict [str , "Segment" ],
159+ default_value : object ,
160+ deep : int ) -> "EvaluationResult" :
161+
162+ warning = ''
163+ try :
164+ return self .do_eval (user , toggles , segments , default_value , deep )
165+ except PrerequisiteError as e :
166+ warning = e
167+ return self ._create_default_result (
168+ user , self ._key , default_value , warning )
169+
170+ def do_eval (self ,
171+ user : "User" ,
172+ toggles : Dict [str , "Toggle" ],
173+ segments : Dict [str , "Segment" ],
174+ default_value : object ,
175+ deep : int ) -> "EvaluationResult" :
150176 if not self ._enabled :
151177 return self ._create_disabled_result (user , self ._key , default_value )
152178
179+ if deep <= 0 :
180+ raise PrerequisiteError ("prerequisite deep overflow" )
153181 warning = None
154182
183+ if not self .prerequisite (user , toggles , segments , deep ):
184+ return self ._create_default_result (
185+ user , self ._key , default_value , warning )
186+
155187 for index , rule in enumerate (self ._rules or []):
156188 hit_result = rule .hit (user , segments , self ._key )
157189 if hit_result .hit :
@@ -161,6 +193,27 @@ def eval(self,
161193 return self ._create_default_result (
162194 user , self ._key , default_value , warning )
163195
196+ def prerequisite (self ,
197+ user : "User" ,
198+ toggles : Dict [str , "Toggle" ],
199+ segments : Dict [str , "Segment" ],
200+ max_deep : int ) -> bool :
201+ if self ._prerequisites is None or len (self ._prerequisites ) == 0 :
202+ return True
203+ for prerequisite in self ._prerequisites :
204+ toggle = toggles .get (prerequisite .key )
205+ if toggle is None :
206+ raise PrerequisiteError (
207+ 'prerequisite not exist %s' %
208+ prerequisite .key )
209+ result = toggle .do_eval (
210+ user , toggles , segments , None , max_deep - 1 )
211+ if result .value is None or str (
212+ result .value ) != str (
213+ prerequisite .value ):
214+ return False
215+ return True
216+
164217 def _create_disabled_result (
165218 self ,
166219 user : "User" ,
0 commit comments