Coverage for postrfp/model/graph.py: 96%
26 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-22 21:34 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-22 21:34 +0000
1from typing import Optional
3from sqlalchemy import ForeignKey
4from sqlalchemy.orm import relationship, Mapped, mapped_column
5from sqlalchemy.types import VARCHAR
6from sqlalchemy.sql.sqltypes import Integer
8from .humans import Organisation
9from .meta import Base
12class RelationshipType(Base):
13 __tablename__ = "relationship_types"
15 org_id: Mapped[Optional[str]] = mapped_column(
16 VARCHAR(length=50),
17 ForeignKey("organisations.id", onupdate="CASCADE", ondelete="CASCADE"),
18 nullable=True,
19 )
20 name: Mapped[str] = mapped_column(VARCHAR(length=128))
21 description: Mapped[Optional[str]] = mapped_column(
22 VARCHAR(length=256), nullable=True
23 )
25 organisation = relationship(
26 Organisation,
27 primaryjoin=org_id == Organisation.id,
28 back_populates="relationship_types",
29 )
31 edges = relationship(
32 "Edge",
33 back_populates="relationship_type",
34 cascade="all, delete",
35 passive_deletes=True,
36 )
38 def __repr__(self) -> str:
39 return f'<RelationshipType - "{self.name}" #{self.id}>'
42class Edge(Base):
43 __tablename__ = "edges"
45 id = None # type: ignore
47 from_org_id: Mapped[str] = mapped_column(
48 VARCHAR(length=50),
49 ForeignKey("organisations.id", onupdate="CASCADE"),
50 primary_key=True,
51 nullable=False,
52 )
54 to_org_id: Mapped[str] = mapped_column(
55 VARCHAR(length=50),
56 ForeignKey("organisations.id", onupdate="CASCADE"),
57 primary_key=True,
58 nullable=False,
59 )
61 relationship_id: Mapped[int] = mapped_column(
62 Integer,
63 ForeignKey("relationship_types.id", ondelete="CASCADE"),
64 primary_key=True,
65 nullable=False,
66 )
68 relationship_type = relationship(
69 RelationshipType, back_populates="edges", uselist=False, lazy="joined"
70 )
72 from_org = relationship(
73 Organisation,
74 primaryjoin=from_org_id == Organisation.id,
75 back_populates="lower_edges",
76 lazy="joined",
77 )
79 to_org = relationship(
80 Organisation,
81 primaryjoin=to_org_id == Organisation.id,
82 back_populates="higher_edges",
83 lazy="joined",
84 )
86 @property
87 def relationship(self) -> str:
88 return self.relationship_type.name
90 def __repr__(self) -> str:
91 return f'<Edge - "{self.from_org_id}" to "{self.to_org_id}">'