88import traceback
99
1010from ldclient .config import Config as Config
11- from ldclient .event_processor import NullEventProcessor
1211from ldclient .feature_requester import FeatureRequesterImpl
1312from ldclient .feature_store import _FeatureStoreDataSetSorter
1413from ldclient .flag import EvaluationDetail , evaluate , error_reason
1514from ldclient .flags_state import FeatureFlagsState
15+ from ldclient .impl .stubs import NullEventProcessor , NullUpdateProcessor
1616from ldclient .interfaces import FeatureStore
1717from ldclient .polling import PollingUpdateProcessor
1818from ldclient .streaming import StreamingUpdateProcessor
@@ -94,52 +94,54 @@ def __init__(self, sdk_key=None, config=None, start_wait=5):
9494 self ._store = _FeatureStoreClientWrapper (self ._config .feature_store )
9595 """ :type: FeatureStore """
9696
97- if self ._config .offline or not self ._config .send_events :
98- self ._event_processor = NullEventProcessor ()
99- else :
100- self ._event_processor = self ._config .event_processor_class (self ._config )
101-
10297 if self ._config .offline :
10398 log .info ("Started LaunchDarkly Client in offline mode" )
104- return
10599
106100 if self ._config .use_ldd :
107101 log .info ("Started LaunchDarkly Client in LDD mode" )
108- return
109102
110- update_processor_ready = threading .Event ()
111-
112- if self ._config .update_processor_class :
113- log .info ("Using user-specified update processor: " + str (self ._config .update_processor_class ))
114- self ._update_processor = self ._config .update_processor_class (
115- self ._config , self ._store , update_processor_ready )
116- else :
117- if self ._config .feature_requester_class :
118- feature_requester = self ._config .feature_requester_class (self ._config )
119- else :
120- feature_requester = FeatureRequesterImpl (self ._config )
121- """ :type: FeatureRequester """
122-
123- if self ._config .stream :
124- self ._update_processor = StreamingUpdateProcessor (
125- self ._config , feature_requester , self ._store , update_processor_ready )
126- else :
127- log .info ("Disabling streaming API" )
128- log .warn ("You should only disable the streaming API if instructed to do so by LaunchDarkly support" )
129- self ._update_processor = PollingUpdateProcessor (
130- self ._config , feature_requester , self ._store , update_processor_ready )
131- """ :type: UpdateProcessor """
103+ self ._event_processor = self ._make_event_processor (self ._config )
132104
105+ update_processor_ready = threading .Event ()
106+ self ._update_processor = self ._make_update_processor (self ._config , self ._store , update_processor_ready )
133107 self ._update_processor .start ()
134- log .info ("Waiting up to " + str (start_wait ) + " seconds for LaunchDarkly client to initialize..." )
135- update_processor_ready .wait (start_wait )
108+
109+ if start_wait > 0 and not self ._config .offline and not self ._config .use_ldd :
110+ log .info ("Waiting up to " + str (start_wait ) + " seconds for LaunchDarkly client to initialize..." )
111+ update_processor_ready .wait (start_wait )
136112
137113 if self ._update_processor .initialized () is True :
138114 log .info ("Started LaunchDarkly Client: OK" )
139115 else :
140116 log .warn ("Initialization timeout exceeded for LaunchDarkly Client or an error occurred. "
141117 "Feature Flags may not yet be available." )
142118
119+ def _make_event_processor (self , config ):
120+ if config .offline or not config .send_events :
121+ return NullEventProcessor ()
122+ return config .event_processor_class (config )
123+
124+ def _make_update_processor (self , config , store , ready ):
125+ if config .update_processor_class :
126+ log .info ("Using user-specified update processor: " + str (config .update_processor_class ))
127+ return config .update_processor_class (config , store , ready )
128+
129+ if config .offline or config .use_ldd :
130+ return NullUpdateProcessor (config , store , ready )
131+
132+ if config .feature_requester_class :
133+ feature_requester = config .feature_requester_class (config )
134+ else :
135+ feature_requester = FeatureRequesterImpl (config )
136+ """ :type: FeatureRequester """
137+
138+ if config .stream :
139+ return StreamingUpdateProcessor (config , feature_requester , store , ready )
140+
141+ log .info ("Disabling streaming API" )
142+ log .warn ("You should only disable the streaming API if instructed to do so by LaunchDarkly support" )
143+ return PollingUpdateProcessor (config , feature_requester , store , ready )
144+
143145 def get_sdk_key (self ):
144146 """Returns the configured SDK key.
145147
@@ -153,13 +155,16 @@ def close(self):
153155 Do not attempt to use the client after calling this method.
154156 """
155157 log .info ("Closing LaunchDarkly client.." )
156- if self .is_offline ():
157- return
158- if self ._event_processor :
159- self ._event_processor .stop ()
160- if self ._update_processor and self ._update_processor .is_alive ():
161- self ._update_processor .stop ()
158+ self ._event_processor .stop ()
159+ self ._update_processor .stop ()
162160
161+ # These magic methods allow a client object to be automatically cleaned up by the "with" scope operator
162+ def __enter__ (self ):
163+ return self
164+
165+ def __exit__ (self , type , value , traceback ):
166+ self .close ()
167+
163168 def _send_event (self , event ):
164169 self ._event_processor .send_event (event )
165170
0 commit comments