Repository navigation
Description
Measured on main at bef739e02, and on the PyPI wheel adcp 9.6.1 for the bundle half.
The observation
src/adcp/types/aliases.py imports a deprecated-3.1.8 compatibility class at module scope, only in order to re-export it under two flat names:
# src/adcp/types/aliases.py:2164
from adcp.types.domains.trusted_match.identity_match_response import (
TmpxMacro as IdentityMatchTmpxMacro,
)
# :2167
from adcp.types.domains.trusted_match.provider_registration import (
TmpxMacro as ProviderRegistrationTmpxMacro,
)(__all__ at :2290-2291; nothing else in the module uses either name.) src/adcp/types/_eager.py:706 and :773 import the same two names the same way.
The class's own generated docstring says what it is:
# src/adcp/types/domains/trusted_match/provider_registration.py:24
class TmpxMacro(ScalarStr):
"""Deprecated 3.1.8 registered macro-name compatibility model."""
_constraints = {'max_length': 64, 'min_length': 1, 'pattern': '^[A-Z][A-Z0-9_]*$'}And that constraint set has no node in the 3.2 bundle the wheel ships
Scanning adcp/_schemas/3.2 from the 9.6.1 wheel (manifest.json → adcp_version 3.2.7), excluding the bundled/ and mcp/ projections, for a node carrying pattern: ^[A-Z][A-Z0-9_]*$:
| document#pointer | maxLength | minLength |
|---|---|---|
core/reporting-adjustment-receipt.json#/definitions/ReportingAdjustmentRejectionCode |
128 | 1 |
core/reporting-receipt.json#/properties/rejection_codes/items |
128 | 1 |
core/reporting-materialization.json#/properties/failure_code |
128 | 1 |
Three positions, all maxLength: 128. Nothing in the bundle states the 64 the class pins, and the two trusted-match documents the class is generated into now state ^[A-Za-z0-9_]+$ (identity-match-response.json#/properties/tmpx_providers/propertyNames) and ^[a-zA-Z][a-zA-Z0-9_]*$ (provider-registration.json#/properties/tmpx_slots/items) instead. So the class looks like a 3.1.8 leftover that survives in the generated tree rather than a projection of a node the current bundle states.
Why the module scope matters
One unguarded module-scope import of a name a regeneration may not produce takes the whole module with it:
aliases.pybinds 254 names at module scope and exports 311;_eager.pybinds 903 and exports 965 — andadcp/types/__init__.pyresolves every flat type symbol by importing_eager(its own docstring at:1164: "to any type symbol, by importing :mod:adcp.types._eager"). So anImportErrorthere is not one missing word, it is the flat surface.
We hit this building a tree from the published 3.2 bundle where the node is not stated: with every other name resolving, these two imports alone were enough to make import adcp.types fail.
The ask, and it is a pattern this file already uses
aliases.py:2002-2009 already guards exactly this situation for a name whose home moved:
try:
from adcp.types.domains.enums.duration_unit import DurationUnit
except ModuleNotFoundError as exc:
if exc.name != "adcp.types.domains.enums.duration_unit":
raise
from adcp.types.domains.core.duration import Unit as DurationUnitWould you take the same guard around the two deprecated-3.1.8 re-exports — try/except ImportError, and on failure simply not bind the two flat words? Then a consumer on a bundle that no longer states the node loses a deprecated compatibility word and keeps the module, which seems like the right trade for something whose own docstring says "Deprecated 3.1.8".
It is also worth asking the prior question: should TmpxMacro still be generated at all, given no node in the shipped 3.2 bundle carries its constraint set? If it is retained deliberately for 3.1.x peers, the guard is the smaller ask and this is only a request to confirm the intent.
Reproduction
python -c "import adcp.types.aliases as a; print(a.IdentityMatchTmpxMacro._constraints)"
# {'max_length': 64, 'min_length': 1, 'pattern': '^[A-Z][A-Z0-9_]*$'}
python - <<'EOF'
import json, pathlib, adcp
B = pathlib.Path(adcp.__file__).parent / "_schemas" / "3.2"
hits = [f for f in B.rglob("*.json")
if not str(f.relative_to(B)).startswith(("bundled/", "mcp/"))
and '"^[A-Z][A-Z0-9_]*$"' in f.read_text()]
print([str(f.relative_to(B)) for f in hits]) # the three reporting documents, all maxLength 128
EOF
Activity