6
0

Label.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. from __future__ import annotations
  2. from contextlib import closing
  3. from datetime import datetime
  4. from pycs import db
  5. from pycs.database.base import NamedBaseModel
  6. def compare_children(start_label: Label, id: int):
  7. """ check for cyclic relationships """
  8. labels_to_check = [start_label]
  9. while id is not None and labels_to_check:
  10. label = labels_to_check.pop(0)
  11. if label.id == id:
  12. return False
  13. labels_to_check.extend(label.children)
  14. return True
  15. def _Label_id():
  16. return Label.id
  17. class Label(NamedBaseModel):
  18. project_id = db.Column(
  19. db.Integer,
  20. db.ForeignKey("project.id", ondelete="CASCADE"),
  21. nullable=False)
  22. parent_id = db.Column(
  23. db.Integer,
  24. db.ForeignKey("label.id", ondelete="SET NULL"))
  25. created = db.Column(db.DateTime, default=datetime.utcnow,
  26. index=True, nullable=False)
  27. reference = db.Column(db.String)
  28. hierarchy_level = db.Column(db.String)
  29. # contraints
  30. __table_args__ = (
  31. db.UniqueConstraint('project_id', 'reference'),
  32. )
  33. # relationships to other models
  34. parent = db.relationship("Label",
  35. backref="children",
  36. remote_side=_Label_id,
  37. )
  38. results = db.relationship("Result",
  39. backref="label",
  40. passive_deletes=True,
  41. lazy="dynamic",
  42. )
  43. serialize_only = (
  44. "id",
  45. "name",
  46. "project_id",
  47. "parent_id",
  48. "reference",
  49. "children",
  50. )
  51. def set_parent(self, parent_id: int, commit: bool = True):
  52. """
  53. set this labels parent
  54. :param parent_id: parent's id
  55. :return:
  56. """
  57. if not compare_children(self, parent_id):
  58. raise ValueError('Cyclic relationship detected!')
  59. self.parent_id = parent_id
  60. if commit:
  61. self.commit()