Skip to content

fix(types): make the domain package roots lazy so a types package imports first in any order - #1798

Merged
bokelley merged 1 commit into
mainfrom
claude/issue-1784-formats-import-cycle-main
Nov 2, 2026
Merged

bokelley merged 1 commit into
mainfrom
claude/issue-1784-formats-import-cycle-main

Conversation

@bokelley

@bokelley bokelley commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Backport of #1797 (SDK 10) to the 9.x line, where #1784 reproduces identically: from adcp.types.domains.formats import Slot raised ImportError when it was the first adcp import in a process, because the domain roots imported every schema module eagerly and formats/canonical/_base.py re-entered formats/canonical through core/__init__ while half built.

  • consolidate_exports.generate_domain_exports writes each domain root as a PEP 562 module: __all__ and a TYPE_CHECKING import block keep the static surface, _DECLARED_IN names each name's schema module, and __getattr__ imports the declaring module on first read and caches the binding. An unknown name raises AttributeError, so submodule imports still fall through. Nothing is renamed; every name still resolves; import * still binds everything.
  • The 24 domain roots are regenerated. make validate-generated ✓, make lint ✓, make typecheck-all ✓. Surface, layering, lazy-types, public-API and codegen suites pass (365 tests).
  • New tests/test_domain_roots_import_in_any_order.py: each domain root and the reported entry points import first in a fresh interpreter.

Non-breaking: import-order fix only.

🤖 Generated with Claude Code

Comment on lines +45 to +46
"from adcp.types.domains.creative.list_creative_formats_response import "
"ListCreativeFormatsResponseCreativeAgent",

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — backport of #1797 to the 9.x line making 24 domain package roots lazy (PEP 562) to fix import-order re-entrancy (#1784).

The only non-generated source change is consolidate_exports.generate_domain_exports (scripts/consolidate_exports.py:972-1011), which emits a TYPE_CHECKING static-import block, _DECLARED_IN, and a guarded __getattr__/__dir__ matching the established types/__init__.py pattern. The AttributeError fall-through preserves submodule imports and import *. Regenerated roots preserve the public surface exactly (core: base __all__=1440, head __all__=1440, _DECLARED_IN=1440 in lockstep), so there is no public-API break and fix(types): is the correct semver signal. The new tests/test_domain_roots_import_in_any_order.py exercises the reported import-order paths in fresh interpreters.

No blocking or medium findings. high_risk is false, gated_paths is false, no author team gate. Although review_decision is REVIEW_REQUIRED, the gated-paths hard gate (row 2) only applies when gated_paths is true — it is not here — so this falls through to row 9.

…orts first in any order

Backport of the SDK 10 fix for #1784 to the 9.x line, where the cycle
reproduces identically: ``from adcp.types.domains.formats import Slot`` raised
ImportError when it was the first adcp import in a process, because the domain
roots imported every schema module eagerly and ``formats/canonical/_base.py``
re-entered ``formats/canonical`` through ``core/__init__`` while half built.

Each domain root is now a PEP 562 module: ``__all__`` and a TYPE_CHECKING
import block keep the static surface, ``_DECLARED_IN`` names each name's
schema module, and ``__getattr__`` imports the declaring module on first read
and caches the binding. Nothing is renamed and every name still resolves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bokelley
bokelley force-pushed the claude/issue-1784-formats-import-cycle-main branch from 12297a9 to 959ff18 Compare November 2, 2026 03:52

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — clean backport of #1797 making the 22 domain package roots lazy (PEP 562) to resolve the #1784 import-order cycle.

Checked:

  • Generator (scripts/consolidate_exports.py): __all__ and the new _DECLARED_IN map both derive from the same rows dict, so every exported name resolves via __getattr__; AttributeError fallthrough preserves submodule imports.
  • The runtime __getattr__/__dir__ sit correctly under if not TYPE_CHECKING:, with the static surface in the TYPE_CHECKING block — preserving type-checker coverage per the repo's PEP 562 facade invariant.
  • Public surface preserved: no renames, __all__ unchanged, non-breaking — no semver signal required.
  • New fresh-interpreter import-order test suite is thorough.

No critical/high/medium findings. Consistent with the prior approve on head 12297a9.

Decision path: high_risk=false, gated_paths=false (no gate applies), no no-auto-approve team match, zero findings → decision table rows 1–8 do not fire → row 9 approve.

@bokelley
bokelley merged commit 7447d00 into main Nov 2, 2026
47 checks passed
@bokelley
bokelley deleted the claude/issue-1784-formats-import-cycle-main branch November 2, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant