From 677ebe72efe86f231bd4c4bfc13f02794ff63b8b Mon Sep 17 00:00:00 2001 From: Marvin Liu Date: Tue, 12 Dec 2023 15:01:26 -0800 Subject: [PATCH] fix: allow none property value but not send (#54) --- README.md | 16 ++++++++++++++++ src/amplitude/event.py | 6 +++++- src/test/test_event.py | 12 ++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b67daf..d1fbecf 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,22 @@ The official Amplitude backend Python SDK for server-side instrumentation. +## Development +### Run Server Locally +Refer to `examples/README.md`. + +### Run Unit Tests Locally +#### Run Directly +``` +python3 -m unittest discover -s ./src -p 'test_*.py' +``` + +#### Run with `tox` +``` +pip3 install --user tox +python3 -m tox -e py +``` + ## Amplitude and Ampli Wrapper [Ampli SDK](https://www.docs.developers.amplitude.com/data/ampli/) is autogenerated library based on your pre-defined [tracking plan](https://developers.data.amplitude.com/what-is-a-tracking-plan). The Ampli Wrapper, is a lightweight wrapper over the Amplitude SDK that provides type-safety, supports linting, and enables features like input validation. The code replicates the spec in the Tracking Plan and enforces its rules and requirements. This repository is about **Amplitude SDK**. To learn more about Ampli Wrapper, please refer to the [Ampli Python](https://www.docs.developers.amplitude.com/data/sdks/python/ampli/) and [examples](https://github.com/amplitude/ampli-examples). diff --git a/src/amplitude/event.py b/src/amplitude/event.py index 92e557b..2d265d0 100644 --- a/src/amplitude/event.py +++ b/src/amplitude/event.py @@ -364,9 +364,11 @@ def get_event_body(self) -> dict: event_body["ingestion_metadata"] = event_body["ingestion_metadata"].get_body() for properties in ["user_properties", "event_properties", "group_properties"]: if properties in event_body: - for key, value in event_body[properties].items(): + for key, value in list(event_body[properties].items()): if isinstance(value, enum.Enum): event_body[properties][key] = value.value + if value is None: + event_body[properties].pop(key) return utils.truncate(event_body) def _verify_property(self, key, value) -> bool: @@ -1249,6 +1251,8 @@ def is_validate_properties(key, value): """ if not isinstance(key, str): return False + if value is None: + return True if isinstance(value, list): result = True for element in value: diff --git a/src/test/test_event.py b/src/test/test_event.py index 91c8c78..c1f3815 100644 --- a/src/test/test_event.py +++ b/src/test/test_event.py @@ -99,6 +99,18 @@ class TestEnum(enum.Enum): "event_properties": {"enum_properties": 'test'}} self.assertEqual(expect_dict, event.get_event_body()) + def test_base_event_get_event_body_with_none_value_in_property(self): + class TestEnum(enum.Enum): + ENUM1 = 'test' + ENUM2 = 'test2' + event = BaseEvent(event_type="test_event", user_id="test_user", user_properties={"email": "test@test"}, + event_properties={'enum_properties': TestEnum.ENUM1, 'empty_property': None}) + expect_dict = {"event_type": "test_event", + "user_id": "test_user", + "user_properties": {"email": "test@test"}, + "event_properties": {"enum_properties": 'test'}} + self.assertEqual(expect_dict, event.get_event_body()) + def test_base_event_set_dict_event_attributes_with_invalid_value_failed(self): event = BaseEvent(event_type="test_event", user_id="test_user") event["event_properties"] = {4: "4"}