Skip to content

Commit 0d54492

Browse files
Remove earlier feature flag parsing (#65)
1 parent de81f79 commit 0d54492

File tree

3 files changed

+6
-291
lines changed

3 files changed

+6
-291
lines changed

optimizely/entities.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,6 @@ def __init__(self, id, key, status, audienceIds, variations, forcedVariations,
5858
self.groupPolicy = groupPolicy
5959

6060

61-
class FeatureFlag(BaseEntity):
62-
63-
class Type(object):
64-
BOOLEAN = 'boolean'
65-
DOUBLE = 'double'
66-
INTEGER = 'integer'
67-
STRING = 'string'
68-
69-
70-
def __init__(self, id, key, type, defaultValue, **kwargs):
71-
self.id = id
72-
self.key = key
73-
self.type = type
74-
self.defaultValue = defaultValue
75-
76-
7761
class Group(BaseEntity):
7862

7963
def __init__(self, id, policy, experiments, trafficAllocation, **kwargs):
@@ -85,8 +69,6 @@ def __init__(self, id, policy, experiments, trafficAllocation, **kwargs):
8569

8670
class Variation(BaseEntity):
8771

88-
def __init__(self, id, key, variables=None, featureFlagMap=None, **kwargs):
72+
def __init__(self, id, key, **kwargs):
8973
self.id = id
9074
self.key = key
91-
self.variables = variables or []
92-
self.featureFlagMap = featureFlagMap or {}

optimizely/project_config.py

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,13 @@ def __init__(self, datafile, logger, error_handler):
5353
self.events = config.get('events', [])
5454
self.attributes = config.get('attributes', [])
5555
self.audiences = config.get('audiences', [])
56-
self.feature_flags = config.get('variables', [])
5756

5857
# Utility maps for quick lookup
5958
self.group_id_map = self._generate_key_map(self.groups, 'id', entities.Group)
6059
self.experiment_key_map = self._generate_key_map(self.experiments, 'key', entities.Experiment)
6160
self.event_key_map = self._generate_key_map(self.events, 'key', entities.Event)
6261
self.attribute_key_map = self._generate_key_map(self.attributes, 'key', entities.Attribute)
6362
self.audience_id_map = self._generate_key_map(self.audiences, 'id', entities.Audience)
64-
self.feature_flag_id_map = self._generate_key_map(self.feature_flags, 'id', entities.FeatureFlag)
6563
self.audience_id_map = self._deserialize_audience(self.audience_id_map)
6664
for group in self.group_id_map.values():
6765
experiments_in_group_key_map = self._generate_key_map(group.experiments, 'key', entities.Experiment)
@@ -82,8 +80,6 @@ def __init__(self, datafile, logger, error_handler):
8280
)
8381
self.variation_id_map[experiment.key] = {}
8482
for variation in self.variation_key_map.get(experiment.key).values():
85-
feature_flag_to_value_map = self._map_feature_flag_to_value(variation.variables, self.feature_flag_id_map)
86-
variation.featureFlagMap = feature_flag_to_value_map
8783
self.variation_id_map[experiment.key][variation.id] = variation
8884

8985
self.parsing_succeeded = True
@@ -127,46 +123,6 @@ def _deserialize_audience(audience_map):
127123

128124
return audience_map
129125

130-
def _get_typecast_value(self, value, type):
131-
""" Helper method to determine actual value based on type of feature flag.
132-
133-
Args:
134-
value: Value in string form as it was parsed from datafile.
135-
type: Type denoting the feature flag type.
136-
137-
Return:
138-
Value type-casted based on type of feature flag.
139-
"""
140-
141-
if type == entities.FeatureFlag.Type.BOOLEAN:
142-
return value == 'true'
143-
elif type == entities.FeatureFlag.Type.INTEGER:
144-
return int(value)
145-
elif type == entities.FeatureFlag.Type.DOUBLE:
146-
return float(value)
147-
else:
148-
return value
149-
150-
def _map_feature_flag_to_value(self, variables, feature_flag_id_map):
151-
""" Helper method to create map of feature flag key to associated value for a given variation's feature flag set.
152-
153-
Args:
154-
variables: List of dicts representing variables on an instance of Variation object.
155-
feature_flag_id_map: Dict mapping feature flag key to feature flag object.
156-
157-
Returns:
158-
Dict mapping values from feature flag key to value stored on the variation's variable.
159-
"""
160-
161-
feature_flag_value_map = {}
162-
for variable in variables:
163-
feature_flag = feature_flag_id_map[variable.get('id')]
164-
if not feature_flag:
165-
continue
166-
feature_flag_value_map[feature_flag.key] = self._get_typecast_value(variable.get('value'), feature_flag.type)
167-
168-
return feature_flag_value_map
169-
170126
def was_parsing_successful(self):
171127
""" Helper method to determine if parsing the datafile was successful.
172128

tests/test_config.py

Lines changed: 5 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ def test_init(self):
159159
self.assertEqual(expected_variation_key_map, self.project_config.variation_key_map)
160160
self.assertEqual(expected_variation_id_map, self.project_config.variation_id_map)
161161

162-
def test_init__with_v3_datafile(self):
163-
""" Test that on creating object, properties are initiated correctly for version 3 datafile. """
162+
def test_init__with_more_fields(self):
163+
""" Test that no issues occur on creating object with datafile consisting of more fields. """
164164

165165
# Adding some additional fields like live variables and IP anonymization
166166
config_dict = {
@@ -172,21 +172,6 @@ def test_init__with_v3_datafile(self):
172172
'key': 'is_working',
173173
'defaultValue': 'true',
174174
'type': 'boolean',
175-
}, {
176-
'id': '128',
177-
'key': 'environment',
178-
'defaultValue': 'devel',
179-
'type': 'string',
180-
}, {
181-
'id': '129',
182-
'key': 'number_of_days',
183-
'defaultValue': '192',
184-
'type': 'integer',
185-
}, {
186-
'id': '130',
187-
'key': 'significance_value',
188-
'defaultValue': '0.00098',
189-
'type': 'double',
190175
}],
191176
'events': [{
192177
'key': 'test_event',
@@ -245,29 +230,11 @@ def test_init__with_v3_datafile(self):
245230
'variations': [{
246231
'key': 'group_exp_1_control',
247232
'id': '28901',
248-
'variables': [{
249-
'id': '128',
250-
'value': 'prod'
251-
}, {
252-
'id': '129',
253-
'value': '1772'
254-
}, {
255-
'id': '130',
256-
'value': '1.22992'
257-
}]
233+
'variables': []
258234
}, {
259235
'key': 'group_exp_1_variation',
260236
'id': '28902',
261-
'variables': [{
262-
'id': '128',
263-
'value': 'stage'
264-
}, {
265-
'id': '129',
266-
'value': '112'
267-
}, {
268-
'id': '130',
269-
'value': '1.211'
270-
}]
237+
'variables': []
271238
}],
272239
'forcedVariations': {
273240
'user_1': 'group_exp_1_control',
@@ -330,197 +297,7 @@ def test_init__with_v3_datafile(self):
330297
}
331298

332299
test_obj = optimizely.Optimizely(json.dumps(config_dict))
333-
project_config = test_obj.config
334-
self.assertEqual(config_dict['accountId'], project_config.account_id)
335-
self.assertEqual(config_dict['projectId'], project_config.project_id)
336-
self.assertEqual(config_dict['revision'], project_config.revision)
337-
self.assertEqual(config_dict['experiments'], project_config.experiments)
338-
self.assertEqual(config_dict['events'], project_config.events)
339-
self.assertEqual(config_dict['variables'], project_config.feature_flags)
340-
341-
expected_group_id_map = {
342-
'19228': entities.Group(
343-
config_dict['groups'][0]['id'],
344-
config_dict['groups'][0]['policy'],
345-
config_dict['groups'][0]['experiments'],
346-
config_dict['groups'][0]['trafficAllocation']
347-
)
348-
}
349-
expected_experiment_key_map = {
350-
'test_experiment': entities.Experiment(
351-
'111127', 'test_experiment', 'Running', ['11154'], [{
352-
'key': 'control',
353-
'id': '111128',
354-
'variables': [{
355-
'id': '127',
356-
'value': 'false'
357-
}]
358-
}, {
359-
'key': 'variation',
360-
'id': '111129',
361-
'variables': [{
362-
'id': '127',
363-
'value': 'true'
364-
}]
365-
}], {
366-
'user_1': 'control',
367-
'user_2': 'control'
368-
}, [{
369-
'entityId': '111128',
370-
'endOfRange': 4000
371-
}, {
372-
'entityId': '',
373-
'endOfRange': 5000
374-
}, {
375-
'entityId': '111129',
376-
'endOfRange': 9000
377-
}],
378-
'111182'),
379-
'group_exp_1': entities.Experiment(
380-
'32222', 'group_exp_1', 'Running', [], [{
381-
'key': 'group_exp_1_control',
382-
'id': '28901',
383-
'variables': [{
384-
'id': '128',
385-
'value': 'prod'
386-
}, {
387-
'id': '129',
388-
'value': '1772'
389-
}, {
390-
'id': '130',
391-
'value': '1.22992'
392-
}]
393-
}, {
394-
'key': 'group_exp_1_variation',
395-
'id': '28902',
396-
'variables': [{
397-
'id': '128',
398-
'value': 'stage'
399-
}, {
400-
'id': '129',
401-
'value': '112'
402-
}, {
403-
'id': '130',
404-
'value': '1.211'
405-
}]
406-
}], {
407-
'user_1': 'group_exp_1_control',
408-
'user_2': 'group_exp_1_control'
409-
}, [{
410-
'entityId': '28901',
411-
'endOfRange': 3000
412-
}, {
413-
'entityId': '28902',
414-
'endOfRange': 9000
415-
}], '111183', groupId='19228', groupPolicy='random'
416-
),
417-
'group_exp_2': entities.Experiment(
418-
'32223', 'group_exp_2', 'Running', [], [{
419-
'key': 'group_exp_2_control',
420-
'id': '28905',
421-
'variables': []
422-
}, {
423-
'key': 'group_exp_2_variation',
424-
'id': '28906',
425-
'variables': []
426-
}], {
427-
'user_1': 'group_exp_2_control',
428-
'user_2': 'group_exp_2_control'
429-
}, [{
430-
'entityId': '28905',
431-
'endOfRange': 8000
432-
}, {
433-
'entityId': '28906',
434-
'endOfRange': 10000
435-
}], '111184', groupId='19228', groupPolicy='random'
436-
),
437-
}
438-
expected_experiment_id_map = {
439-
'111127': expected_experiment_key_map.get('test_experiment'),
440-
'32222': expected_experiment_key_map.get('group_exp_1'),
441-
'32223': expected_experiment_key_map.get('group_exp_2')
442-
}
443-
expected_event_key_map = {
444-
'test_event': entities.Event('111095', 'test_event', ['111127']),
445-
'Total Revenue': entities.Event('111096', 'Total Revenue', ['111127'])
446-
}
447-
expected_attribute_key_map = {
448-
'test_attribute': entities.Attribute('111094', 'test_attribute', segmentId='11133')
449-
}
450-
expected_audience_id_map = {
451-
'11154': entities.Audience(
452-
'11154', 'Test attribute users',
453-
'["and", ["or", ["or", {"name": "test_attribute", "type": "custom_attribute", "value": "test_value"}]]]',
454-
conditionStructure=['and', ['or', ['or', 0]]],
455-
conditionList=[['test_attribute', 'test_value']]
456-
)
457-
}
458-
expected_variation_key_map = {
459-
'test_experiment': {
460-
'control': entities.Variation('111128', 'control', [{'id': '127', 'value': 'false'}], {'is_working': False}),
461-
'variation': entities.Variation('111129', 'variation', [{'id': '127', 'value': 'true'}], {'is_working': True})
462-
},
463-
'group_exp_1': {
464-
'group_exp_1_control': entities.Variation(
465-
'28901', 'group_exp_1_control', [
466-
{'id': '128', 'value': 'prod'}, {'id': '129', 'value': '1772'}, {'id': '130', 'value': '1.22992'}], {
467-
'environment': 'prod',
468-
'number_of_days': 1772,
469-
'significance_value': 1.22992
470-
}),
471-
'group_exp_1_variation': entities.Variation(
472-
'28902', 'group_exp_1_variation', [
473-
{'id': '128', 'value': 'stage'}, {'id': '129', 'value': '112'}, {'id': '130', 'value': '1.211'}], {
474-
'environment': 'stage',
475-
'number_of_days': 112,
476-
'significance_value': 1.211
477-
})
478-
},
479-
'group_exp_2': {
480-
'group_exp_2_control': entities.Variation('28905', 'group_exp_2_control'),
481-
'group_exp_2_variation': entities.Variation('28906', 'group_exp_2_variation')
482-
}
483-
}
484-
expected_variation_id_map = {
485-
'test_experiment': {
486-
'111128': entities.Variation('111128', 'control', [{'id': '127', 'value': 'false'}], {'is_working': False}),
487-
'111129': entities.Variation('111129', 'variation', [{'id': '127', 'value': 'true'}], {'is_working': True})
488-
},
489-
'group_exp_1': {
490-
'28901': entities.Variation('28901', 'group_exp_1_control', [
491-
{'id': '128', 'value': 'prod'}, {'id': '129', 'value': '1772'}, {'id': '130', 'value': '1.22992'}], {
492-
'environment': 'prod',
493-
'number_of_days': 1772,
494-
'significance_value': 1.22992
495-
}),
496-
'28902': entities.Variation('28902', 'group_exp_1_variation', [
497-
{'id': '128', 'value': 'stage'}, {'id': '129', 'value': '112'}, {'id': '130', 'value': '1.211'}], {
498-
'environment': 'stage',
499-
'number_of_days': 112,
500-
'significance_value': 1.211
501-
})
502-
},
503-
'group_exp_2': {
504-
'28905': entities.Variation('28905', 'group_exp_2_control'),
505-
'28906': entities.Variation('28906', 'group_exp_2_variation')
506-
}
507-
}
508-
expected_feature_flag_id_map = {
509-
'127': entities.FeatureFlag('127', 'is_working', 'boolean', 'true'),
510-
'128': entities.FeatureFlag('128', 'environment', 'string', 'devel'),
511-
'129': entities.FeatureFlag('129', 'number_of_days', 'integer', '192'),
512-
'130': entities.FeatureFlag('130', 'significance_value', 'double', '0.00098')
513-
}
514-
515-
self.assertEqual(expected_group_id_map, project_config.group_id_map)
516-
self.assertEqual(expected_experiment_key_map, project_config.experiment_key_map)
517-
self.assertEqual(expected_experiment_id_map, project_config.experiment_id_map)
518-
self.assertEqual(expected_event_key_map, project_config.event_key_map)
519-
self.assertEqual(expected_attribute_key_map, project_config.attribute_key_map)
520-
self.assertEqual(expected_audience_id_map, project_config.audience_id_map)
521-
self.assertEqual(expected_variation_key_map, project_config.variation_key_map)
522-
self.assertEqual(expected_variation_id_map, project_config.variation_id_map)
523-
self.assertEqual(expected_feature_flag_id_map, project_config.feature_flag_id_map)
300+
self.assertTrue(test_obj.is_valid)
524301

525302
def test_get_version(self):
526303
""" Test that JSON version is retrieved correctly when using get_version. """

0 commit comments

Comments
 (0)