Skip to content

Commit b35ec6e

Browse files
authored
remove global set_sdk_key, make SDK key required in Config (#140)
1 parent 58b5bc3 commit b35ec6e

14 files changed

+44
-130
lines changed

demo/demo.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

docs/api-main.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ldclient module
55
---------------
66

77
.. automodule:: ldclient
8-
:members: get,set_config,set_sdk_key
8+
:members: get,set_config
99

1010
ldclient.client module
1111
----------------------

ldclient/__init__.py

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
start_wait = 5
1919

2020
__client = None
21-
__config = Config()
21+
__config = None
2222
__lock = ReadWriteLock()
2323

2424

@@ -48,52 +48,12 @@ def set_config(config: Config):
4848
__lock.unlock()
4949

5050

51-
def set_sdk_key(sdk_key: str):
52-
"""Sets the SDK key for the shared SDK client instance.
53-
54-
If this is called prior to :func:`ldclient.get()`, it stores the SDK key that will be used when the client is
55-
initialized. If it is called after the client has already been initialized, the client will be
56-
re-initialized with the new SDK key (this will result in the next call to :func:`ldclient.get()` returning a
57-
new client instance).
58-
59-
If you need to set any configuration options other than the SDK key, use :func:`ldclient.set_config()` instead.
60-
61-
:param sdk_key: the new SDK key
62-
"""
63-
global __config
64-
global __client
65-
global __lock
66-
sdk_key_changed = False
67-
try:
68-
__lock.rlock()
69-
if sdk_key == __config.sdk_key:
70-
log.info("New sdk_key is the same as the existing one. doing nothing.")
71-
else:
72-
sdk_key_changed = True
73-
finally:
74-
__lock.runlock()
75-
76-
if sdk_key_changed:
77-
try:
78-
__lock.lock()
79-
__config = __config.copy_with_new_sdk_key(new_sdk_key=sdk_key)
80-
if __client:
81-
log.info("Reinitializing LaunchDarkly Client " + VERSION + " with new sdk key")
82-
new_client = LDClient(config=__config, start_wait=start_wait)
83-
old_client = __client
84-
__client = new_client
85-
old_client.close()
86-
finally:
87-
__lock.unlock()
88-
89-
9051
def get() -> LDClient:
9152
"""Returns the shared SDK client instance, using the current global configuration.
9253
93-
To use the SDK as a singleton, first make sure you have called :func:`ldclient.set_sdk_key()` or
94-
:func:`ldclient.set_config()` at startup time. Then ``get()`` will return the same shared
95-
:class:`ldclient.client.LDClient` instance each time. The client will be initialized if it has
96-
not been already.
54+
To use the SDK as a singleton, first make sure you have called :func:`ldclient.set_config()`
55+
at startup time. Then ``get()`` will return the same shared :class:`ldclient.client.LDClient`
56+
instance each time. The client will be initialized if it has not been already.
9757
9858
If you need to create multiple client instances with different configurations, instead of this
9959
singleton approach you can call the :class:`ldclient.client.LDClient` constructor directly instead.
@@ -105,6 +65,8 @@ def get() -> LDClient:
10565
__lock.rlock()
10666
if __client:
10767
return __client
68+
if __config is None:
69+
raise Exception("set_config was not called")
10870
finally:
10971
__lock.runlock()
11072

ldclient/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ class LDClient:
6464
6565
Applications should configure the client at startup time and continue to use it throughout the lifetime
6666
of the application, rather than creating instances on the fly. The best way to do this is with the
67-
singleton methods :func:`ldclient.set_sdk_key()`, :func:`ldclient.set_config()`, and :func:`ldclient.get()`.
68-
However, you may also call the constructor directly if you need to maintain multiple instances.
67+
singleton methods :func:`ldclient.set_config()` and :func:`ldclient.get()`. However, you may also call
68+
the constructor directly if you need to maintain multiple instances.
6969
7070
Client instances are thread-safe.
7171
"""

ldclient/config.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Config:
8282
if you are using the singleton client, or the :class:`ldclient.client.LDClient` constructor otherwise.
8383
"""
8484
def __init__(self,
85-
sdk_key: Optional[str]=None,
85+
sdk_key: str,
8686
base_uri: str='https://app.launchdarkly.com',
8787
events_uri: str='https://events.launchdarkly.com',
8888
events_max_pending: int=10000,
@@ -111,7 +111,7 @@ def __init__(self,
111111
wrapper_version: Optional[str]=None,
112112
http: HTTPConfig=HTTPConfig()):
113113
"""
114-
:param sdk_key: The SDK key for your LaunchDarkly account.
114+
:param sdk_key: The SDK key for your LaunchDarkly account. This is always required.
115115
:param base_uri: The base URL for the LaunchDarkly server. Most users should use the default
116116
value.
117117
:param events_uri: The URL for the LaunchDarkly events server. Most users should use the
@@ -205,12 +205,6 @@ def __init__(self,
205205
self.__wrapper_version = wrapper_version
206206
self.__http = http
207207

208-
@classmethod
209-
def default(cls) -> 'Config':
210-
"""Returns a ``Config`` instance with default values for all properties.
211-
"""
212-
return cls()
213-
214208
def copy_with_new_sdk_key(self, new_sdk_key: str) -> 'Config':
215209
"""Returns a new ``Config`` instance that is the same as this one, except for having a different SDK key.
216210

ldclient/diagnostics.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import uuid
99
import platform
1010

11+
from ldclient.config import Config
1112
from ldclient.version import VERSION
1213

1314
class _DiagnosticAccumulator:
@@ -62,7 +63,7 @@ def _diagnostic_base_fields(kind, creation_date, diagnostic_id):
6263
'id': diagnostic_id}
6364

6465
def _create_diagnostic_config_object(config):
65-
default_config = config.default()
66+
default_config = Config("SDK_KEY")
6667
return {'customBaseURI': config.base_uri != default_config.base_uri,
6768
'customEventsURI': config.events_uri != default_config.events_uri,
6869
'customStreamURI': config.stream_base_uri != default_config.stream_base_uri,

testing/test_diagnostics.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_create_diagnostic_init():
3939
json.dumps(diag_init)
4040

4141
def test_create_diagnostic_config_defaults():
42-
test_config = Config()
42+
test_config = Config("SDK_KEY")
4343
diag_config = _create_diagnostic_config_object(test_config)
4444

4545
assert len(diag_config) == 17
@@ -63,7 +63,7 @@ def test_create_diagnostic_config_defaults():
6363

6464
def test_create_diagnostic_config_custom():
6565
test_store = CachingStoreWrapper(_TestStoreForDiagnostics(), CacheConfig.default())
66-
test_config = Config(base_uri='https://test.com', events_uri='https://test.com',
66+
test_config = Config("SDK_KEY", base_uri='https://test.com', events_uri='https://test.com',
6767
events_max_pending=10, flush_interval=1, stream_uri='https://test.com',
6868
stream=False, poll_interval=60, use_ldd=True, feature_store=test_store,
6969
all_attributes_private=True, user_keys_capacity=10, user_keys_flush_interval=60,
@@ -95,7 +95,7 @@ def describe_configuration(self, config):
9595

9696
def test_diagnostic_accumulator():
9797
test_config = Config(sdk_key = "SDK_KEY")
98-
diag_id = create_diagnostic_id(test_config);
98+
diag_id = create_diagnostic_id(test_config)
9999
diag_accum = _DiagnosticAccumulator(diag_id)
100100

101101
# Test default periodic event

testing/test_event_processor.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from testing.stub_util import MockResponse, MockHttp
1414

1515

16-
default_config = Config()
16+
default_config = Config("fake_sdk_key")
1717
user = {
1818
'key': 'userkey',
1919
'name': 'Red'
@@ -69,6 +69,8 @@ class DefaultTestProcessor(DefaultEventProcessor):
6969
def __init__(self, **kwargs):
7070
if not 'diagnostic_opt_out' in kwargs:
7171
kwargs['diagnostic_opt_out'] = True
72+
if not 'sdk_key' in kwargs:
73+
kwargs['sdk_key'] = 'SDK_KEY'
7274
config = Config(**kwargs)
7375
diagnostic_accumulator = _DiagnosticAccumulator(create_diagnostic_id(config))
7476
DefaultEventProcessor.__init__(self, config, mock_http, diagnostic_accumulator = diagnostic_accumulator)
@@ -531,7 +533,7 @@ def test_will_still_send_after_500_error():
531533
verify_recoverable_http_error(500)
532534

533535
def test_does_not_block_on_full_inbox():
534-
config = Config(events_max_pending=1) # this sets the size of both the inbox and the outbox to 1
536+
config = Config("fake_sdk_key", events_max_pending=1) # this sets the size of both the inbox and the outbox to 1
535537
ep_inbox_holder = [ None ]
536538
ep_inbox = None
537539

testing/test_file_data_source.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def teardown_function():
100100

101101
def make_data_source(**kwargs):
102102
global data_source
103-
data_source = Files.new_data_source(**kwargs)(Config(), store, ready)
103+
data_source = Files.new_data_source(**kwargs)(Config("SDK_KEY"), store, ready)
104104
return data_source
105105

106106
def make_temp_file(content):
@@ -226,7 +226,7 @@ def test_evaluates_full_flag_with_client_as_expected():
226226
path = make_temp_file(all_properties_json)
227227
try:
228228
factory = Files.new_data_source(paths = path)
229-
client = LDClient(config=Config(update_processor_class = factory, send_events = False))
229+
client = LDClient(config=Config('SDK_KEY', update_processor_class = factory, send_events = False))
230230
value = client.variation('flag1', { 'key': 'user' }, '')
231231
assert value == 'on'
232232
finally:
@@ -238,7 +238,7 @@ def test_evaluates_simplified_flag_with_client_as_expected():
238238
path = make_temp_file(all_properties_json)
239239
try:
240240
factory = Files.new_data_source(paths = path)
241-
client = LDClient(config=Config(update_processor_class = factory, send_events = False))
241+
client = LDClient(config=Config('SDK_KEY', update_processor_class = factory, send_events = False))
242242
value = client.variation('flag2', { 'key': 'user' }, '')
243243
assert value == 'value2'
244244
finally:
@@ -264,7 +264,7 @@ def test_does_not_allow_unsafe_yaml():
264264
path = make_temp_file(unsafe_yaml)
265265
try:
266266
factory = Files.new_data_source(paths = path)
267-
client = LDClient(config=Config(update_processor_class = factory, send_events = False))
267+
client = LDClient(config=Config('SDK_KEY', update_processor_class = factory, send_events = False))
268268
finally:
269269
os.remove(path)
270270
if client is not None:

testing/test_init.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,6 @@
66
mylogger = logging.getLogger()
77

88

9-
def test_set_sdk_key():
10-
old_sdk_key = "OLD_SDK_KEY"
11-
new_sdk_key = "NEW_SDK_KEY"
12-
13-
old_config = Config(sdk_key=old_sdk_key, stream=False, offline=True)
14-
ldclient.set_config(old_config)
15-
16-
old_client = ldclient.get()
17-
assert old_client.get_sdk_key() == old_sdk_key
18-
19-
ldclient.set_sdk_key(new_sdk_key)
20-
new_client = ldclient.get()
21-
22-
assert new_client.get_sdk_key() == new_sdk_key
23-
24-
# illustrates bad behavior- assigning value of ldclient.get() means
25-
# the old_client didn't get updated when we called set_sdk_key()
26-
assert old_client.get_sdk_key() == old_sdk_key
27-
28-
299
def test_set_config():
3010
old_sdk_key = "OLD_SDK_KEY"
3111
new_sdk_key = "NEW_SDK_KEY"

0 commit comments

Comments
 (0)