Coverage for dj/models/tag.py: 100%
27 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 tags.
3"""
4from typing import TYPE_CHECKING, Any, Dict, List, Optional
6from pydantic import Extra
7from sqlalchemy import String
8from sqlalchemy.sql.schema import Column as SqlaColumn
9from sqlmodel import JSON, Field, Relationship
11from dj.models.base import BaseSQLModel, generate_display_name
13if TYPE_CHECKING:
14 from dj.models.node import Node
17class MutableTagFields(BaseSQLModel):
18 """
19 Tag fields that can be changed.
20 """
22 description: str
23 tag_metadata: Dict[str, Any] = Field(default={}, sa_column=SqlaColumn(JSON))
25 class Config: # pylint: disable=too-few-public-methods
26 """
27 Allow types for tag metadata.
28 """
30 arbitrary_types_allowed = True
33class ImmutableTagFields(BaseSQLModel):
34 """
35 Tag fields that cannot be changed.
36 """
38 name: str = Field(sa_column=SqlaColumn("name", String, unique=True))
39 display_name: Optional[str] = Field(
40 sa_column=SqlaColumn(
41 "display_name",
42 String,
43 default=generate_display_name("name"),
44 ),
45 )
46 tag_type: str
49class TagNodeRelationship(BaseSQLModel, table=True): # type: ignore
50 """
51 Join table between tags and nodes
52 """
54 tag_id: Optional[int] = Field(
55 default=None,
56 foreign_key="tag.id",
57 primary_key=True,
58 )
59 node_id: Optional[int] = Field(
60 default=None,
61 foreign_key="node.id",
62 primary_key=True,
63 )
66class Tag(ImmutableTagFields, MutableTagFields, table=True): # type: ignore
67 """
68 A tag.
69 """
71 id: Optional[int] = Field(default=None, primary_key=True)
72 nodes: List["Node"] = Relationship(
73 back_populates="tags",
74 link_model=TagNodeRelationship,
75 sa_relationship_kwargs={
76 "primaryjoin": "TagNodeRelationship.tag_id==Tag.id",
77 "secondaryjoin": "TagNodeRelationship.node_id==Node.id",
78 },
79 )
82class CreateTag(ImmutableTagFields, MutableTagFields):
83 """
84 Create tag model.
85 """
88class TagOutput(ImmutableTagFields, MutableTagFields):
89 """
90 Output tag model.
91 """
94class UpdateTag(MutableTagFields):
95 """
96 Update tag model. Only works on mutable fields.
97 """
99 __annotations__ = {
100 k: Optional[v]
101 for k, v in {
102 **MutableTagFields.__annotations__, # pylint: disable=E1101
103 }.items()
104 }
106 class Config: # pylint: disable=too-few-public-methods
107 """
108 Do not allow fields other than the ones defined here.
109 """
111 extra = Extra.forbid