Label.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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 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. class Label(NamedBaseModel):
  16. id = db.Column(db.Integer, primary_key=True)
  17. project_id = db.Column(
  18. db.Integer,
  19. db.ForeignKey("project.id", ondelete="CASCADE"),
  20. nullable=False)
  21. parent_id = db.Column(
  22. db.Integer,
  23. db.ForeignKey("label.id", ondelete="SET NULL"))
  24. created = db.Column(db.DateTime, default=datetime.utcnow,
  25. index=True, nullable=False)
  26. reference = db.Column(db.String)
  27. # contraints
  28. __table_args__ = (
  29. db.UniqueConstraint('project_id', 'reference'),
  30. )
  31. # relationships to other models
  32. parent = db.relationship("Label",
  33. backref="children",
  34. remote_side=[id],
  35. )
  36. serialize_only = (
  37. "id",
  38. "name",
  39. "project_id",
  40. "parent_id",
  41. "reference",
  42. )
  43. def set_parent(self, parent_id: int):
  44. """
  45. set this labels parent
  46. :param parent_id: parent's id
  47. :return:
  48. """
  49. if not compare_children(self, parent_id):
  50. raise ValueError('Cyclic relationship detected!')
  51. self.parent_id = parent_id
  52. self.commit()