diff --git a/.sampo/changesets/haughty-thunderbearer-mielikki.md b/.sampo/changesets/haughty-thunderbearer-mielikki.md new file mode 100644 index 00000000..68cc9bc6 --- /dev/null +++ b/.sampo/changesets/haughty-thunderbearer-mielikki.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +Make module-level setup no-op when API key is blank diff --git a/posthog/__init__.py b/posthog/__init__.py index 93fead78..559aba88 100644 --- a/posthog/__init__.py +++ b/posthog/__init__.py @@ -266,8 +266,8 @@ def get_tags() -> Dict[str, Any]: the corresponding constructor arguments. Attributes: - api_key: Project API key/token used by the global client. Required before - calling any global capture or feature flag API. + api_key: Project API key/token used by the global client. Missing or blank + values create a disabled no-op global client. host: PostHog ingestion host. Defaults to the US ingestion endpoint when not set. on_error: Optional callback invoked by background consumers when event upload @@ -1064,20 +1064,17 @@ def setup() -> Client: ``setup()`` is called automatically by global APIs such as ``capture()``. Returns: - The global ``Client`` instance. - - Raises: - ValueError: If ``api_key`` has not been configured. + The global ``Client`` instance. If ``api_key`` is missing or blank, + the client is disabled and module-level calls become no-ops. Category: Initialization """ global default_client if not default_client: - if not api_key: - raise ValueError("API key is required") + configured_api_key = api_key.strip() if api_key else "" default_client = Client( - api_key, + configured_api_key, host=host, debug=debug, on_error=on_error, diff --git a/posthog/test/test_module.py b/posthog/test/test_module.py index aa87314f..b9dea8c5 100644 --- a/posthog/test/test_module.py +++ b/posthog/test/test_module.py @@ -43,7 +43,6 @@ def setUp(self): self._original_disabled = posthog.disabled self._original_send = posthog.send posthog.default_client = None - posthog.api_key = " \n\t " posthog.disabled = False posthog.send = False @@ -53,12 +52,24 @@ def tearDown(self): posthog.disabled = self._original_disabled posthog.send = self._original_send - def test_setup_preserves_client_disabled_when_trimmed_api_key_is_empty(self): - posthog.setup() + @parameterized.expand( + [ + ("unset", None), + ("empty", ""), + ("whitespace", " \n\t "), + ] + ) + def test_setup_configures_disabled_client_when_api_key_is_blank( + self, _name, api_key + ): + posthog.api_key = api_key + + client = posthog.setup() - self.assertIsNotNone(posthog.default_client) - self.assertEqual(posthog.default_client.api_key, "") - self.assertTrue(posthog.default_client.disabled) + self.assertIs(client, posthog.default_client) + self.assertEqual(client.api_key, "") + self.assertTrue(client.disabled) + self.assertIsNone(posthog.capture("Module Python Event", distinct_id="john")) class TestModuleLevelWrappers(unittest.TestCase):