From ad1be3b6d5c0a496aa721261abb40f7e920b32e4 Mon Sep 17 00:00:00 2001 From: Andrew Miller Date: Fri, 12 Jun 2026 23:36:36 -0500 Subject: [PATCH 1/2] Add .env and graphify-out/ to .gitignore Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index dec3713..3409ff2 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,9 @@ CLAUDE.md # Docs (local reference material) Design Docs/ Visor API docs/ + +# Graphify knowledge graph outputs +graphify-out/ + +# Environment variables +.env From 78074f4f037a5b468da40f2c25c26e0a1c6d7cb1 Mon Sep 17 00:00:00 2001 From: Andrew Miller Date: Fri, 12 Jun 2026 23:39:05 -0500 Subject: [PATCH 2/2] Add public export audit and test suite (step 12) Confirms src/visor/__init__.py already exposes all required public symbols, and adds tests/test_exports.py to guard against future export drift. Co-Authored-By: Claude Sonnet 4.6 --- tests/test_exports.py | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/test_exports.py diff --git a/tests/test_exports.py b/tests/test_exports.py new file mode 100644 index 0000000..ea302b8 --- /dev/null +++ b/tests/test_exports.py @@ -0,0 +1,80 @@ +"""Smoke-test that all public symbols are importable from the visor package root.""" + +import visor + +EXPECTED_EXPORTS = { + # clients + "AsyncVisorClient", + "VisorClient", + # pagination + "paginate_listings", + "paginate_dealers", + "iter_listings", + "iter_dealers", + # exceptions + "VisorError", + "VisorAPIError", + "VisorTransportError", + "AuthError", + "ForbiddenError", + "NotFoundError", + "ValidationError", + "PaymentRequiredError", + "RateLimitError", + # filter / request models + "ListingsFilter", + "FacetsFilter", + "DealerFilter", + "BBox", + # listing response models + "ListingsPage", + "ListingSummary", + "ListingDetail", + "ListingSnapshot", + # dealer response models + "DealersPage", + "DealerSummary", + "DealerDetail", + "DealerAddress", + # other response models + "VinDetail", + "UsageSummary", + "UsageRecord", + "UsageTotals", + "UsageMeta", + "FacetsResponse", + "FacetsData", + "FacetBucket", + # shared models + "Pagination", + "DealerRef", + "VehicleBuild", + "VehicleRecord", + "VehicleOption", +} + +PRIVATE_TRANSPORT = {"AsyncVisorTransport", "SyncVisorTransport"} + + +def test_all_contains_expected(): + missing = EXPECTED_EXPORTS - set(visor.__all__) + assert not missing, f"Missing from __all__: {sorted(missing)}" + + +def test_symbols_importable(): + missing = [name for name in EXPECTED_EXPORTS if not hasattr(visor, name)] + assert not missing, f"Not importable from visor: {sorted(missing)}" + + +def test_transport_internals_not_exported(): + leaked = PRIVATE_TRANSPORT & set(visor.__all__) + assert not leaked, f"Internal transport classes in __all__: {sorted(leaked)}" + + +def test_readme_imports(): + from visor import AsyncVisorClient, ListingsFilter, VisorClient, iter_listings + + assert AsyncVisorClient is visor.AsyncVisorClient + assert VisorClient is visor.VisorClient + assert ListingsFilter is visor.ListingsFilter + assert iter_listings is visor.iter_listings