diff --git a/optimizely/entities.py b/optimizely/entities.py index 6aa0060d..589ca984 100644 --- a/optimizely/entities.py +++ b/optimizely/entities.py @@ -22,7 +22,7 @@ if TYPE_CHECKING: # prevent circular dependenacy by skipping import at runtime - from .helpers.types import ExperimentDict, ExperimentType, TrafficAllocation, VariableDict, VariationDict, CmabDict + from .helpers.types import ExperimentDict, TrafficAllocation, VariableDict, VariationDict, CmabDict class BaseEntity: @@ -87,7 +87,7 @@ def __init__( groupId: Optional[str] = None, groupPolicy: Optional[str] = None, cmab: Optional[CmabDict] = None, - type: Optional[ExperimentType] = None, + type: Optional[str] = None, **kwargs: Any ): self.id = id diff --git a/optimizely/project_config.py b/optimizely/project_config.py index 3aa1cc2b..5b752538 100644 --- a/optimizely/project_config.py +++ b/optimizely/project_config.py @@ -189,24 +189,7 @@ def __init__(self, datafile: str | bytes, logger: Logger, error_handler: Any): self.variation_key_map_by_experiment_id: dict[str, dict[str, Union[entities.Variation, VariationDict]]] = {} self.flag_variations_map: dict[str, list[entities.Variation]] = {} - valid_experiment_types = { - enums.ExperimentTypes.ab, - enums.ExperimentTypes.mab, - enums.ExperimentTypes.cmab, - enums.ExperimentTypes.td, - enums.ExperimentTypes.fr, - } for experiment in self.experiment_id_map.values(): - if experiment.type is not None and experiment.type not in valid_experiment_types: - self.logger.error( - f'Experiment "{experiment.key}" has invalid type "{experiment.type}". ' - f'Valid types: {valid_experiment_types}.' - ) - self.error_handler.handle_error( - exceptions.InvalidExperimentException( - f'Invalid experiment type: {experiment.type}' - ) - ) self.experiment_key_map[experiment.key] = experiment self.variation_key_map[experiment.key] = self._generate_key_map( experiment.variations, 'key', entities.Variation diff --git a/tests/test_config.py b/tests/test_config.py index eba36bc4..c21f9b34 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1651,6 +1651,41 @@ def test_experiment_type_field_none_when_missing(self): experiment = config.experiment_id_map['exp_ab'] self.assertIsNone(experiment.type) + def test_unknown_experiment_type_accepted(self): + """Test that experiments with unknown type values are accepted without error.""" + datafile = self._build_datafile( + experiments=[ + { + 'id': 'exp_unknown', + 'key': 'unknown_type_exp', + 'status': 'Running', + 'forcedVariations': {}, + 'layerId': 'layer_1', + 'audienceIds': [], + 'trafficAllocation': [{'entityId': 'var_1', 'endOfRange': 5000}], + 'variations': [{'key': 'var_1', 'id': 'var_1', 'featureEnabled': True}], + 'type': 'new_unknown_type', + }, + ], + feature_flags=[ + { + 'id': 'flag_1', + 'key': 'test_flag', + 'experimentIds': ['exp_unknown'], + 'rolloutId': '', + 'variables': [], + }, + ], + ) + + opt = optimizely.Optimizely(json.dumps(datafile)) + config = opt.config_manager.get_config() + + self.assertIsNotNone(config) + experiment = config.experiment_id_map['exp_unknown'] + self.assertEqual(experiment.type, 'new_unknown_type') + self.assertEqual(experiment.key, 'unknown_type_exp') + def test_feature_rollout_injects_everyone_else_variation(self): """Test that feature_rollout experiments get the everyone else variation injected.""" datafile = self._build_datafile(