from typing import TYPE_CHECKING, Optional from sqlalchemy import Table, Column, ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship from models.base import BaseModel if TYPE_CHECKING: from models import Project project_module = Table( 'project_module', BaseModel.metadata, Column('project_id', ForeignKey('projects.id'), primary_key=True), Column('module_id', ForeignKey('modules.id'), primary_key=True), ) module_dependencies = Table( 'module_dependencies', BaseModel.metadata, Column('module_id', ForeignKey('modules.id'), primary_key=True), Column('depends_on_id', ForeignKey('modules.id'), primary_key=True), ) class Module(BaseModel): __tablename__ = 'modules' id: Mapped[int] = mapped_column(primary_key=True) key: Mapped[str] = mapped_column(unique=True, nullable=False) label: Mapped[str] = mapped_column(nullable=False) icon_name: Mapped[Optional[str]] = mapped_column(unique=True, nullable=False) is_deleted: Mapped[bool] = mapped_column(default=False) depends_on: Mapped[list['Module']] = relationship( 'Module', secondary=module_dependencies, primaryjoin='Module.id == module_dependencies.c.module_id', secondaryjoin='Module.id == module_dependencies.c.depends_on_id', back_populates='depended_on_by', lazy='immediate', ) depended_on_by: Mapped[list['Module']] = relationship( 'Module', secondary='module_dependencies', primaryjoin='Module.id == module_dependencies.c.depends_on_id', secondaryjoin='Module.id == module_dependencies.c.module_id', back_populates='depends_on', lazy='noload', ) projects: Mapped[list['Project']] = relationship( 'Project', uselist=True, secondary='project_module', back_populates='modules', lazy='noload', )