6
0

File.py 4.3 KB

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