12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- from __future__ import annotations
- import typing as T
- from datetime import datetime
- from pycs import db
- from pycs.database.base import NamedBaseModel
- from pycs.database.util import commit_on_return
- def compare_children(start_label: Label, identifier: int) -> bool:
- """ check for cyclic relationships """
- labels_to_check = [start_label]
- while labels_to_check:
- label = labels_to_check.pop(0)
- if label.id == identifier:
- return False
- labels_to_check.extend(label.children)
- return True
- def _label_id():
- return Label.id
- class Label(NamedBaseModel):
- """ DB Model for labels """
- id = db.Column(db.Integer, primary_key=True)
- project_id = db.Column(
- db.Integer,
- db.ForeignKey("project.id", ondelete="CASCADE"),
- nullable=False)
- parent_id = db.Column(
- db.Integer,
- db.ForeignKey("label.id", ondelete="SET NULL"))
- created = db.Column(db.DateTime, default=datetime.utcnow,
- index=True, nullable=False)
- reference = db.Column(db.String)
- hierarchy_level = db.Column(db.String)
- # contraints
- __table_args__ = (
- db.UniqueConstraint('project_id', 'reference'),
- )
- # relationships to other models
- parent = db.relationship("Label",
- backref="children",
- remote_side=_label_id,
- )
- results = db.relationship("Result",
- backref="label",
- passive_deletes=True,
- lazy="dynamic",
- )
- serialize_only = NamedBaseModel.serialize_only + (
- "project_id",
- "parent_id",
- "reference",
- "hierarchy_level",
- # "children",
- )
- @commit_on_return
- def set_parent(self, parent: T.Optional[T.Union[int, str, Label]] = None) -> None:
- """
- set this labels parent
- :param parent: parent label. Can be a reference, an id or a Label instance
- :return:
- """
- parent_id = None
- if parent is not None:
- if isinstance(parent, Label):
- parent_id = parent.id
- elif isinstance(parent, str):
- parent_id = Label.query.filter(Label.reference == parent).one().id
- elif isinstance(parent, int):
- parent_id = parent
- if not compare_children(self, parent_id):
- raise ValueError('Cyclic relationship detected!')
- self.parent_id = parent_id
|