diff --git a/growthbook/common_types.py b/growthbook/common_types.py index 0e167e9..6a01a6a 100644 --- a/growthbook/common_types.py +++ b/growthbook/common_types.py @@ -54,6 +54,7 @@ def __init__( bucketVersion: Optional[int] = None, minBucketVersion: Optional[int] = None, parentConditions: Optional[List[Dict[str, Any]]] = None, + customFields: Optional[Dict[str, Any]] = None, **_ignored: Any, ) -> None: self.key = key @@ -76,6 +77,9 @@ def __init__( self.bucketVersion = bucketVersion or 0 self.minBucketVersion = minBucketVersion or 0 self.parentConditions = parentConditions + # Custom Fields defined for the experiment in the GrowthBook UI. + # Arrives from the API as a flat dict (e.g. {"cfl_abc123": "value"}). + self.customFields = customFields or {} self.fallbackAttribute = None if not self.disableStickyBucketing: @@ -117,6 +121,8 @@ def to_dict(self) -> Dict[str, Any]: obj["minBucketVersion"] = self.minBucketVersion if self.parentConditions: obj["parentConditions"] = self.parentConditions + if self.customFields: + obj["customFields"] = self.customFields return obj diff --git a/tests/test_growthbook.py b/tests/test_growthbook.py index b51f6a6..a0b80c1 100644 --- a/tests/test_growthbook.py +++ b/tests/test_growthbook.py @@ -359,6 +359,38 @@ def test_handles_weird_experiment_values(): gb.destroy() +def test_custom_fields_parsed_from_api_dict(): + # The API delivers experiment Custom Fields as a flat dict. + exp = Experiment( + **{ + "key": "my-experiment", + "variations": ["control", "variant"], + "customFields": {"cfl_abc123": "My custom field", "cfl_def456": 42}, + } + ) + assert exp.customFields == {"cfl_abc123": "My custom field", "cfl_def456": 42} + assert exp.to_dict()["customFields"] == { + "cfl_abc123": "My custom field", + "cfl_def456": 42, + } + + +def test_custom_fields_default_when_absent(): + exp = Experiment(key="my-experiment", variations=["control", "variant"]) + assert exp.customFields == {} + # Empty custom fields are omitted from the serialized dict. + assert "customFields" not in exp.to_dict() + + +def test_custom_fields_public_init(): + exp = Experiment( + key="my-experiment", + variations=["control", "variant"], + customFields={"cfl_xyz": "hello"}, + ) + assert exp.customFields == {"cfl_xyz": "hello"} + + def test_skip_all_experiments_flag(): """Test that skip_all_experiments flag prevents users from being put into experiments"""