12
12
# limitations under the License.
13
13
14
14
from __future__ import annotations
15
- from typing import Any , Optional
15
+ from typing import Any , Optional , Union
16
16
from sys import version_info
17
17
from . import logger as _logging
18
18
from . import decision_service
19
-
19
+ from . helpers import enums
20
20
if version_info < (3 , 8 ):
21
21
from typing_extensions import Final
22
22
else :
@@ -46,7 +46,7 @@ class UserProfile:
46
46
def __init__ (
47
47
self ,
48
48
user_id : str ,
49
- experiment_bucket_map : Optional [dict [str , Decision ]] = None ,
49
+ experiment_bucket_map : Optional [dict [str , Union [ Decision , dict [ str , str ]] ]] = None ,
50
50
** kwargs : Any
51
51
):
52
52
self .user_id = user_id
@@ -64,8 +64,14 @@ def get_variation_for_experiment(self, experiment_id: str) -> Optional[str]:
64
64
Returns:
65
65
Variation ID corresponding to the experiment. None if no decision available.
66
66
"""
67
+ experiment_data = self .experiment_bucket_map .get (experiment_id )
68
+
69
+ if isinstance (experiment_data , decision_service .Decision ):
70
+ return experiment_data .variation .id if experiment_data .variation is not None else None
71
+ elif isinstance (experiment_data , dict ):
72
+ return experiment_data .get (self .VARIATION_ID_KEY )
67
73
68
- return self . experiment_bucket_map . get ( experiment_id , { self . VARIATION_ID_KEY : None }). get ( self . VARIATION_ID_KEY )
74
+ return None
69
75
70
76
def save_variation_for_experiment (self , experiment_id : str , variation_id : str ) -> None :
71
77
""" Helper method to save new experiment/variation as part of the user's profile.
@@ -74,7 +80,6 @@ def save_variation_for_experiment(self, experiment_id: str, variation_id: str) -
74
80
experiment_id: ID for experiment for which the decision is to be stored.
75
81
variation_id: ID for variation that the user saw.
76
82
"""
77
-
78
83
self .experiment_bucket_map .update ({experiment_id : {self .VARIATION_ID_KEY : variation_id }})
79
84
80
85
@@ -107,16 +112,18 @@ def __init__(self, user_id: str, user_profile_service: UserProfileService, logge
107
112
self .user_profile_service = user_profile_service
108
113
self .logger = _logging .adapt_logger (logger or _logging .NoOpLogger ())
109
114
self .profile_updated = False
110
- self .user_profile = None
115
+ self .user_profile = UserProfile ( user_id , {})
111
116
112
117
def get_user_profile (self ):
113
118
return self .user_profile
114
119
115
120
def load_user_profile (self , reasons : Optional [list [str ]]= [], error_handler : Optional [BaseErrorHandler ]= None ):
121
+ reasons = reasons if reasons else []
116
122
try :
117
123
user_profile = self .user_profile_service .lookup (self .user_id )
118
124
if user_profile is None :
119
- message = reasons .append ("Unable to get a user profile from the UserProfileService." )
125
+ message = "Unable to get a user profile from the UserProfileService."
126
+ reasons .append (message )
120
127
self .logger .info (message )
121
128
else :
122
129
if 'user_id' in user_profile and 'experiment_bucket_map' in user_profile :
@@ -130,7 +137,8 @@ def load_user_profile(self, reasons: Optional[list[str]]=[], error_handler: Opti
130
137
message = f"User profile is missing keys: { ', ' .join (missing_keys )} "
131
138
reasons .append (message )
132
139
except Exception as exception :
133
- message = reasons .append (str (exception ))
140
+ message = str (exception )
141
+ reasons .append (message )
134
142
self .logger .exception (f'Unable to retrieve user profile for user "{ self .user_id } "as lookup failed.' )
135
143
# Todo: add error handler
136
144
# error_handler.handle_error()
@@ -139,10 +147,14 @@ def load_user_profile(self, reasons: Optional[list[str]]=[], error_handler: Opti
139
147
self .user_profile = UserProfile (self .user_id , {})
140
148
141
149
def update_user_profile (self , experiment : Experiment , variation : Variation ):
142
- decision :Decision = None
143
150
if experiment .id in self .user_profile .experiment_bucket_map :
144
151
decision = self .user_profile .experiment_bucket_map [experiment .id ]
145
- decision .variation = variation
152
+ if isinstance (decision , decision_service .Decision ):
153
+ decision = decision_service .Decision (
154
+ experiment = decision .experiment ,
155
+ variation = variation ,
156
+ source = decision .source
157
+ )
146
158
else :
147
159
decision = decision_service .Decision (experiment = None , variation = variation , source = None )
148
160
@@ -154,9 +166,8 @@ def update_user_profile(self, experiment: Experiment, variation: Variation):
154
166
def save_user_profile (self , error_handler : Optional [BaseErrorHandler ] = None ):
155
167
if not self .profile_updated :
156
168
return
157
-
158
169
try :
159
- self .user_profile_service .save (self .user_profile )
170
+ self .user_profile_service .save (self .user_profile . __dict__ )
160
171
self .logger .info (f'Saved user profile of user "{ self .user_profile .user_id } ".' )
161
172
except Exception as exception :
162
173
self .logger .warning (f'Failed to save user profile of user "{ self .user_profile .user_id } ".' )
0 commit comments