Skip to content

Commit e65eb04

Browse files
Introduce user profile service interface (#52)
1 parent ea14b86 commit e65eb04

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

optimizely/optimizely.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,31 @@
3131
class Optimizely(object):
3232
""" Class encapsulating all SDK functionality. """
3333

34-
def __init__(self, datafile, event_dispatcher=None, logger=None, error_handler=None, skip_json_validation=False):
34+
def __init__(self,
35+
datafile,
36+
event_dispatcher=None,
37+
logger=None,
38+
error_handler=None,
39+
skip_json_validation=False,
40+
user_profile_service=None):
3541
""" Optimizely init method for managing Custom projects.
3642
3743
Args:
3844
datafile: JSON string representing the project.
3945
event_dispatcher: Provides a dispatch_event method which if given a URL and params sends a request to it.
40-
logger: Optional param which provides a log method to log messages. By default nothing would be logged.
41-
error_handler: Optional param which provides a handle_error method to handle exceptions.
46+
logger: Optional component which provides a log method to log messages. By default nothing would be logged.
47+
error_handler: Optional component which provides a handle_error method to handle exceptions.
4248
By default all exceptions will be suppressed.
4349
skip_json_validation: Optional boolean param which allows skipping JSON schema validation upon object invocation.
4450
By default JSON schema validation will be performed.
51+
user_profile_service: Optional component which provides methods to store and manage user profiles.
4552
"""
4653

4754
self.is_valid = True
4855
self.event_dispatcher = event_dispatcher or default_event_dispatcher
4956
self.logger = logger or noop_logger
5057
self.error_handler = error_handler or noop_error_handler
58+
self.user_profile_service = user_profile_service
5159

5260
try:
5361
self._validate_instantiation_options(datafile, skip_json_validation)
@@ -274,15 +282,17 @@ def get_variation(self, experiment_key, user_id, attributes=None):
274282

275283
experiment = self.config.get_experiment_from_key(experiment_key)
276284
if not experiment:
277-
self.logger.log(enums.LogLevels.INFO, 'Experiment key "%s" is invalid. Not activating user "%s".' % (experiment_key, user_id))
285+
self.logger.log(enums.LogLevels.INFO,
286+
'Experiment key "%s" is invalid. Not activating user "%s".' % (experiment_key,
287+
user_id))
278288
return None
279289

280290
if not self._validate_preconditions(experiment, attributes):
281291
return None
282292

283-
forcedVariation = self.bucketer.get_forced_variation(experiment, user_id)
284-
if forcedVariation:
285-
return forcedVariation.key
293+
forced_variation = self.bucketer.get_forced_variation(experiment, user_id)
294+
if forced_variation:
295+
return forced_variation.key
286296

287297
if not audience_helper.is_user_in_experiment(self.config, experiment, attributes):
288298
self.logger.log(

optimizely/user_profile.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2017, Optimizely
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
15+
class UserProfile(object):
16+
""" Class encapsulating information representing a user's profile.
17+
18+
user_id: User's identifier.
19+
experiment_bucket_map: Dict mapping experiment ID to dict consisting of the
20+
variation ID identifying the variation for the user.
21+
"""
22+
23+
def __init__(self, user_id, experiment_bucket_map=None, **kwargs):
24+
self.user_id = user_id
25+
self.experiment_bucket_map = experiment_bucket_map or {}
26+
27+
28+
class UserProfileService(object):
29+
""" Class encapsulating user profile service functionality.
30+
Override with your own implementation for storing and retrieving the user profile. """
31+
32+
def lookup(self, user_id):
33+
""" Fetch the user profile dict corresponding to the user ID.
34+
35+
Args:
36+
user_id: ID for user whose profile needs to be retrieved.
37+
38+
Returns:
39+
Dict representing the user's profile.
40+
"""
41+
return dict(UserProfile(user_id))
42+
43+
def save(self, user_profile):
44+
""" Save the user profile dict sent to this method.
45+
46+
Args:
47+
user_profile: Dict representing the user's profile.
48+
"""
49+
pass

0 commit comments

Comments
 (0)