Coverage for dj/models/attribute.py: 100%
31 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-17 20:05 -0700
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-17 20:05 -0700
1"""
2Models for attributes.
3"""
4import enum
5from typing import TYPE_CHECKING, List, Optional
7from sqlalchemy import JSON, String, UniqueConstraint
8from sqlalchemy.sql.schema import Column as SqlaColumn
9from sqlmodel import Field, Relationship
11from dj.models.base import BaseSQLModel
12from dj.models.node import NodeType
14if TYPE_CHECKING:
15 from dj.models import Column
18RESERVED_ATTRIBUTE_NAMESPACE = "system"
21class MutableAttributeTypeFields(BaseSQLModel):
22 """
23 Fields on attribute types that users can set.
24 """
26 namespace: str
27 name: str = Field(sa_column=SqlaColumn("name", String))
28 description: str
29 allowed_node_types: List[NodeType] = Field(sa_column=SqlaColumn(JSON))
32class UniquenessScope(str, enum.Enum):
33 """
34 The scope at which this attribute needs to be unique.
35 """
37 NODE = "node"
38 COLUMN_TYPE = "column_type"
41class RestrictedAttributeTypeFields(BaseSQLModel):
42 """
43 Fields on attribute types that aren't configurable by users.
44 """
46 uniqueness_scope: List[UniquenessScope] = Field(
47 default=[],
48 sa_column=SqlaColumn(JSON),
49 )
52class AttributeTypeBase(MutableAttributeTypeFields, RestrictedAttributeTypeFields):
53 """Base attribute type."""
56class AttributeType(AttributeTypeBase, table=True): # type: ignore # pylint: disable=too-many-ancestors
57 """
58 Available attribute types for column metadata.
59 """
61 __table_args__ = (UniqueConstraint("namespace", "name"),)
63 id: Optional[int] = Field(default=None, primary_key=True)
65 def __hash__(self):
66 return hash(self.id)
69class ColumnAttribute(BaseSQLModel, table=True): # type: ignore
70 """
71 Column attributes.
72 """
74 __table_args__ = (UniqueConstraint("attribute_type_id", "column_id"),)
76 id: Optional[int] = Field(default=None, primary_key=True)
77 attribute_type_id: Optional[int] = Field(
78 default=None,
79 foreign_key="attributetype.id",
80 )
81 attribute_type: AttributeType = Relationship()
83 column_id: Optional[int] = Field(default=None, foreign_key="column.id")
84 column: "Column" = Relationship(back_populates="attributes")