diff --git a/splitio/client/client.py b/splitio/client/client.py index 8a638a0b..35030595 100644 --- a/splitio/client/client.py +++ b/splitio/client/client.py @@ -59,8 +59,9 @@ def destroyed(self): """Return whether the factory holding this client has been destroyed.""" return self._factory.destroyed - def _evaluate_if_ready(self, matching_key, bucketing_key, feature, attributes=None): + def _evaluate_if_ready(self, matching_key, bucketing_key, feature, method, attributes=None): if not self.ready: + _LOGGER.warning("%s: The SDK is not ready, results may be incorrect for feature flag %s. Make sure to wait for SDK readiness before using this method", method, feature) self._telemetry_init_producer.record_not_ready_usage() return { 'treatment': CONTROL, @@ -102,7 +103,7 @@ def _make_evaluation(self, key, feature_flag, attributes, method_name, metric_na or not input_validator.validate_attributes(attributes, method_name): return CONTROL, None - result = self._evaluate_if_ready(matching_key, bucketing_key, feature_flag, attributes) + result = self._evaluate_if_ready(matching_key, bucketing_key, feature_flag, method_name, attributes) impression = self._build_impression( matching_key, @@ -167,7 +168,7 @@ def _make_evaluations(self, key, feature_flags, attributes, method_name, metric_ try: evaluations = self._evaluate_features_if_ready(matching_key, bucketing_key, - list(feature_flags), attributes) + list(feature_flags), method_name, attributes) for feature_flag in feature_flags: try: @@ -212,8 +213,9 @@ def _make_evaluations(self, key, feature_flags, attributes, method_name, metric_ _LOGGER.debug('Error: ', exc_info=True) return input_validator.generate_control_treatments(list(feature_flags), method_name) - def _evaluate_features_if_ready(self, matching_key, bucketing_key, feature_flags, attributes=None): + def _evaluate_features_if_ready(self, matching_key, bucketing_key, feature_flags, method, attributes=None): if not self.ready: + _LOGGER.warning("%s: The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", method, ', '.join([feature for feature in feature_flags])) self._telemetry_init_producer.record_not_ready_usage() return { feature_flag: { diff --git a/splitio/models/splits.py b/splitio/models/splits.py index 5ab32953..0a10dd87 100644 --- a/splitio/models/splits.py +++ b/splitio/models/splits.py @@ -7,7 +7,7 @@ SplitView = namedtuple( 'SplitView', - ['name', 'traffic_type', 'killed', 'treatments', 'change_number', 'configs', 'sets'] + ['name', 'traffic_type', 'killed', 'treatments', 'change_number', 'configs', 'default_treatment', 'sets'] ) @@ -200,6 +200,7 @@ def to_split_view(self): list(set(part.treatment for cond in self.conditions for part in cond.partitions)), self.change_number, self._configurations if self._configurations is not None else {}, + self._default_treatment, list(self._sets) if self._sets is not None else [] ) diff --git a/tests/client/test_client.py b/tests/client/test_client.py index fcddbf79..6341142c 100644 --- a/tests/client/test_client.py +++ b/tests/client/test_client.py @@ -83,6 +83,7 @@ def test_get_treatment(self, mocker): assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flag %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -159,6 +160,7 @@ def test_get_treatment_with_config(self, mocker): [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flag %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -236,6 +238,7 @@ def test_get_treatments(self, mocker): assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -310,6 +313,7 @@ def test_get_treatments_with_config(self, mocker): assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -400,6 +404,7 @@ def evaluate_features(feature_flag_names, matching_key, bucketing_key, attribute assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -465,7 +470,6 @@ def evaluate_features(feature_flag_names, matching_key, bucketing_key, attribute client._evaluator.evaluate_features = evaluate_features _logger = mocker.Mock() client._send_impression_to_listener = mocker.Mock() -# pytest.set_trace() assert client.get_treatments_by_flag_sets('key', ['set1', 'set2']) == {'f1': 'on', 'f2': 'on'} impressions_called = impmanager.process_impressions.mock_calls[0][1][0] @@ -488,6 +492,7 @@ def evaluate_features(feature_flag_names, matching_key, bucketing_key, attribute assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -581,6 +586,7 @@ def evaluate_features(feature_flag_names, matching_key, bucketing_key, attribute assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -677,6 +683,7 @@ def evaluate_features(feature_flag_names, matching_key, bucketing_key, attribute assert mocker.call( [(Impression('some_key', 'some_feature', 'control', Label.NOT_READY, mocker.ANY, mocker.ANY, mocker.ANY), {'some_attribute': 1})] ) in impmanager.process_impressions.mock_calls + assert _logger.call(["The SDK is not ready, results may be incorrect for feature flags %s. Make sure to wait for SDK readiness before using this method", 'some_feature']) # Test with exception: ready_property.return_value = True @@ -748,6 +755,7 @@ def test_track(self, mocker): telemetry_producer.get_telemetry_init_producer(), mocker.Mock() ) + _logger = mocker.Mock() destroyed_mock = mocker.PropertyMock() destroyed_mock.return_value = False @@ -762,6 +770,7 @@ def test_track(self, mocker): size=1024 ) ]) in event_storage.put.mock_calls + assert _logger.call("track: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method") def test_evaluations_before_running_post_fork(self, mocker): destroyed_property = mocker.PropertyMock() @@ -837,7 +846,7 @@ def test_telemetry_not_ready(self, mocker): ) client = Client(factory, mocker.Mock()) client.ready = False - client._evaluate_if_ready('matching_key','matching_key', 'feature') + client._evaluate_if_ready('matching_key','matching_key', 'method', 'feature') assert(telemetry_storage._tel_config._not_ready == 1) client.track('key', 'tt', 'ev') assert(telemetry_storage._tel_config._not_ready == 2) diff --git a/tests/models/test_splits.py b/tests/models/test_splits.py index d56e6f77..23688d9e 100644 --- a/tests/models/test_splits.py +++ b/tests/models/test_splits.py @@ -117,4 +117,5 @@ def test_to_split_view(self): assert as_split_view.killed == self.raw['killed'] assert as_split_view.traffic_type == self.raw['trafficTypeName'] assert set(as_split_view.treatments) == set(['on', 'off']) + assert as_split_view.default_treatment == self.raw['defaultTreatment'] assert sorted(as_split_view.sets) == sorted(list(self.raw['sets']))