Agentic-Reliability-Framework-API / tests /test_tracker_binding.py
petter2025's picture
Upload folder using huggingface_hub
202f097 verified
Raw
History Blame Contribute Delete
4.03 kB
"""Guard against re-introducing the stale `tracker` from-import.
`app.core.usage_tracker.tracker` starts as None and is rebound by
`init_tracker()` during the lifespan. `from app.core.usage_tracker import
tracker` copies the *binding* -- None -- at import time, and the later
rebinding never reaches the importer. Five modules did this: main.py
crashed the Render deploy with "'NoneType' object has no attribute
'warm_up'", routes_admin's 20 unguarded uses would have 500'd, and
routes_incidents/payments/users each had a `if tracker` guard that could
only ever take the None branch -- so usage went unmetered and signup and
checkout were permanently disabled, silently.
This is a source-level check on purpose. Reproducing the bug at runtime
needs a real UsageTracker (Postgres, pepper) and would only cover the
modules the test happened to import; parsing every module catches the
next one too, and costs nothing.
"""
import ast
import re
import pathlib
import pytest
APP = pathlib.Path(__file__).resolve().parent.parent / "app"
# Names safe to import directly: functions defined in usage_tracker.py
# resolve the module global at call time, so they always see the live
# instance. Only the mutable module-level object itself is unsafe.
UNSAFE_NAMES = {"tracker"}
def _source_files():
return sorted(p for p in APP.rglob("*.py"))
TESTS = pathlib.Path(__file__).resolve().parent
# `patch("app.api.routes_admin.tracker")` and
# `monkeypatch.setattr(routes_payments, "tracker", ...)` both target an
# attribute that only exists while the broken from-import does. They passed
# for as long as the bug was there and broke the moment it was fixed --
# and, worse, while the bug was there they were patching a name the route
# code was already reading as None, so they proved nothing.
#
# conftest.py has always done the right thing (`app.core.usage_tracker
# .tracker = MockTracker()`), which is why this is the correct target: one
# patch on the defining module reaches every consumer.
_BAD_PATCH_TARGETS = re.compile(
r"""["']app\.api\.routes_\w+\.tracker["']"""
r"""|setattr\(\s*routes_\w+\s*,\s*["']tracker["']"""
)
def _test_files():
"""Every test module but this one.
The check is textual, so this file trips it on the comment above that
quotes the bad forms. Excluding self rather than contorting the regex
keeps the pattern readable and the examples literal -- and the cost is
only that this file cannot police itself, which it has no reason to.
"""
here = pathlib.Path(__file__).resolve()
return sorted(p for p in TESTS.glob("test_*.py") if p.resolve() != here)
@pytest.mark.parametrize("path", _test_files(), ids=lambda p: p.name)
def test_no_test_patches_tracker_on_a_route_module(path):
src = path.read_text(encoding="utf-8")
for lineno, line in enumerate(src.splitlines(), start=1):
assert not _BAD_PATCH_TARGETS.search(line), (
f"{path.name}:{lineno} patches `tracker` on a route module. Route "
"modules reference `usage_tracker.tracker` and hold no binding of "
'their own -- patch "app.core.usage_tracker.tracker" instead, '
"which is what conftest.py already does."
)
@pytest.mark.parametrize("path", _source_files(), ids=lambda p: p.name)
def test_tracker_is_never_imported_by_name(path):
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
for node in ast.walk(tree):
if not isinstance(node, ast.ImportFrom):
continue
if node.module != "app.core.usage_tracker":
continue
offenders = sorted(
{a.name for a in node.names} & UNSAFE_NAMES
)
assert not offenders, (
f"{path.name}:{node.lineno} imports {offenders} by name from "
"app.core.usage_tracker. That binding is None at import time and "
"init_tracker() will not update it. Use `from app.core import "
"usage_tracker` and reference `usage_tracker.tracker` instead."
)