diff --git a/ldclient/client.py b/ldclient/client.py index 4d8b9600..66d925f7 100644 --- a/ldclient/client.py +++ b/ldclient/client.py @@ -10,7 +10,7 @@ import threading import traceback -from ldclient.config import Config as Config +from ldclient.config import Config, HTTPConfig from ldclient.diagnostics import create_diagnostic_id, _DiagnosticAccumulator from ldclient.event_processor import DefaultEventProcessor from ldclient.feature_requester import FeatureRequesterImpl @@ -69,24 +69,15 @@ class LDClient: Client instances are thread-safe. """ - def __init__(self, sdk_key: str=None, config: Config=None, start_wait: float=5): + def __init__(self, config: Config, start_wait: float=5): """Constructs a new LDClient instance. - :param sdk_key: the SDK key for your LaunchDarkly environment :param config: optional custom configuration :param start_wait: the number of seconds to wait for a successful connection to LaunchDarkly """ check_uwsgi() - if config is not None and config.sdk_key is not None and sdk_key is not None: - raise Exception("LaunchDarkly client init received both sdk_key and config with sdk_key. " - "Only one of either is expected") - - if sdk_key is not None: - log.warning("Deprecated sdk_key argument was passed to init. Use config object instead.") - self._config = Config(sdk_key=sdk_key) - else: - self._config = config or Config.default() + self._config = config self._config._validate() self._event_processor = None @@ -237,14 +228,6 @@ def flush(self): return return self._event_processor.flush() - def toggle(self, key, user, default): - """Deprecated synonym for :func:`variation()`. - - .. deprecated:: 2.0.0 - """ - log.warning("Deprecated method: toggle() called. Use variation() instead.") - return self.variation(key, user, default) - def variation(self, key: str, user: dict, default: Any) -> Any: """Determines the variation of a feature flag for a user. @@ -325,21 +308,6 @@ def _evaluate_internal(self, key, user, default, event_factory): self._send_event(event_factory.new_default_event(flag, user, default, reason)) return EvaluationDetail(default, None, reason) - def all_flags(self, user: dict) -> Optional[dict]: - """Returns all feature flag values for the given user. - - This method is deprecated - please use :func:`all_flags_state()` instead. Current versions of the - client-side SDK will not generate analytics events correctly if you pass the result of ``all_flags``. - - :param user: the end user requesting the feature flags - :return: a dictionary of feature flag keys to values; returns None if the client is offline, - has not been initialized, or the user is None or has no key - """ - state = self.all_flags_state(user) - if not state.valid: - return None - return state.to_values_map() - def all_flags_state(self, user: dict, **kwargs) -> FeatureFlagsState: """Returns an object that encapsulates the state of all feature flags for a given user, including the flag values and also metadata that can be used on the front end. See the diff --git a/ldclient/config.py b/ldclient/config.py index 5a0d25e2..c421610f 100644 --- a/ldclient/config.py +++ b/ldclient/config.py @@ -20,10 +20,6 @@ class HTTPConfig: This class groups together HTTP/HTTPS-related configuration properties that rarely need to be changed. If you need to set these, construct an `HTTPConfig` instance and pass it as the `http` parameter when you construct the main :class:`Config` for the SDK client. - - For some of these properties, :class:`Config` also has properties with the same names; the latter are - deprecated and will be removed in the future, and if you specify an `HTTPConfig` instance then the - corresponding `Config` properties will be ignored. """ def __init__(self, connect_timeout: float=10, @@ -89,18 +85,15 @@ def __init__(self, sdk_key: Optional[str]=None, base_uri: str='https://app.launchdarkly.com', events_uri: str='https://events.launchdarkly.com', - connect_timeout=10, # deprecated - read_timeout=15, # deprecated events_max_pending: int=10000, flush_interval: float=5, stream_uri: str='https://stream.launchdarkly.com', stream: bool=True, initial_reconnect_delay: float=1, - verify_ssl=True, # deprecated defaults: dict={}, send_events: Optional[bool]=None, events_enabled: bool=True, - update_processor_class: Callable[[str, 'Config', FeatureStore], UpdateProcessor]=None, + update_processor_class: Optional[Callable[[str, 'Config', FeatureStore], UpdateProcessor]]=None, poll_interval: float=30, use_ldd: bool=False, feature_store: Optional[FeatureStore]=None, @@ -112,22 +105,17 @@ def __init__(self, user_keys_capacity: int=1000, user_keys_flush_interval: float=300, inline_users_in_events: bool=False, - http_proxy=None, # deprecated diagnostic_opt_out: bool=False, diagnostic_recording_interval: int=900, wrapper_name: Optional[str]=None, wrapper_version: Optional[str]=None, - http: Optional[HTTPConfig]=None): + http: HTTPConfig=HTTPConfig()): """ :param sdk_key: The SDK key for your LaunchDarkly account. :param base_uri: The base URL for the LaunchDarkly server. Most users should use the default value. :param events_uri: The URL for the LaunchDarkly events server. Most users should use the default value. - :param connect_timeout: Deprecated; use `http` instead and specify the `connect_timeout` as - part of :class:`HTTPConfig`. - :param read_timeout: Deprecated; use `http` instead and specify the `read_timeout` as - part of :class:`HTTPConfig`. :param events_max_pending: The capacity of the events buffer. The client buffers up to this many events in memory before flushing. If the capacity is exceeded before the buffer is flushed, events will be discarded. @@ -141,8 +129,6 @@ def __init__(self, connection. The streaming service uses a backoff algorithm (with jitter) every time the connection needs to be reestablished. The delay for the first reconnection will start near this value, and then increase exponentially for any subsequent connection failures. - :param verify_ssl: Deprecated; use `http` instead and specify `disable_ssl_verification` as - part of :class:`HTTPConfig` if you want to turn off SSL verification (not recommended). :param send_events: Whether or not to send events back to LaunchDarkly. This differs from `offline` in that it affects only the sending of client-side events, not streaming or polling for events from the server. By default, events will be sent. @@ -171,8 +157,6 @@ def __init__(self, :param event_processor_class: A factory for an EventProcessor implementation taking the config :param update_processor_class: A factory for an UpdateProcessor implementation taking the sdk key, config, and FeatureStore implementation - :param http_proxy: Deprecated; use `http` instead and specify the `http_proxy` as part of - :class:`HTTPConfig`. :param diagnostic_opt_out: Unless this field is set to True, the client will send some diagnostics data to the LaunchDarkly servers in order to assist in the development of future SDK improvements. These diagnostics consist of an initial payload containing some details of SDK in use, @@ -203,11 +187,8 @@ def __init__(self, self.__feature_store = InMemoryFeatureStore() if not feature_store else feature_store self.__event_processor_class = event_processor_class self.__feature_requester_class = feature_requester_class - self.__connect_timeout = connect_timeout - self.__read_timeout = read_timeout self.__events_max_pending = events_max_pending self.__flush_interval = flush_interval - self.__verify_ssl = verify_ssl self.__defaults = defaults if offline is True: send_events = False @@ -218,7 +199,6 @@ def __init__(self, self.__user_keys_capacity = user_keys_capacity self.__user_keys_flush_interval = user_keys_flush_interval self.__inline_users_in_events = inline_users_in_events - self.__http_proxy = http_proxy self.__diagnostic_opt_out = diagnostic_opt_out self.__diagnostic_recording_interval = max(diagnostic_recording_interval, 60) self.__wrapper_name = wrapper_name @@ -239,14 +219,11 @@ def copy_with_new_sdk_key(self, new_sdk_key: str) -> 'Config': return Config(sdk_key=new_sdk_key, base_uri=self.__base_uri, events_uri=self.__events_uri, - connect_timeout=self.__connect_timeout, - read_timeout=self.__read_timeout, events_max_pending=self.__events_max_pending, flush_interval=self.__flush_interval, stream_uri=self.__stream_uri, stream=self.__stream, initial_reconnect_delay=self.__initial_reconnect_delay, - verify_ssl=self.__verify_ssl, defaults=self.__defaults, send_events=self.__send_events, update_processor_class=self.__update_processor_class, @@ -335,14 +312,6 @@ def event_processor_class(self) -> Optional[Callable[['Config'], EventProcessor] def feature_requester_class(self) -> Callable: return self.__feature_requester_class - @property - def connect_timeout(self) -> float: - return self.__connect_timeout - - @property - def read_timeout(self) -> float: - return self.__read_timeout - @property def events_enabled(self) -> bool: return self.__send_events @@ -359,10 +328,6 @@ def events_max_pending(self) -> int: def flush_interval(self) -> float: return self.__flush_interval - @property - def verify_ssl(self) -> bool: - return self.__verify_ssl - @property def private_attribute_names(self) -> list: return list(self.__private_attribute_names) @@ -387,10 +352,6 @@ def user_keys_flush_interval(self) -> float: def inline_users_in_events(self) -> bool: return self.__inline_users_in_events - @property - def http_proxy(self): - return self.__http_proxy - @property def diagnostic_opt_out(self) -> bool: return self.__diagnostic_opt_out @@ -409,15 +370,6 @@ def wrapper_version(self) -> Optional[str]: @property def http(self) -> HTTPConfig: - if self.__http is None: - return HTTPConfig( - connect_timeout=self.__connect_timeout, - read_timeout=self.__read_timeout, - http_proxy=self.__http_proxy, - ca_certs=None, - cert_file=None, - disable_ssl_verification=not self.__verify_ssl - ) return self.__http def _validate(self): diff --git a/ldclient/diagnostics.py b/ldclient/diagnostics.py index fc3486b5..055dfe06 100644 --- a/ldclient/diagnostics.py +++ b/ldclient/diagnostics.py @@ -67,10 +67,10 @@ def _create_diagnostic_config_object(config): 'customEventsURI': config.events_uri != default_config.events_uri, 'customStreamURI': config.stream_base_uri != default_config.stream_base_uri, 'eventsCapacity': config.events_max_pending, - 'connectTimeoutMillis': config.connect_timeout * 1000, - 'socketTimeoutMillis': config.read_timeout * 1000, + 'connectTimeoutMillis': config.http.connect_timeout * 1000, + 'socketTimeoutMillis': config.http.read_timeout * 1000, 'eventsFlushIntervalMillis': config.flush_interval * 1000, - 'usingProxy': config.http_proxy is not None, + 'usingProxy': config.http.http_proxy is not None, 'streamingDisabled': not config.stream, 'usingRelayDaemon': config.use_ldd, 'allAttributesPrivate': config.all_attributes_private, diff --git a/ldclient/event_processor.py b/ldclient/event_processor.py index de5f8107..6bdb7da9 100644 --- a/ldclient/event_processor.py +++ b/ldclient/event_processor.py @@ -477,7 +477,7 @@ def _post_events_with_retry( uri, headers=hdrs, body=body, - timeout=urllib3.Timeout(connect=config.connect_timeout, read=config.read_timeout), + timeout=urllib3.Timeout(connect=config.http.connect_timeout, read=config.http.read_timeout), retries=0 ) if r.status < 300: diff --git a/ldclient/feature_requester.py b/ldclient/feature_requester.py index 4557104f..b526a332 100644 --- a/ldclient/feature_requester.py +++ b/ldclient/feature_requester.py @@ -37,7 +37,7 @@ def get_all_data(self): hdrs['If-None-Match'] = cache_entry.etag r = self._http.request('GET', uri, headers=hdrs, - timeout=urllib3.Timeout(connect=self._config.connect_timeout, read=self._config.read_timeout), + timeout=urllib3.Timeout(connect=self._config.http.connect_timeout, read=self._config.http.read_timeout), retries=1) throw_if_unsuccessful_response(r) if r.status == 304 and cache_entry is not None: diff --git a/ldclient/file_data_source.py b/ldclient/file_data_source.py deleted file mode 100644 index 56da8de8..00000000 --- a/ldclient/file_data_source.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Deprecated entry point for a component that has been moved. -""" -# currently excluded from documentation - see docs/README.md - -from ldclient.impl.integrations.files.file_data_source import _FileDataSource -from ldclient.interfaces import UpdateProcessor - -class FileDataSource(UpdateProcessor): - @classmethod - def factory(cls, **kwargs): - """Provides a way to use local files as a source of feature flag state. - - .. deprecated:: 6.8.0 - This module and this implementation class are deprecated and may be changed or removed in the future. - Please use :func:`ldclient.integrations.Files.new_data_source()`. - - The keyword arguments are the same as the arguments to :func:`ldclient.integrations.Files.new_data_source()`. - """ - - return lambda config, store, ready : _FileDataSource(store, ready, - paths=kwargs.get("paths"), - auto_update=kwargs.get("auto_update", False), - poll_interval=kwargs.get("poll_interval", 1), - force_polling=kwargs.get("force_polling", False)) diff --git a/ldclient/memoized_value.py b/ldclient/memoized_value.py deleted file mode 100644 index d92b69ad..00000000 --- a/ldclient/memoized_value.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Internal helper class for caching. No longer used. -""" -# currently excluded from documentation - see docs/README.md - -from threading import RLock - -class MemoizedValue: - """Simple implementation of a thread-safe memoized value whose generator function will never be - run more than once, and whose value can be overridden by explicit assignment. - - .. deprecated:: 6.7.0 - No longer used. Retained here only in case third parties were using it for another purpose. - """ - def __init__(self, generator): - self.generator = generator - self.inited = False - self.value = None - self.lock = RLock() - - def get(self): - with self.lock: - if not self.inited: - self.value = self.generator() - self.inited = True - return self.value - - def set(self, value): - with self.lock: - self.value = value - self.inited = True diff --git a/ldclient/operators.py b/ldclient/operators.py index 39e8860c..8bf95f86 100644 --- a/ldclient/operators.py +++ b/ldclient/operators.py @@ -5,7 +5,7 @@ import logging import re -import semver +from semver import VersionInfo import sys from datetime import tzinfo, timedelta, datetime from collections import defaultdict @@ -67,17 +67,17 @@ def _time_operator(u, c, fn): def _parse_semver(input): try: - semver.VersionInfo.parse(input) + VersionInfo.parse(input) return input except ValueError as e: try: input = _add_zero_version_component(input) - semver.VersionInfo.parse(input) + VersionInfo.parse(input) return input except ValueError as e: try: input = _add_zero_version_component(input) - semver.VersionInfo.parse(input) + VersionInfo.parse(input) return input except ValueError as e: return None @@ -143,15 +143,15 @@ def _after(u, c): def _semver_equal(u, c): - return _semver_operator(u, c, lambda u, c: semver.compare(u, c) == 0) + return _semver_operator(u, c, lambda u, c: VersionInfo.parse(u).compare(c) == 0) def _semver_less_than(u, c): - return _semver_operator(u, c, lambda u, c: semver.compare(u, c) < 0) + return _semver_operator(u, c, lambda u, c: VersionInfo.parse(u).compare(c) < 0) def _semver_greater_than(u, c): - return _semver_operator(u, c, lambda u, c: semver.compare(u, c) > 0) + return _semver_operator(u, c, lambda u, c: VersionInfo.parse(u).compare(c) > 0) _ZERO = timedelta(0) diff --git a/ldclient/redis_feature_store.py b/ldclient/redis_feature_store.py deleted file mode 100644 index 1e49d9ee..00000000 --- a/ldclient/redis_feature_store.py +++ /dev/null @@ -1,46 +0,0 @@ -from ldclient.impl.integrations.redis.redis_feature_store import _RedisFeatureStoreCore - -from ldclient.feature_store import CacheConfig -from ldclient.feature_store_helpers import CachingStoreWrapper -from ldclient.interfaces import FeatureStore - - -# Note that this class is now just a facade around CachingStoreWrapper, which is in turn delegating -# to _RedisFeatureStoreCore where the actual database logic is. This class was retained for historical -# reasons, to support existing code that calls the RedisFeatureStore constructor. In the future, we -# will migrate away from exposing these concrete classes and use only the factory methods. - -class RedisFeatureStore(FeatureStore): - """A Redis-backed implementation of :class:`ldclient.interfaces.FeatureStore`. - - .. deprecated:: 6.7.0 - This module and this implementation class are deprecated and may be changed or removed in the future. - Please use :func:`ldclient.integrations.Redis.new_feature_store()`. - """ - def __init__(self, - url='redis://localhost:6379/0', - prefix='launchdarkly', - max_connections=16, - expiration=15, - capacity=1000): - self.core = _RedisFeatureStoreCore(url, prefix, max_connections) # exposed for testing - self._wrapper = CachingStoreWrapper(self.core, CacheConfig(expiration=expiration, capacity=capacity)) - - def get(self, kind, key, callback = lambda x: x): - return self._wrapper.get(kind, key, callback) - - def all(self, kind, callback): - return self._wrapper.all(kind, callback) - - def init(self, all_data): - return self._wrapper.init(all_data) - - def upsert(self, kind, item): - return self._wrapper.upsert(kind, item) - - def delete(self, kind, key, version): - return self._wrapper.delete(kind, key, version) - - @property - def initialized(self): - return self._wrapper.initialized diff --git a/requirements.txt b/requirements.txt index e80910cf..449e3467 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ certifi>=2018.4.16 expiringdict>=1.1.4,<1.2.0 pyRFC3339>=1.0 -semver>=2.10.2 +semver>=2.10.2,<3.0.0 urllib3>=1.22.0 diff --git a/testing/proxy_test_util.py b/testing/proxy_test_util.py index b9483f7b..2d6532d4 100644 --- a/testing/proxy_test_util.py +++ b/testing/proxy_test_util.py @@ -31,7 +31,7 @@ def do_proxy_tests(action, action_method, monkeypatch): base_uri = target_uri, events_uri = target_uri, stream_uri = target_uri, - http = None if use_env_vars else HTTPConfig(http_proxy=proxy_uri), + http = HTTPConfig(http_proxy=proxy_uri), diagnostic_opt_out = True) try: action(server, config, secure) diff --git a/testing/test_diagnostics.py b/testing/test_diagnostics.py index 6fd8e90d..7d10e1ba 100644 --- a/testing/test_diagnostics.py +++ b/testing/test_diagnostics.py @@ -1,14 +1,14 @@ import json import uuid -from ldclient.config import Config +from ldclient.config import Config, HTTPConfig from ldclient.diagnostics import create_diagnostic_id, create_diagnostic_init, _DiagnosticAccumulator, _create_diagnostic_config_object from ldclient.feature_store import CacheConfig from ldclient.feature_store_helpers import CachingStoreWrapper def test_create_diagnostic_id(): - test_config = Config(sdk_key = "SDK_KEY") - diag_id = create_diagnostic_id(test_config); + test_config = Config(sdk_key = "SDK_KEY", http=HTTPConfig()) + diag_id = create_diagnostic_id(test_config) assert len(diag_id) == 2 uid = diag_id['diagnosticId'] # Will throw if invalid UUID4 @@ -17,7 +17,7 @@ def test_create_diagnostic_id(): def test_create_diagnostic_init(): test_config = Config(sdk_key = "SDK_KEY", wrapper_name='django', wrapper_version = '5.1.1') - diag_id = create_diagnostic_id(test_config); + diag_id = create_diagnostic_id(test_config) diag_init = create_diagnostic_init(100, diag_id, test_config) assert len(diag_init) == 6 assert diag_init['kind'] == 'diagnostic-init' @@ -64,11 +64,10 @@ def test_create_diagnostic_config_defaults(): def test_create_diagnostic_config_custom(): test_store = CachingStoreWrapper(_TestStoreForDiagnostics(), CacheConfig.default()) test_config = Config(base_uri='https://test.com', events_uri='https://test.com', - connect_timeout=1, read_timeout=1, events_max_pending=10, - flush_interval=1, stream_uri='https://test.com', + events_max_pending=10, flush_interval=1, stream_uri='https://test.com', stream=False, poll_interval=60, use_ldd=True, feature_store=test_store, all_attributes_private=True, user_keys_capacity=10, user_keys_flush_interval=60, - inline_users_in_events=True, http_proxy='', diagnostic_recording_interval=60) + inline_users_in_events=True, http=HTTPConfig(http_proxy = 'proxy', read_timeout=1, connect_timeout=1), diagnostic_recording_interval=60) diag_config = _create_diagnostic_config_object(test_config) assert len(diag_config) == 17 diff --git a/testing/test_event_processor.py b/testing/test_event_processor.py index 76208784..900d04eb 100644 --- a/testing/test_event_processor.py +++ b/testing/test_event_processor.py @@ -4,7 +4,7 @@ import time import uuid -from ldclient.config import Config +from ldclient.config import Config, HTTPConfig from ldclient.diagnostics import create_diagnostic_id, _DiagnosticAccumulator from ldclient.event_processor import DefaultEventProcessor from ldclient.util import log @@ -215,7 +215,7 @@ def test_two_events_for_same_user_only_produce_one_index_event(): 'kind': 'feature', 'key': 'flagkey', 'version': 11, 'user': user, 'variation': 1, 'value': 'value', 'default': 'default', 'trackEvents': True } - e1 = e0.copy(); + e1 = e0.copy() ep.send_event(e0) ep.send_event(e1) @@ -232,8 +232,8 @@ def test_new_index_event_is_added_if_user_cache_has_been_cleared(): 'kind': 'feature', 'key': 'flagkey', 'version': 11, 'user': user, 'variation': 1, 'value': 'value', 'default': 'default', 'trackEvents': True } - e1 = e0.copy(); - ep.send_event(e0); + e1 = e0.copy() + ep.send_event(e0) time.sleep(0.2) ep.send_event(e1) diff --git a/testing/test_feature_store.py b/testing/test_feature_store.py index bb54bb50..1df87694 100644 --- a/testing/test_feature_store.py +++ b/testing/test_feature_store.py @@ -18,7 +18,6 @@ from ldclient.feature_store import CacheConfig, InMemoryFeatureStore from ldclient.impl.integrations.dynamodb.dynamodb_feature_store import _DynamoDBFeatureStoreCore, _DynamoDBHelpers from ldclient.integrations import Consul, DynamoDB, Redis -from ldclient.redis_feature_store import RedisFeatureStore from ldclient.versioned_data_kind import FEATURES skip_db_tests = os.environ.get('LD_SKIP_DATABASE_TESTS') == '1' @@ -54,17 +53,6 @@ def _clear_data(self): r = redis.StrictRedis(host=self.redis_host, port=self.redis_port, db=0) r.flushdb() - -class RedisWithDeprecatedConstructorTester(RedisTester): - def init_store(self, prefix=None): - self._clear_data() - return RedisFeatureStore(expiration=(30 if self._cache_config.enabled else 0), prefix=prefix) - - @property - def supports_prefix(self): - return True - - class ConsulTester(Tester): def __init__(self, cache_config): self._cache_config = cache_config @@ -182,8 +170,6 @@ class TestFeatureStore: InMemoryTester(), RedisTester(CacheConfig.default()), RedisTester(CacheConfig.disabled()), - RedisWithDeprecatedConstructorTester(CacheConfig.default()), - RedisWithDeprecatedConstructorTester(CacheConfig.disabled()), DynamoDBTester(CacheConfig.default()), DynamoDBTester(CacheConfig.disabled()) ] @@ -332,7 +318,7 @@ def test_stores_with_different_prefixes_are_independent(self, tester): class TestRedisFeatureStoreExtraTests: def test_upsert_race_condition_against_external_client_with_higher_version(self): other_client = redis.StrictRedis(host='localhost', port=6379, db=0) - store = RedisFeatureStore() + store = Redis.new_feature_store() store.init({ FEATURES: {} }) other_version = {u'key': u'flagkey', u'version': 2} @@ -340,7 +326,7 @@ def hook(base_key, key): if other_version['version'] <= 4: other_client.hset(base_key, key, json.dumps(other_version)) other_version['version'] = other_version['version'] + 1 - store.core.test_update_hook = hook + store._core.test_update_hook = hook feature = { u'key': 'flagkey', u'version': 1 } @@ -350,7 +336,7 @@ def hook(base_key, key): def test_upsert_race_condition_against_external_client_with_lower_version(self): other_client = redis.StrictRedis(host='localhost', port=6379, db=0) - store = RedisFeatureStore() + store = Redis.new_feature_store() store.init({ FEATURES: {} }) other_version = {u'key': u'flagkey', u'version': 2} @@ -358,7 +344,7 @@ def hook(base_key, key): if other_version['version'] <= 4: other_client.hset(base_key, key, json.dumps(other_version)) other_version['version'] = other_version['version'] + 1 - store.core.test_update_hook = hook + store._core.test_update_hook = hook feature = { u'key': 'flagkey', u'version': 5 } diff --git a/testing/test_ldclient_end_to_end.py b/testing/test_ldclient_end_to_end.py index 48968b9f..7003805a 100644 --- a/testing/test_ldclient_end_to_end.py +++ b/testing/test_ldclient_end_to_end.py @@ -129,7 +129,7 @@ def test_can_connect_with_selfsigned_cert_if_ssl_verify_is_false(): base_uri = server.uri, stream = False, send_events = False, - verify_ssl = False + http = HTTPConfig(disable_ssl_verification=True) ) with LDClient(config = config) as client: assert client.is_initialized() diff --git a/testing/test_ldclient_evaluation.py b/testing/test_ldclient_evaluation.py index f716c5de..06ec99f7 100644 --- a/testing/test_ldclient_evaluation.py +++ b/testing/test_ldclient_evaluation.py @@ -166,27 +166,27 @@ def test_all_flags_returns_values(): store = InMemoryFeatureStore() store.init({ FEATURES: { 'key1': flag1, 'key2': flag2 } }) client = make_client(store) - result = client.all_flags(user) + result = client.all_flags_state(user).to_values_map() assert result == { 'key1': 'value1', 'key2': 'value2' } def test_all_flags_returns_none_if_user_is_none(): store = InMemoryFeatureStore() store.init({ FEATURES: { 'key1': flag1, 'key2': flag2 } }) client = make_client(store) - result = client.all_flags(None) - assert result is None + result = client.all_flags_state(None) + assert not result.valid def test_all_flags_returns_none_if_user_has_no_key(): store = InMemoryFeatureStore() store.init({ FEATURES: { 'key1': flag1, 'key2': flag2 } }) client = make_client(store) - result = client.all_flags({ }) - assert result is None + result = client.all_flags_state({ }) + assert not result.valid def test_all_flags_returns_none_if_feature_store_throws_error(caplog): store = ErroringFeatureStore() client = make_client(store) - assert client.all_flags({ "key": "user" }) is None + assert not client.all_flags_state({ "key": "user" }).valid errlog = get_log_lines(caplog, 'ERROR') assert errlog == [ 'Unable to read flags for all_flag_state: NotImplementedError()' ] @@ -195,7 +195,7 @@ def test_all_flags_state_returns_state(): store.init({ FEATURES: { 'key1': flag1, 'key2': flag2 } }) client = make_client(store) state = client.all_flags_state(user) - assert state.valid == True + assert state.valid result = state.to_json_dict() assert result == { 'key1': 'value1', @@ -220,7 +220,7 @@ def test_all_flags_state_returns_state_with_reasons(): store.init({ FEATURES: { 'key1': flag1, 'key2': flag2 } }) client = make_client(store) state = client.all_flags_state(user, with_reasons=True) - assert state.valid == True + assert state.valid result = state.to_json_dict() assert result == { 'key1': 'value1', @@ -277,7 +277,7 @@ def test_all_flags_state_can_be_filtered_for_client_side_flags(): client = make_client(store) state = client.all_flags_state(user, client_side_only=True) - assert state.valid == True + assert state.valid values = state.to_values_map() assert values == { 'client-side-1': 'value1', 'client-side-2': 'value2' }