"""Contact model - backwards-compatibility re-export (Paket 6, #357). The physical home of Contact/ContactPerson moved to the ContactsPlugin: app/plugins.builtins.contacts.models This module re-exports both classes lazily (PEP 562 ``__getattr__``) so every existing import keeps working - ``from app.models.contact import Contact`` resolves at attribute-access time: - alembic/env.py (``from app.models import *`` -> Base.metadata stays complete; Autogenerate never sees the tables as removed) - Core services (worker.py, jobs.py, address_service.py, ...) - 19 test files and scripts Why LAZY and not a top-level import: app/models/__init__.py is imported very early (app.core.auth imports app.models.session). A top-level plugin import here would pull in app.plugins -> registry -> service_container -> cache -> app.core.auth while app.core.auth is still initializing -> circular ImportError (proven in the Paket 6 red run). With PEP 562 the plugin framework is only touched when Contact is actually accessed, long after app.models finished initializing - every entry order is cycle-free. The cross-plugin checker (scripts/check_cross_plugin_imports.py) lists this file in EXEMPT_PATHS: the re-export is the deliberate, documented bridge - the plugin OWNS the model; the core only mirrors it for import stability. """ from __future__ import annotations _EXPORTS = {"Contact", "ContactPerson"} def __getattr__(name: str): if name in _EXPORTS: from app.plugins.builtins.contacts.models import Contact, ContactPerson return {"Contact": Contact, "ContactPerson": ContactPerson}[name] raise AttributeError(f"module {__name__!r} has no attribute {name!r}") def __dir__() -> list[str]: return sorted(_EXPORTS | {"__getattr__", "__dir__"})