File.py 4.1 KB

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