Files
leocrm/app/models/contact.py
T

42 lines
1.8 KiB
Python

"""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__"})