From d9e8f83dbb5f0734de5ab98959d0334b230b250a Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 15:25:28 +0400 Subject: [PATCH 01/25] [FSSDK-11458] Python - Add SDK Multi-Region Support for Data Hosting --- optimizely/event/event_factory.py | 10 ++- optimizely/event/user_event.py | 4 +- optimizely/event/user_event_factory.py | 4 +- optimizely/event_builder.py | 16 ++++- optimizely/project_config.py | 7 ++- tests/test_config.py | 27 ++++++++- tests/test_optimizely.py | 84 ++++++++++++++++++++++++++ tests/test_user_event_factory.py | 17 ++++++ 8 files changed, 158 insertions(+), 11 deletions(-) diff --git a/optimizely/event/event_factory.py b/optimizely/event/event_factory.py index 8a4bb0cf8..3dbbb8163 100644 --- a/optimizely/event/event_factory.py +++ b/optimizely/event/event_factory.py @@ -42,7 +42,10 @@ class EventFactory: to record the events via the Optimizely Events API ("https://developers.optimizely.com/x/events/api/index.html") """ - EVENT_ENDPOINT: Final = 'https://logx.optimizely.com/v1/events' + EVENT_ENDPOINTS: Final = { + 'US': 'https://logx.optimizely.com/v1/events', + 'EU': 'https://eu.logx.optimizely.com/v1/events' + } HTTP_VERB: Final = 'POST' HTTP_HEADERS: Final = {'Content-Type': 'application/json'} ACTIVATE_EVENT_KEY: Final = 'campaign_activated' @@ -97,7 +100,10 @@ def create_log_event( event_params = event_batch.get_event_params() - return log_event.LogEvent(cls.EVENT_ENDPOINT, event_params, cls.HTTP_VERB, cls.HTTP_HEADERS) + region = user_context.region or 'US' + endpoint = cls.EVENT_ENDPOINTS.get(region) + + return log_event.LogEvent(endpoint, event_params, cls.HTTP_VERB, cls.HTTP_HEADERS) @classmethod def _create_visitor(cls, event: Optional[user_event.UserEvent], logger: Logger) -> Optional[payload.Visitor]: diff --git a/optimizely/event/user_event.py b/optimizely/event/user_event.py index 9cdb623a9..243234d3b 100644 --- a/optimizely/event/user_event.py +++ b/optimizely/event/user_event.py @@ -17,6 +17,7 @@ from sys import version_info from optimizely import version +from optimizely.project_config import Region if version_info < (3, 8): @@ -97,10 +98,11 @@ def __init__( class EventContext: """ Class respresenting User Event Context. """ - def __init__(self, account_id: str, project_id: str, revision: str, anonymize_ip: bool): + def __init__(self, account_id: str, project_id: str, revision: str, anonymize_ip: bool, region: Region): self.account_id = account_id self.project_id = project_id self.revision = revision self.client_name = CLIENT_NAME self.client_version = version.__version__ self.anonymize_ip = anonymize_ip + self.region = region or 'US' diff --git a/optimizely/event/user_event_factory.py b/optimizely/event/user_event_factory.py index ef07d06be..cd2791558 100644 --- a/optimizely/event/user_event_factory.py +++ b/optimizely/event/user_event_factory.py @@ -76,7 +76,7 @@ def create_impression_event( variation = project_config.get_variation_from_id_by_experiment_id(experiment_id, variation_id) event_context = user_event.EventContext( - project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, + project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, project_config.region ) return user_event.ImpressionEvent( @@ -115,7 +115,7 @@ def create_conversion_event( """ event_context = user_event.EventContext( - project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, + project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, project_config.region ) return user_event.ConversionEvent( diff --git a/optimizely/event_builder.py b/optimizely/event_builder.py index ecabf14c1..a243b94d3 100644 --- a/optimizely/event_builder.py +++ b/optimizely/event_builder.py @@ -54,7 +54,10 @@ class EventBuilder: """ Class which encapsulates methods to build events for tracking impressions and conversions using the new V3 event API (batch). """ - EVENTS_URL: Final = 'https://logx.optimizely.com/v1/events' + EVENTS_URLS: Final = { + 'US': 'https://logx.optimizely.com/v1/events', + 'EU': 'https://eu.logx.optimizely.com/v1/events' + } HTTP_VERB: Final = 'POST' HTTP_HEADERS: Final = {'Content-Type': 'application/json'} @@ -266,7 +269,10 @@ def create_impression_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(impression_params) - return Event(self.EVENTS_URL, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) + region = project_config.region or 'US' + events_url = self.EVENTS_URLS.get(region) + + return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) def create_conversion_event( self, project_config: ProjectConfig, event_key: str, @@ -289,4 +295,8 @@ def create_conversion_event( conversion_params = self._get_required_params_for_conversion(project_config, event_key, event_tags) params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(conversion_params) - return Event(self.EVENTS_URL, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) + + region = project_config.region or 'US' + events_url = self.EVENTS_URLS.get(region) + + return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index f774ff8a6..d13b28dd0 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -22,9 +22,9 @@ from .helpers import types if version_info < (3, 8): - from typing_extensions import Final + from typing_extensions import Final, Literal else: - from typing import Final # type: ignore + from typing import Final, Literal # type: ignore if TYPE_CHECKING: # prevent circular dependenacy by skipping import at runtime @@ -41,6 +41,8 @@ EntityClass = TypeVar('EntityClass') +Region = Literal['US', 'EU'] + class ProjectConfig: """ Representation of the Optimizely project config. """ @@ -84,6 +86,7 @@ def __init__(self, datafile: str | bytes, logger: Logger, error_handler: Any): self.public_key_for_odp: Optional[str] = None self.host_for_odp: Optional[str] = None self.all_segments: list[str] = [] + self.region: Region = config.get('region') or 'US' # Utility maps for quick lookup self.group_id_map: dict[str, entities.Group] = self._generate_key_map(self.groups, 'id', entities.Group) diff --git a/tests/test_config.py b/tests/test_config.py index 9ec5c7614..265b69044 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -21,7 +21,7 @@ from optimizely import logger from optimizely import optimizely from optimizely.helpers import enums -from optimizely.project_config import ProjectConfig +from optimizely.project_config import ProjectConfig, Region from . import base @@ -154,6 +154,31 @@ def test_init(self): self.assertEqual(expected_variation_key_map, self.project_config.variation_key_map) self.assertEqual(expected_variation_id_map, self.project_config.variation_id_map) + def test_region_when_no_region(self): + """ Test that region defaults to 'US' when not specified in the config. """ + config_dict = copy.deepcopy(self.config_dict_with_multiple_experiments) + opt_obj = optimizely.Optimizely(json.dumps(config_dict)) + project_config = opt_obj.config_manager.get_config() + self.assertEqual(project_config.region, Region.US) + + + def test_region_when_specified_in_datafile(self): + """ Test that region is set to 'US' when specified in the config. """ + config_dict_us = copy.deepcopy(self.config_dict_with_multiple_experiments) + config_dict_us['region'] = 'US' + opt_obj_us = optimizely.Optimizely(json.dumps(config_dict_us)) + project_config_us = opt_obj_us.config_manager.get_config() + self.assertEqual(project_config_us.region, Region.US) + + """ Test that region is set to 'EU' when specified in the config. """ + config_dict_eu = copy.deepcopy(self.config_dict_with_multiple_experiments) + config_dict_eu['region'] = 'EU' + opt_obj_eu = optimizely.Optimizely(json.dumps(config_dict_eu)) + project_config_eu = opt_obj_eu.config_manager.get_config() + self.assertEqual(project_config_eu.region, Region.EU) + + + def test_cmab_field_population(self): """ Test that the cmab field is populated correctly in experiments.""" diff --git a/tests/test_optimizely.py b/tests/test_optimizely.py index 1f4293cdd..2c9caa874 100644 --- a/tests/test_optimizely.py +++ b/tests/test_optimizely.py @@ -365,6 +365,7 @@ def test_activate(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -385,6 +386,76 @@ def test_activate(self): {'Content-Type': 'application/json'}, ) + def test_activate_with_eu_hosting(self): + """ Test that activate calls process with right params and returns expected variation. """ + """ Test EU hosting for activate method. """ + + with mock.patch( + 'optimizely.decision_service.DecisionService.get_variation', + return_value=(self.project_config.get_variation_from_id('test_experiment', '111129'), []), + ) as mock_decision, mock.patch('time.time', return_value=42), mock.patch( + 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' + ), mock.patch( + 'optimizely.event.event_processor.BatchEventProcessor.process' + ) as mock_process: + self.assertEqual('variation', self.optimizely.activate('test_experiment', 'test_user')) + + expected_params = { + 'account_id': '12001', + 'project_id': '111001', + 'visitors': [ + { + 'visitor_id': 'test_user', + 'attributes': [], + 'snapshots': [ + { + 'decisions': [ + {'variation_id': '111129', 'experiment_id': '111127', 'campaign_id': '111182', + 'metadata': {'flag_key': '', + 'rule_key': 'test_experiment', + 'rule_type': 'experiment', + 'variation_key': 'variation', + 'enabled': True}, + } + ], + 'events': [ + { + 'timestamp': 42000, + 'entity_id': '111182', + 'uuid': 'a68cf1ad-0393-4e18-af87-efe8f01a7c9c', + 'key': 'campaign_activated', + } + ], + } + ], + } + ], + 'client_version': version.__version__, + 'client_name': 'python-sdk', + 'enrich_decisions': True, + 'anonymize_ip': False, + 'revision': '42', + 'region': 'EU', + } + + log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) + user_context = mock_decision.call_args[0][2] + user_profile_tracker = mock_decision.call_args[0][3] + + mock_decision.assert_called_once_with( + self.project_config, self.project_config.get_experiment_from_key('test_experiment'), + user_context, user_profile_tracker + ) + self.assertEqual(1, mock_process.call_count) + + self._validate_event_object( + log_event.__dict__, + 'https://eu.logx.optimizely.com/v1/events', + expected_params, + 'POST', + {'Content-Type': 'application/json'}, + ) + def test_add_activate_remove_clear_listener(self): callbackhit = [False] """ Test adding a listener activate passes correctly and gets called""" @@ -764,6 +835,7 @@ def test_activate__with_attributes__audience_match(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -848,6 +920,7 @@ def test_activate__with_attributes_of_different_types(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1044,6 +1117,7 @@ def test_activate__with_attributes__audience_match__forced_bucketing(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1120,6 +1194,7 @@ def test_activate__with_attributes__audience_match__bucketing_id_provided(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1288,6 +1363,7 @@ def test_track__with_attributes(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1424,6 +1500,7 @@ def test_track__with_attributes__bucketing_id_provided(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1504,6 +1581,7 @@ def test_track__with_event_tags(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1560,6 +1638,7 @@ def test_track__with_event_tags_revenue(self): 'account_id': '12001', 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1648,6 +1727,7 @@ def test_track__with_event_tags__forced_bucketing(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -1703,6 +1783,7 @@ def test_track__with_invalid_event_tags(self): 'account_id': '12001', 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -2103,6 +2184,7 @@ def test_is_feature_enabled__returns_true_for_feature_experiment_if_feature_enab 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '1', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -2204,6 +2286,7 @@ def test_is_feature_enabled__returns_false_for_feature_experiment_if_feature_dis 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '1', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) @@ -2356,6 +2439,7 @@ def test_is_feature_enabled__returns_true_for_feature_rollout_if_feature_enabled 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '1', + 'region': 'US', } log_event = EventFactory.create_log_event(mock_process.call_args[0][0], self.optimizely.logger) diff --git a/tests/test_user_event_factory.py b/tests/test_user_event_factory.py index 009ef05dd..f5bb2f8ea 100644 --- a/tests/test_user_event_factory.py +++ b/tests/test_user_event_factory.py @@ -41,6 +41,20 @@ def test_impression_event(self): self.assertEqual(experiment, impression_event.experiment) self.assertEqual(variation, impression_event.variation) self.assertEqual(user_id, impression_event.user_id) + self.assertEqual(self.project_config.region, impression_event.event_context.region) + + def test_impression_event_with_region_eu(self): + project_config = self.project_config + experiment = self.project_config.get_experiment_from_key('test_experiment') + user_id = 'test_user' + + impression_event = UserEventFactory.create_impression_event( + project_config, experiment, '111128', '', 'rule_key', 'rule_type', True, user_id, None, region='EU' + ) + + self.assertEqual(self.project_config.region, impression_event.event_context.region) + self.assertEqual('EU', impression_event.event_context.region) + def test_impression_event__with_attributes(self): project_config = self.project_config @@ -66,6 +80,7 @@ def test_impression_event__with_attributes(self): self.assertEqual(experiment, impression_event.experiment) self.assertEqual(variation, impression_event.variation) self.assertEqual(user_id, impression_event.user_id) + self.assertEqual(self.project_config.region, impression_event.event_context.region) self.assertEqual( [x.__dict__ for x in expected_attrs], [x.__dict__ for x in impression_event.visitor_attributes], ) @@ -91,6 +106,7 @@ def test_conversion_event(self): self.assertEqual(self.project_config.bot_filtering, conversion_event.bot_filtering) self.assertEqual(self.project_config.get_event(event_key), conversion_event.event) self.assertEqual(user_id, conversion_event.user_id) + self.assertEqual(self.project_config.region, conversion_event.event_context.region) self.assertEqual( [x.__dict__ for x in expected_attrs], [x.__dict__ for x in conversion_event.visitor_attributes], ) @@ -117,6 +133,7 @@ def test_conversion_event__with_event_tags(self): self.assertEqual(self.project_config.bot_filtering, conversion_event.bot_filtering) self.assertEqual(self.project_config.get_event(event_key), conversion_event.event) self.assertEqual(user_id, conversion_event.user_id) + self.assertEqual(self.project_config.region, conversion_event.event_context.region) self.assertEqual( [x.__dict__ for x in expected_attrs], [x.__dict__ for x in conversion_event.visitor_attributes], ) From 08669627c058d2e59f29582863b9958e74af851f Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 15:30:28 +0400 Subject: [PATCH 02/25] Fix lint issues --- optimizely/event/user_event_factory.py | 12 ++++++++++-- tests/test_config.py | 3 --- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/optimizely/event/user_event_factory.py b/optimizely/event/user_event_factory.py index cd2791558..a15d8f578 100644 --- a/optimizely/event/user_event_factory.py +++ b/optimizely/event/user_event_factory.py @@ -76,7 +76,11 @@ def create_impression_event( variation = project_config.get_variation_from_id_by_experiment_id(experiment_id, variation_id) event_context = user_event.EventContext( - project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, project_config.region + project_config.account_id, + project_config.project_id, + project_config.revision, + project_config.anonymize_ip, + project_config.region ) return user_event.ImpressionEvent( @@ -115,7 +119,11 @@ def create_conversion_event( """ event_context = user_event.EventContext( - project_config.account_id, project_config.project_id, project_config.revision, project_config.anonymize_ip, project_config.region + project_config.account_id, + project_config.project_id, + project_config.revision, + project_config.anonymize_ip, + project_config.region ) return user_event.ConversionEvent( diff --git a/tests/test_config.py b/tests/test_config.py index 265b69044..2d7fff5fd 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -161,7 +161,6 @@ def test_region_when_no_region(self): project_config = opt_obj.config_manager.get_config() self.assertEqual(project_config.region, Region.US) - def test_region_when_specified_in_datafile(self): """ Test that region is set to 'US' when specified in the config. """ config_dict_us = copy.deepcopy(self.config_dict_with_multiple_experiments) @@ -177,8 +176,6 @@ def test_region_when_specified_in_datafile(self): project_config_eu = opt_obj_eu.config_manager.get_config() self.assertEqual(project_config_eu.region, Region.EU) - - def test_cmab_field_population(self): """ Test that the cmab field is populated correctly in experiments.""" From 5a0e19dd0d7783be6dd04c014d02e0e6a5597553 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 15:30:52 +0400 Subject: [PATCH 03/25] Fix lint issue --- tests/test_user_event_factory.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_user_event_factory.py b/tests/test_user_event_factory.py index f5bb2f8ea..4b9947277 100644 --- a/tests/test_user_event_factory.py +++ b/tests/test_user_event_factory.py @@ -55,7 +55,6 @@ def test_impression_event_with_region_eu(self): self.assertEqual(self.project_config.region, impression_event.event_context.region) self.assertEqual('EU', impression_event.event_context.region) - def test_impression_event__with_attributes(self): project_config = self.project_config experiment = self.project_config.get_experiment_from_key('test_experiment') From 730fede7d93401c80203dc175b942a5542fb574a Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 15:43:34 +0400 Subject: [PATCH 04/25] Fix errors --- optimizely/event/event_factory.py | 2 +- optimizely/event_builder.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/optimizely/event/event_factory.py b/optimizely/event/event_factory.py index 3dbbb8163..e2fa35316 100644 --- a/optimizely/event/event_factory.py +++ b/optimizely/event/event_factory.py @@ -101,7 +101,7 @@ def create_log_event( event_params = event_batch.get_event_params() region = user_context.region or 'US' - endpoint = cls.EVENT_ENDPOINTS.get(region) + endpoint = cls.EVENT_ENDPOINTS.get(region, cls.EVENT_ENDPOINTS['US']) return log_event.LogEvent(endpoint, event_params, cls.HTTP_VERB, cls.HTTP_HEADERS) diff --git a/optimizely/event_builder.py b/optimizely/event_builder.py index a243b94d3..383e44530 100644 --- a/optimizely/event_builder.py +++ b/optimizely/event_builder.py @@ -270,7 +270,7 @@ def create_impression_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(impression_params) region = project_config.region or 'US' - events_url = self.EVENTS_URLS.get(region) + events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) @@ -297,6 +297,6 @@ def create_conversion_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(conversion_params) region = project_config.region or 'US' - events_url = self.EVENTS_URLS.get(region) + events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) From 47ccb94c9540db3f305452bf03c91f12cb1d0bd1 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 15:53:32 +0400 Subject: [PATCH 05/25] Add region on base test --- tests/base.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/base.py b/tests/base.py index 875a26e69..63344d4aa 100644 --- a/tests/base.py +++ b/tests/base.py @@ -57,6 +57,7 @@ def fake_server_response(self, status_code: Optional[int] = None, def setUp(self, config_dict='config_dict'): self.config_dict = { + 'region': 'US', 'revision': '42', 'sdkKey': 'basic-test', 'version': '2', @@ -150,6 +151,7 @@ def setUp(self, config_dict='config_dict'): # datafile version 4 self.config_dict_with_features = { + 'region': 'US', 'revision': '1', 'sdkKey': 'features-test', 'accountId': '12001', @@ -553,6 +555,7 @@ def setUp(self, config_dict='config_dict'): } self.config_dict_with_multiple_experiments = { + 'region': 'US', 'revision': '42', 'sdkKey': 'multiple-experiments', 'version': '2', @@ -686,6 +689,7 @@ def setUp(self, config_dict='config_dict'): 'accountId': '10367498574', 'events': [{'experimentIds': ['10420810910'], 'id': '10404198134', 'key': 'winning'}], 'revision': '1337', + 'region': 'US', } self.config_dict_with_typed_audiences = { @@ -1078,6 +1082,7 @@ def setUp(self, config_dict='config_dict'): ], 'revision': '3', 'sdkKey': 'typed-audiences', + 'region': 'US', } self.config_dict_with_audience_segments = { @@ -1274,7 +1279,8 @@ def setUp(self, config_dict='config_dict'): } ], 'revision': '101', - 'sdkKey': 'segments-test' + 'sdkKey': 'segments-test', + 'region': 'US', } config = getattr(self, config_dict) From a7d74acccee7a5b6c2c6439feda6215e3273fe2b Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 16:34:39 +0400 Subject: [PATCH 06/25] Update Region as enum --- optimizely/project_config.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index d13b28dd0..e6f676c5f 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -22,9 +22,9 @@ from .helpers import types if version_info < (3, 8): - from typing_extensions import Final, Literal + from typing_extensions import Final else: - from typing import Final, Literal # type: ignore + from typing import Final # type: ignore if TYPE_CHECKING: # prevent circular dependenacy by skipping import at runtime @@ -41,8 +41,9 @@ EntityClass = TypeVar('EntityClass') -Region = Literal['US', 'EU'] - +class Region(str, enums): + US = 'US' + EU = 'EU' class ProjectConfig: """ Representation of the Optimizely project config. """ From 8a65e0fe793a80f44ac27588f900a6e54ea7369a Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 16:39:52 +0400 Subject: [PATCH 07/25] Delete blank lines --- optimizely/project_config.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index e6f676c5f..b17d34e43 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -40,11 +40,9 @@ RESERVED_ATTRIBUTE_PREFIX: Final = '$opt_' EntityClass = TypeVar('EntityClass') - class Region(str, enums): US = 'US' EU = 'EU' - class ProjectConfig: """ Representation of the Optimizely project config. """ From 24d2fcd6d0e6a104e95d9928b7e7cbc5dae04f05 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 16:41:39 +0400 Subject: [PATCH 08/25] Fix lint issue --- optimizely/project_config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index b17d34e43..e6f676c5f 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -40,9 +40,11 @@ RESERVED_ATTRIBUTE_PREFIX: Final = '$opt_' EntityClass = TypeVar('EntityClass') + class Region(str, enums): US = 'US' EU = 'EU' + class ProjectConfig: """ Representation of the Optimizely project config. """ From ba5beee4fb5f79770c9c232f3b772a58f038110d Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:21:59 +0400 Subject: [PATCH 09/25] Fix lint issue --- optimizely/project_config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index e6f676c5f..8400068b8 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -41,10 +41,12 @@ EntityClass = TypeVar('EntityClass') + class Region(str, enums): US = 'US' EU = 'EU' + class ProjectConfig: """ Representation of the Optimizely project config. """ From 17c9280e281546ce1a732dd216de79dcc3b0b6d1 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:26:16 +0400 Subject: [PATCH 10/25] Fix test errors --- optimizely/project_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index 8400068b8..d46a57164 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -42,7 +42,7 @@ EntityClass = TypeVar('EntityClass') -class Region(str, enums): +class Region: US = 'US' EU = 'EU' From 155ab2545bb23a9521ec75a2850a7d0d12027ebf Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:32:30 +0400 Subject: [PATCH 11/25] Add enum --- optimizely/project_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index d46a57164..9ff054179 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -14,6 +14,7 @@ import json from typing import TYPE_CHECKING, Optional, Type, TypeVar, cast, Any, Iterable, List from sys import version_info +from enum import Enum from . import entities from . import exceptions @@ -42,7 +43,7 @@ EntityClass = TypeVar('EntityClass') -class Region: +class Region(str, Enum): US = 'US' EU = 'EU' From ba049b6df1b4ec63e97fb9516acb884a581dce6c Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:36:02 +0400 Subject: [PATCH 12/25] Fix region value --- optimizely/project_config.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index 9ff054179..58f123de5 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -90,7 +90,12 @@ def __init__(self, datafile: str | bytes, logger: Logger, error_handler: Any): self.public_key_for_odp: Optional[str] = None self.host_for_odp: Optional[str] = None self.all_segments: list[str] = [] - self.region: Region = config.get('region') or 'US' + + region_value = config.get('region') + if region_value == Region.EU.value: + self.region: Region = Region.EU + else: + self.region: Region = Region.US # Utility maps for quick lookup self.group_id_map: dict[str, entities.Group] = self._generate_key_map(self.groups, 'id', entities.Group) From a777fa0e0e8206f98fb389a0d28b628292d4e250 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:38:05 +0400 Subject: [PATCH 13/25] Fix type issue --- optimizely/project_config.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/optimizely/project_config.py b/optimizely/project_config.py index 58f123de5..bfbf7ca5d 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -92,10 +92,11 @@ def __init__(self, datafile: str | bytes, logger: Logger, error_handler: Any): self.all_segments: list[str] = [] region_value = config.get('region') + self.region: Region if region_value == Region.EU.value: - self.region: Region = Region.EU + self.region = Region.EU else: - self.region: Region = Region.US + self.region = Region.US # Utility maps for quick lookup self.group_id_map: dict[str, entities.Group] = self._generate_key_map(self.groups, 'id', entities.Group) From c1f16938914c669ece074276356d82ba0d2b07ef Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 17:45:31 +0400 Subject: [PATCH 14/25] Correct the event url --- tests/test_event_builder.py | 35 +++++++++++++++++++++-------------- tests/test_event_factory.py | 7 +++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/tests/test_event_builder.py b/tests/test_event_builder.py index fb4d7a0d3..818b939b2 100644 --- a/tests/test_event_builder.py +++ b/tests/test_event_builder.py @@ -100,7 +100,7 @@ def test_create_impression_event(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -155,7 +155,7 @@ def test_create_impression_event__with_attributes(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -208,7 +208,7 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -280,7 +280,7 @@ def side_effect(*args, **kwargs): self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -345,7 +345,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -409,7 +409,7 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -479,7 +479,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -515,6 +515,7 @@ def test_create_conversion_event(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -525,7 +526,7 @@ def test_create_conversion_event(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -563,6 +564,7 @@ def test_create_conversion_event__with_attributes(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -573,7 +575,7 @@ def test_create_conversion_event__with_attributes(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -618,6 +620,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -631,7 +634,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -681,6 +684,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -694,7 +698,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -735,6 +739,7 @@ def test_create_conversion_event__with_event_tags(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -749,7 +754,7 @@ def test_create_conversion_event__with_event_tags(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -788,6 +793,7 @@ def test_create_conversion_event__with_invalid_event_tags(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -802,7 +808,7 @@ def test_create_conversion_event__with_invalid_event_tags(self): ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, @@ -843,6 +849,7 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -857,7 +864,7 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel ) self._validate_event_object( event_obj, - event_builder.EventBuilder.EVENTS_URL, + event_builder.EventBuilder.EVENTS_URLS.get('US'), expected_params, event_builder.EventBuilder.HTTP_VERB, event_builder.EventBuilder.HTTP_HEADERS, diff --git a/tests/test_event_factory.py b/tests/test_event_factory.py index adbebd35c..781bffe3e 100644 --- a/tests/test_event_factory.py +++ b/tests/test_event_factory.py @@ -582,6 +582,7 @@ def test_create_conversion_event(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -629,6 +630,7 @@ def test_create_conversion_event__with_attributes(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -683,6 +685,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -744,6 +747,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -796,6 +800,7 @@ def test_create_conversion_event__with_event_tags(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -848,6 +853,7 @@ def test_create_conversion_event__with_invalid_event_tags(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -902,6 +908,7 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( From 6de08895c6a1a3cca13f0d1539d1336966d80819 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 18:05:08 +0400 Subject: [PATCH 15/25] Add region in params --- optimizely/event_builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/optimizely/event_builder.py b/optimizely/event_builder.py index 383e44530..04b6ec97a 100644 --- a/optimizely/event_builder.py +++ b/optimizely/event_builder.py @@ -269,6 +269,8 @@ def create_impression_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(impression_params) + params['region'] = str(project_config.region) + region = project_config.region or 'US' events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) @@ -296,6 +298,8 @@ def create_conversion_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(conversion_params) + params['region'] = str(project_config.region) + region = project_config.region or 'US' events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) From 83afabe45060364260784238e54af4dac1b32d49 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 18:45:38 +0400 Subject: [PATCH 16/25] Fix region param --- optimizely/event_builder.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/optimizely/event_builder.py b/optimizely/event_builder.py index 04b6ec97a..b3ea39c28 100644 --- a/optimizely/event_builder.py +++ b/optimizely/event_builder.py @@ -269,10 +269,10 @@ def create_impression_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(impression_params) - params['region'] = str(project_config.region) + params['region'] = project_config.region.value region = project_config.region or 'US' - events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) + events_url = self.EVENTS_URLS.get(str(region), self.EVENTS_URLS['US']) return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) @@ -298,9 +298,9 @@ def create_conversion_event( params[self.EventParams.USERS][0][self.EventParams.SNAPSHOTS].append(conversion_params) - params['region'] = str(project_config.region) + params['region'] = project_config.region.value region = project_config.region or 'US' - events_url = self.EVENTS_URLS.get(region, self.EVENTS_URLS['US']) + events_url = self.EVENTS_URLS.get(str(region), self.EVENTS_URLS['US']) return Event(events_url, params, http_verb=self.HTTP_VERB, headers=self.HTTP_HEADERS) From 158aab3b1f1633ed80bdd6e6edf27ffa61e69d1a Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 18:49:16 +0400 Subject: [PATCH 17/25] Add region to create --- optimizely/event_builder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/optimizely/event_builder.py b/optimizely/event_builder.py index b3ea39c28..eb80bdd05 100644 --- a/optimizely/event_builder.py +++ b/optimizely/event_builder.py @@ -249,7 +249,8 @@ def _get_required_params_for_conversion( def create_impression_event( self, project_config: ProjectConfig, experiment: Experiment, - variation_id: str, user_id: str, attributes: UserAttributes + variation_id: str, user_id: str, attributes: UserAttributes, + region: str = 'US' ) -> Event: """ Create impression Event to be sent to the logging endpoint. @@ -278,7 +279,8 @@ def create_impression_event( def create_conversion_event( self, project_config: ProjectConfig, event_key: str, - user_id: str, attributes: UserAttributes, event_tags: event_tag_utils.EventTags + user_id: str, attributes: UserAttributes, event_tags: event_tag_utils.EventTags, + region: str = 'US' ) -> Event: """ Create conversion Event to be sent to the logging endpoint. From 0a0cdefe688db3465f15afa2e72d1f962659fded Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 18:58:15 +0400 Subject: [PATCH 18/25] Fix test cases --- tests/test_event_builder.py | 7 +++++++ tests/test_user_event_factory.py | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_event_builder.py b/tests/test_event_builder.py index 818b939b2..31cf32cdf 100644 --- a/tests/test_event_builder.py +++ b/tests/test_event_builder.py @@ -86,6 +86,7 @@ def test_create_impression_event(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -141,6 +142,7 @@ def test_create_impression_event__with_attributes(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -194,6 +196,7 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -250,6 +253,7 @@ def test_create_impression_event_calls_is_attribute_valid(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } def side_effect(*args, **kwargs): @@ -328,6 +332,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -392,6 +397,7 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -462,6 +468,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( diff --git a/tests/test_user_event_factory.py b/tests/test_user_event_factory.py index 4b9947277..4e4d17d1f 100644 --- a/tests/test_user_event_factory.py +++ b/tests/test_user_event_factory.py @@ -48,8 +48,10 @@ def test_impression_event_with_region_eu(self): experiment = self.project_config.get_experiment_from_key('test_experiment') user_id = 'test_user' + project_config.region = 'EU' + impression_event = UserEventFactory.create_impression_event( - project_config, experiment, '111128', '', 'rule_key', 'rule_type', True, user_id, None, region='EU' + project_config, experiment, '111128', '', 'rule_key', 'rule_type', True, user_id, None ) self.assertEqual(self.project_config.region, impression_event.event_context.region) From f68d67800feffd61f1277003b1f5b43ec8cd05bf Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 19:05:50 +0400 Subject: [PATCH 19/25] Fix test cases --- tests/test_event_factory.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/test_event_factory.py b/tests/test_event_factory.py index 781bffe3e..ebcfb9709 100644 --- a/tests/test_event_factory.py +++ b/tests/test_event_factory.py @@ -118,7 +118,7 @@ def test_create_impression_event(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_attributes(self): @@ -182,7 +182,7 @@ def test_create_impression_event__with_attributes(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_impression_event_when_attribute_is_not_in_datafile(self): @@ -244,7 +244,7 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_impression_event_calls_is_attribute_valid(self): @@ -323,7 +323,7 @@ def side_effect(*args, **kwargs): self._validate_event_object( log_event, - EventFactory.EVENT_ENDPOINT, + EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, @@ -399,7 +399,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_enabled(self,): @@ -471,7 +471,7 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled(self,): @@ -549,7 +549,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event(self): @@ -595,7 +595,7 @@ def test_create_conversion_event(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_attributes(self): @@ -643,7 +643,7 @@ def test_create_conversion_event__with_attributes(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled(self,): @@ -700,7 +700,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled(self,): @@ -762,7 +762,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_event_tags(self): @@ -817,7 +817,7 @@ def test_create_conversion_event__with_event_tags(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_invalid_event_tags(self): @@ -870,7 +870,7 @@ def test_create_conversion_event__with_invalid_event_tags(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__when_event_is_used_in_multiple_experiments(self): @@ -925,5 +925,5 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINT, expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, ) From 81cd042f36d2fa91da554c35358af12fa3166897 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 19:11:32 +0400 Subject: [PATCH 20/25] Fix lint --- tests/test_event_factory.py | 78 ++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/tests/test_event_factory.py b/tests/test_event_factory.py index ebcfb9709..da58c4cb1 100644 --- a/tests/test_event_factory.py +++ b/tests/test_event_factory.py @@ -118,7 +118,11 @@ def test_create_impression_event(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_attributes(self): @@ -182,7 +186,11 @@ def test_create_impression_event__with_attributes(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_impression_event_when_attribute_is_not_in_datafile(self): @@ -244,7 +252,11 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_impression_event_calls_is_attribute_valid(self): @@ -399,7 +411,11 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_enabled(self,): @@ -471,7 +487,11 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled(self,): @@ -549,7 +569,11 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event(self): @@ -595,7 +619,11 @@ def test_create_conversion_event(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_attributes(self): @@ -643,7 +671,11 @@ def test_create_conversion_event__with_attributes(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled(self,): @@ -700,7 +732,11 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled(self,): @@ -762,7 +798,11 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_event_tags(self): @@ -817,7 +857,11 @@ def test_create_conversion_event__with_event_tags(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__with_invalid_event_tags(self): @@ -870,7 +914,11 @@ def test_create_conversion_event__with_invalid_event_tags(self): log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) def test_create_conversion_event__when_event_is_used_in_multiple_experiments(self): @@ -925,5 +973,9 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel log_event = EventFactory.create_log_event(event_obj, self.logger) self._validate_event_object( - log_event, EventFactory.EVENT_ENDPOINTS.get('US'), expected_params, EventFactory.HTTP_VERB, EventFactory.HTTP_HEADERS, + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, ) From 9d2c892d8948be5d00d26bf6ef784638fa967d21 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Wed, 2 Jul 2025 19:46:17 +0400 Subject: [PATCH 21/25] Add region --- tests/test_event_factory.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_event_factory.py b/tests/test_event_factory.py index da58c4cb1..b4d02cac2 100644 --- a/tests/test_event_factory.py +++ b/tests/test_event_factory.py @@ -98,6 +98,7 @@ def test_create_impression_event(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -166,6 +167,7 @@ def test_create_impression_event__with_attributes(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -232,6 +234,7 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -299,6 +302,7 @@ def test_create_impression_event_calls_is_attribute_valid(self): 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } def side_effect(*args, **kwargs): @@ -389,6 +393,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -465,6 +470,7 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( @@ -547,6 +553,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled 'enrich_decisions': True, 'anonymize_ip': False, 'revision': '42', + 'region': 'US', } with mock.patch('time.time', return_value=42.123), mock.patch( From 3c1332f8862ff2aa3a858d86c1a4a1625c5598a1 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Fri, 4 Jul 2025 13:11:14 +0400 Subject: [PATCH 22/25] Fix test cases --- optimizely/event/event_factory.py | 1 + optimizely/event/payload.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/optimizely/event/event_factory.py b/optimizely/event/event_factory.py index e2fa35316..5e3683238 100644 --- a/optimizely/event/event_factory.py +++ b/optimizely/event/event_factory.py @@ -93,6 +93,7 @@ def create_log_event( user_context.client_name, user_context.client_version, user_context.anonymize_ip, + user_context.region, True, ) diff --git a/optimizely/event/payload.py b/optimizely/event/payload.py index ac6f35e42..369172308 100644 --- a/optimizely/event/payload.py +++ b/optimizely/event/payload.py @@ -34,6 +34,7 @@ def __init__( anonymize_ip: bool, enrich_decisions: bool = True, visitors: Optional[list[Visitor]] = None, + region: str = 'US' ): self.account_id = account_id self.project_id = project_id @@ -43,6 +44,7 @@ def __init__( self.anonymize_ip = anonymize_ip self.enrich_decisions = enrich_decisions self.visitors = visitors or [] + self.region = region def __eq__(self, other: object) -> bool: batch_obj = self.get_event_params() From 11523cf6f0c3f801412f38a810729c6e37da4a94 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Fri, 4 Jul 2025 13:15:54 +0400 Subject: [PATCH 23/25] Fix tests --- optimizely/event/event_factory.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/optimizely/event/event_factory.py b/optimizely/event/event_factory.py index 5e3683238..a906b78a6 100644 --- a/optimizely/event/event_factory.py +++ b/optimizely/event/event_factory.py @@ -86,6 +86,7 @@ def create_log_event( return None user_context = first_event.event_context + region_value = user_context.region.value if hasattr(user_context.region, 'value') else user_context.region event_batch = payload.EventBatch( user_context.account_id, user_context.project_id, @@ -93,7 +94,7 @@ def create_log_event( user_context.client_name, user_context.client_version, user_context.anonymize_ip, - user_context.region, + region_value, True, ) From 1af68db0b4e490c112589b8c515f9d30f4e450f1 Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Fri, 4 Jul 2025 13:19:57 +0400 Subject: [PATCH 24/25] Cast to string --- optimizely/event/event_factory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/optimizely/event/event_factory.py b/optimizely/event/event_factory.py index a906b78a6..66f50442f 100644 --- a/optimizely/event/event_factory.py +++ b/optimizely/event/event_factory.py @@ -102,8 +102,8 @@ def create_log_event( event_params = event_batch.get_event_params() - region = user_context.region or 'US' - endpoint = cls.EVENT_ENDPOINTS.get(region, cls.EVENT_ENDPOINTS['US']) + region_str = user_context.region.value if hasattr(user_context.region, 'value') else str(user_context.region) + endpoint = cls.EVENT_ENDPOINTS.get(region_str, cls.EVENT_ENDPOINTS['US']) return log_event.LogEvent(endpoint, event_params, cls.HTTP_VERB, cls.HTTP_HEADERS) From 7a09f1d8910eebba1ce4510d6a476106927911de Mon Sep 17 00:00:00 2001 From: esrakartalOpt Date: Fri, 4 Jul 2025 15:01:11 +0400 Subject: [PATCH 25/25] Fix tests --- tests/test_event_builder.py | 16 +++++++--- tests/test_event_factory.py | 62 ++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/tests/test_event_builder.py b/tests/test_event_builder.py index 31cf32cdf..593d084c8 100644 --- a/tests/test_event_builder.py +++ b/tests/test_event_builder.py @@ -208,6 +208,7 @@ def test_create_impression_event_when_attribute_is_not_in_datafile(self): '111129', 'test_user', {'do_you_know_me': 'test_value'}, + 'US' ) self._validate_event_object( event_obj, @@ -280,6 +281,7 @@ def side_effect(*args, **kwargs): '111129', 'test_user', attributes, + 'US', ) self._validate_event_object( @@ -346,6 +348,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled( '111129', 'test_user', {'$opt_user_agent': 'Edge'}, + 'US' ) self._validate_event_object( @@ -411,6 +414,7 @@ def test_create_impression_event__with_empty_attributes_when_bot_filtering_is_en '111129', 'test_user', None, + 'US' ) self._validate_event_object( @@ -482,6 +486,7 @@ def test_create_impression_event__with_user_agent_when_bot_filtering_is_disabled '111129', 'test_user', {'$opt_user_agent': 'Chrome'}, + 'US' ) self._validate_event_object( @@ -529,7 +534,7 @@ def test_create_conversion_event(self): 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' ): event_obj = self.event_builder.create_conversion_event( - self.project_config, 'test_event', 'test_user', None, None + self.project_config, 'test_event', 'test_user', None, None, 'US' ) self._validate_event_object( event_obj, @@ -578,7 +583,7 @@ def test_create_conversion_event__with_attributes(self): 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' ): event_obj = self.event_builder.create_conversion_event( - self.project_config, 'test_event', 'test_user', {'test_attribute': 'test_value'}, None, + self.project_config, 'test_event', 'test_user', {'test_attribute': 'test_value'}, None, 'US' ) self._validate_event_object( event_obj, @@ -636,7 +641,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_enabled( 'optimizely.project_config.ProjectConfig.get_bot_filtering_value', return_value=True, ): event_obj = self.event_builder.create_conversion_event( - self.project_config, 'test_event', 'test_user', {'$opt_user_agent': 'Edge'}, None, + self.project_config, 'test_event', 'test_user', {'$opt_user_agent': 'Edge'}, None, 'US' ) self._validate_event_object( @@ -700,7 +705,7 @@ def test_create_conversion_event__with_user_agent_when_bot_filtering_is_disabled 'optimizely.project_config.ProjectConfig.get_bot_filtering_value', return_value=False, ): event_obj = self.event_builder.create_conversion_event( - self.project_config, 'test_event', 'test_user', {'$opt_user_agent': 'Chrome'}, None, + self.project_config, 'test_event', 'test_user', {'$opt_user_agent': 'Chrome'}, None, 'US' ) self._validate_event_object( @@ -758,6 +763,7 @@ def test_create_conversion_event__with_event_tags(self): 'test_user', {'test_attribute': 'test_value'}, {'revenue': 4200, 'value': 1.234, 'non-revenue': 'abc'}, + 'US' ) self._validate_event_object( event_obj, @@ -812,6 +818,7 @@ def test_create_conversion_event__with_invalid_event_tags(self): 'test_user', {'test_attribute': 'test_value'}, {'revenue': '4200', 'value': True, 'non-revenue': 'abc'}, + 'US' ) self._validate_event_object( event_obj, @@ -868,6 +875,7 @@ def test_create_conversion_event__when_event_is_used_in_multiple_experiments(sel 'test_user', {'test_attribute': 'test_value'}, {'revenue': 4200, 'value': 1.234, 'non-revenue': 'abc'}, + 'US' ) self._validate_event_object( event_obj, diff --git a/tests/test_event_factory.py b/tests/test_event_factory.py index b4d02cac2..fd73582a1 100644 --- a/tests/test_event_factory.py +++ b/tests/test_event_factory.py @@ -312,39 +312,39 @@ def side_effect(*args, **kwargs): return False - attributes = { - 'test_attribute': 'test_value', - 'boolean_key': True, - 'integer_key': 0, - 'double_key': 5.5, - } - - with mock.patch('time.time', return_value=42.123), mock.patch( - 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' - ), mock.patch( - 'optimizely.helpers.validator.is_attribute_valid', side_effect=side_effect, - ): - - event_obj = UserEventFactory.create_impression_event( - self.project_config, - self.project_config.get_experiment_from_key('test_experiment'), - '111129', - '', - 'experiment', - 'test_user', - attributes, - ) - - log_event = EventFactory.create_log_event(event_obj, self.logger) - - self._validate_event_object( - log_event, - EventFactory.EVENT_ENDPOINTS.get('US'), - expected_params, - EventFactory.HTTP_VERB, - EventFactory.HTTP_HEADERS, + attributes = { + 'test_attribute': 'test_value', + 'boolean_key': True, + 'integer_key': 0, + 'double_key': 5.5, + } + + with mock.patch('time.time', return_value=42.123), mock.patch( + 'uuid.uuid4', return_value='a68cf1ad-0393-4e18-af87-efe8f01a7c9c' + ), mock.patch( + 'optimizely.helpers.validator.is_attribute_valid', side_effect=side_effect, + ): + + event_obj = UserEventFactory.create_impression_event( + self.project_config, + self.project_config.get_experiment_from_key('test_experiment'), + '111129', + '', + 'experiment', + 'test_user', + attributes, ) + log_event = EventFactory.create_log_event(event_obj, self.logger) + + self._validate_event_object( + log_event, + EventFactory.EVENT_ENDPOINTS.get('US'), + expected_params, + EventFactory.HTTP_VERB, + EventFactory.HTTP_HEADERS, + ) + def test_create_impression_event__with_user_agent_when_bot_filtering_is_enabled(self,): """ Test that create_impression_event creates Event object with right params when user agent attribute is provided and