File.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. from __future__ import annotations
  2. import json
  3. import typing as T
  4. from contextlib import closing
  5. from datetime import datetime
  6. from pycs import db
  7. from pycs.database.Result import Result
  8. from pycs.database.Collection import Collection
  9. from pycs.database.base import NamedBaseModel
  10. class File(NamedBaseModel):
  11. # table columns
  12. uuid = db.Column(db.String, nullable=False)
  13. extension = db.Column(db.String, nullable=False)
  14. type = db.Column(db.String, nullable=False)
  15. size = db.Column(db.String, nullable=False)
  16. created = db.Column(db.DateTime, default=datetime.utcnow,
  17. index=True, nullable=False)
  18. path = db.Column(db.String, nullable=False)
  19. frames = db.Column(db.Integer)
  20. fps = db.Column(db.Float)
  21. project_id = db.Column(
  22. db.Integer,
  23. db.ForeignKey("project.id", ondelete="CASCADE"),
  24. nullable=False)
  25. collection_id = db.Column(
  26. db.Integer,
  27. db.ForeignKey("collection.id", ondelete="SET NULL"))
  28. # contraints
  29. __table_args__ = (
  30. db.UniqueConstraint('project_id', 'path'),
  31. )
  32. # relationships to other models
  33. results = db.relationship("Result", backref="file", lazy="dynamic")
  34. serialize_rules = ('-results',)
  35. def serialize(self):
  36. result = super().serialize()
  37. if result["data"] is not None:
  38. result["data"] = json.loads(result["data"])
  39. return result
  40. def set_collection(self, id: T.Optional[int]):
  41. """
  42. set this file's collection
  43. :param id: new collection id
  44. :return:
  45. """
  46. self.collection_id = id
  47. self.commit()
  48. def set_collection_by_reference(self, collection_reference: T.Optional[str]):
  49. """
  50. set this file's collection
  51. :param collection_reference: collection reference
  52. :return:
  53. """
  54. if self.collection_reference is None:
  55. self.set_collection(None)
  56. collection = Collection.query.filter_by(reference=collection_reference).one()
  57. self.collection = collection
  58. self.commit()
  59. def _get_another_file(self, *query) -> T.Optional[File]:
  60. """
  61. get the first file matching the query ordered by descending id
  62. :return: another file or None
  63. """
  64. return self.project.files.filter(*query)\
  65. .order_by(File.id.desc())\
  66. .first()
  67. def next(self) -> T.Optional[File]:
  68. """
  69. get the successor of this file
  70. :return: another file or None
  71. """
  72. query = File.id > self.id
  73. return self._get_another_file(*query)
  74. def previous(self) -> T.Optional[File]:
  75. """
  76. get the predecessor of this file
  77. :return: another file or None
  78. """
  79. query = File.id < self.id
  80. return self._get_another_file(*query)
  81. def next_in_collection(self) -> T.Optional[File]:
  82. """
  83. get the predecessor of this file
  84. :return: another file or None
  85. """
  86. query = File.id > self.id, Collection.id == self.collection_id
  87. return self._get_another_file(*query)
  88. def previous_in_collection(self) -> T.Optional[File]:
  89. """
  90. get the predecessor of this file
  91. :return: another file or None
  92. """
  93. query = File.id < self.id, Collection.id == self.collection_id
  94. return self._get_another_file(*query)
  95. def result(self, id: int) -> T.Optional[Result]:
  96. return self.results.get(id)
  97. def create_result(self, origin, result_type, label, data: T.Optional[dict] = None):
  98. data = data if data is None else json.dumps(data)
  99. result = Result.new(commit=True,
  100. file=self,
  101. origin=origin,
  102. type=result_type,
  103. label=label,
  104. data=data)
  105. return result
  106. def remove_results(self, origin='pipeline'):
  107. results = Result.query.filter(Result.file == self, Result.origin == origin)
  108. results.remove()
  109. return results