diff --git a/.github/scripts/check_public_api.py b/.github/scripts/check_public_api.py index 7b276890..702abf17 100644 --- a/.github/scripts/check_public_api.py +++ b/.github/scripts/check_public_api.py @@ -9,16 +9,11 @@ from pathlib import Path from typing import Iterable -try: - import griffe -except ImportError: # pragma: no cover - exercised only when dependencies are missing. - print("griffe is required; install dev dependencies first.", file=sys.stderr) - raise - ROOT = Path(__file__).resolve().parents[2] SNAPSHOT_PATH = ROOT / "references" / "public_api_snapshot.txt" PUBLIC_SPECIAL_NAMES = {"__version__"} EXCLUDED_MODULE_PREFIXES = ("posthog.test",) +ATTRIBUTE_VALUE_PLACEHOLDERS = {"posthog.version.VERSION": ""} HEADER = """# This file is generated by .github/scripts/check_public_api.py. # Run `make public_api_snapshot` after an intentional public API change. @@ -142,6 +137,7 @@ def _attribute_details(obj: object) -> str: value = getattr(obj, "value", None) if value is not None: + value = ATTRIBUTE_VALUE_PLACEHOLDERS.get(_object_path(obj), value) parts.append(f" = {value}") return "".join(parts) @@ -207,7 +203,17 @@ def _iter_module_members(module: object) -> Iterable[object]: yield from _iter_class_members(member) +def _load_griffe(): + try: + import griffe + except ImportError: # pragma: no cover + print("griffe is required; install dev dependencies first.", file=sys.stderr) + raise + return griffe + + def generate_snapshot() -> str: + griffe = _load_griffe() package = griffe.load( "posthog", allow_inspection=False, diff --git a/.github/scripts/test_check_public_api.py b/.github/scripts/test_check_public_api.py new file mode 100644 index 00000000..6fade7b4 --- /dev/null +++ b/.github/scripts/test_check_public_api.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Tests for check_public_api.py.""" + +from __future__ import annotations + +import importlib.util +from pathlib import Path +from types import SimpleNamespace + + +SCRIPT_PATH = Path(__file__).with_name("check_public_api.py") + + +def load_check_public_api(): + spec = importlib.util.spec_from_file_location("check_public_api", SCRIPT_PATH) + assert spec is not None + assert spec.loader is not None + + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def test_attribute_details_uses_placeholder_values() -> None: + check_public_api = load_check_public_api() + + for path, placeholder in check_public_api.ATTRIBUTE_VALUE_PLACEHOLDERS.items(): + obj = SimpleNamespace(path=path, annotation=None, value='"7.19.1"') + assert check_public_api._attribute_details(obj) == f"{path} = {placeholder}" + + +def main() -> int: + test_attribute_details_uses_placeholder_values() + print("check_public_api tests passed.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fccec51..4b3f5e6c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,6 +74,7 @@ jobs: - name: Check public API snapshot run: | + python .github/scripts/test_check_public_api.py make public_api_check package-build: diff --git a/posthog/test/conftest.py b/posthog/test/conftest.py new file mode 100644 index 00000000..1aa9d03f --- /dev/null +++ b/posthog/test/conftest.py @@ -0,0 +1,10 @@ +from __future__ import annotations + +import pytest + +import posthog.client as client_module + + +@pytest.fixture(autouse=True) +def disable_client_atexit_join(monkeypatch): + monkeypatch.setattr(client_module.atexit, "register", lambda *args, **kwargs: None) diff --git a/references/public_api_snapshot.txt b/references/public_api_snapshot.txt index e6645985..2ba8a253 100644 --- a/references/public_api_snapshot.txt +++ b/references/public_api_snapshot.txt @@ -685,7 +685,7 @@ attribute posthog.utils.RedisFlagCache.stale_ttl = stale_ttl attribute posthog.utils.RedisFlagCache.version_key = f'{key_prefix}version' attribute posthog.utils.SizeLimitedDict.max_size = max_size attribute posthog.utils.log = logging.getLogger('posthog') -attribute posthog.version.VERSION = '7.19.1' +attribute posthog.version.VERSION = class posthog.Posthog class posthog.ai.anthropic.anthropic.Anthropic(posthog_client: Optional[PostHogClient] = None, **kwargs) class posthog.ai.anthropic.anthropic.WrappedMessages