77from flag_engine .environments .builders import build_environment_model
88from flag_engine .environments .models import EnvironmentModel
99from flag_engine .identities .models import IdentityModel , TraitModel
10- from requests .adapters import HTTPAdapter , Retry
10+ from requests .adapters import HTTPAdapter
11+ from urllib3 import Retry
1112
1213from flagsmith .analytics import AnalyticsProcessor
1314from flagsmith .exceptions import FlagsmithAPIError , FlagsmithClientError
2122
2223
2324class Flagsmith :
25+ """A Flagsmith client.
26+
27+ Provides an interface for interacting with the Flagsmith http API.
28+
29+ Basic Usage::
30+
31+ >>> from flagsmith import Flagsmith
32+ >>> flagsmith = Flagsmith(environment_key="<your API key>")
33+ >>> environment_flags = flagsmith.get_environment_flags()
34+ >>> feature_enabled = environment_flags.is_feature_enabled("foo")
35+ >>> identity_flags = flagsmith.get_identity_flags("identifier", {"foo": "bar"})
36+ >>> feature_enabled_for_identity = identity_flags.is_feature_enabled("foo")
37+ """
38+
2439 def __init__ (
2540 self ,
2641 environment_key : str ,
@@ -31,8 +46,26 @@ def __init__(
3146 environment_refresh_interval_seconds : int = 60 ,
3247 retries : Retry = None ,
3348 enable_analytics : bool = False ,
34- defaults : typing .List [ DefaultFlag ] = None ,
49+ default_flag_handler : typing .Callable [[ str ], DefaultFlag ] = None ,
3550 ):
51+ """
52+ :param environment_key: The environment key obtained from Flagsmith interface
53+ :param api_url: Override the URL of the Flagsmith API to communicate with
54+ :param custom_headers: Additional headers to add to requests made to the
55+ Flagsmith API
56+ :param request_timeout_seconds: Number of seconds to wait for a request to
57+ complete before terminating the request
58+ :param enable_local_evaluation: Enables local evaluation of flags
59+ :param environment_refresh_interval_seconds: If using local evaluation,
60+ specify the interval period between refreshes of local environment data
61+ :param retries: a urllib3.Retry object to use on all http requests to the
62+ Flagsmith API
63+ :param enable_analytics: if enabled, sends additional requests to the Flagsmith
64+ API to power flag analytics charts
65+ :param default_flag_handler: callable which will be used in the case where
66+ flags cannot be retrieved from the API or a non existent feature is
67+ requested
68+ """
3669 self .session = requests .Session ()
3770 self .session .headers .update (
3871 ** {"X-Environment-Key" : environment_key }, ** (custom_headers or {})
@@ -65,7 +98,7 @@ def __init__(
6598 else None
6699 )
67100
68- self .defaults = defaults or []
101+ self .default_flag_handler = default_flag_handler
69102
70103 def get_environment_flags (self ) -> Flags :
71104 """
@@ -107,7 +140,7 @@ def _get_environment_flags_from_document(self) -> Flags:
107140 return Flags .from_feature_state_models (
108141 feature_states = engine .get_environment_feature_states (self ._environment ),
109142 analytics_processor = self ._analytics_processor ,
110- defaults = self .defaults ,
143+ default_flag_handler = self .default_flag_handler ,
111144 )
112145
113146 def _get_identity_flags_from_document (
@@ -121,32 +154,41 @@ def _get_identity_flags_from_document(
121154 feature_states = feature_states ,
122155 analytics_processor = self ._analytics_processor ,
123156 identity_id = identity_model .composite_key ,
124- defaults = self .defaults ,
157+ default_flag_handler = self .default_flag_handler ,
125158 )
126159
127160 def _get_environment_flags_from_api (self ) -> Flags :
128- api_flags = self ._get_json_response (
129- url = self .environment_flags_url , method = "GET"
130- )
131-
132- return Flags .from_api_flags (
133- api_flags = api_flags ,
134- analytics_processor = self ._analytics_processor ,
135- defaults = self .defaults ,
136- )
161+ try :
162+ api_flags = self ._get_json_response (
163+ url = self .environment_flags_url , method = "GET"
164+ )
165+ return Flags .from_api_flags (
166+ api_flags = api_flags ,
167+ analytics_processor = self ._analytics_processor ,
168+ default_flag_handler = self .default_flag_handler ,
169+ )
170+ except FlagsmithAPIError :
171+ if self .default_flag_handler :
172+ return Flags (default_flag_handler = self .default_flag_handler )
173+ raise
137174
138175 def _get_identity_flags_from_api (
139176 self , identifier : str , traits : typing .Dict [str , typing .Any ]
140177 ) -> Flags :
141- data = generate_identities_data (identifier , traits )
142- json_response = self ._get_json_response (
143- url = self .identities_url , method = "POST" , body = data
144- )
145- return Flags .from_api_flags (
146- api_flags = json_response ["flags" ],
147- analytics_processor = self ._analytics_processor ,
148- defaults = self .defaults ,
149- )
178+ try :
179+ data = generate_identities_data (identifier , traits )
180+ json_response = self ._get_json_response (
181+ url = self .identities_url , method = "POST" , body = data
182+ )
183+ return Flags .from_api_flags (
184+ api_flags = json_response ["flags" ],
185+ analytics_processor = self ._analytics_processor ,
186+ default_flag_handler = self .default_flag_handler ,
187+ )
188+ except FlagsmithAPIError :
189+ if self .default_flag_handler :
190+ return Flags (default_flag_handler = self .default_flag_handler )
191+ raise
150192
151193 def _get_json_response (self , url : str , method : str , body : dict = None ):
152194 try :
0 commit comments