6
0

File.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. from contextlib import closing
  2. import os
  3. from json import dumps
  4. from typing import List
  5. from typing import Optional
  6. from pycs.database.Result import Result
  7. class File:
  8. """
  9. database class for files
  10. """
  11. def __init__(self, database, row):
  12. self.database = database
  13. self.identifier = row[0]
  14. self.uuid = row[1]
  15. self.project_id = row[2]
  16. self.collection_id = row[3]
  17. self.type = row[4]
  18. self.name = row[5]
  19. self.extension = row[6]
  20. self.size = row[7]
  21. self.created = row[8]
  22. self.path = row[9]
  23. self.frames = row[10]
  24. self.fps = row[11]
  25. @property
  26. def absolute_path(self):
  27. if os.path.isabs(self.path):
  28. return self.path
  29. return os.path.join(os.getcwd(), self.path)
  30. def project(self):
  31. """
  32. get the project associated with this file
  33. :return: project
  34. """
  35. return self.database.project(self.project_id)
  36. def collection(self):
  37. """
  38. get the collection associated with this file
  39. :return: collection
  40. """
  41. if self.collection_id is None:
  42. return None
  43. return self.database.collection(self.collection_id)
  44. def set_collection(self, collection_id: Optional[int]):
  45. """
  46. set this file's collection
  47. :param collection_id: new collection
  48. :return:
  49. """
  50. with closing(self.database.con.cursor()) as cursor:
  51. cursor.execute('UPDATE files SET collection = ? WHERE id = ?',
  52. (collection_id, self.identifier))
  53. self.collection_id = collection_id
  54. def set_collection_by_reference(self, collection_reference: Optional[str]):
  55. """
  56. set this file's collection
  57. :param collection_reference: collection reference
  58. :return:
  59. """
  60. if collection_reference is None:
  61. self.set_collection(None)
  62. return
  63. with closing(self.database.con.cursor()) as cursor:
  64. cursor.execute('SELECT id FROM collections WHERE reference = ?', [collection_reference])
  65. row = cursor.fetchone()
  66. self.set_collection(row[0] if row is not None else None)
  67. def remove(self) -> None:
  68. """
  69. remove this file from the database
  70. :return:
  71. """
  72. with closing(self.database.con.cursor()) as cursor:
  73. cursor.execute('DELETE FROM files WHERE id = ?', [self.identifier])
  74. def previous(self):
  75. """
  76. get the predecessor of this file
  77. :return: another file
  78. """
  79. with closing(self.database.con.cursor()) as cursor:
  80. cursor.execute('''
  81. SELECT * FROM files WHERE id < ? AND project = ? ORDER BY id DESC LIMIT 1
  82. ''', (self.identifier, self.project_id))
  83. row = cursor.fetchone()
  84. if row is not None:
  85. return File(self.database, row)
  86. return None
  87. def next(self):
  88. """
  89. get the successor of this file
  90. :return: another file
  91. """
  92. with closing(self.database.con.cursor()) as cursor:
  93. cursor.execute('''
  94. SELECT * FROM files WHERE id > ? AND project = ? ORDER BY id ASC LIMIT 1
  95. ''', (self.identifier, self.project_id))
  96. row = cursor.fetchone()
  97. if row is not None:
  98. return File(self.database, row)
  99. return None
  100. def previous_in_collection(self):
  101. """
  102. get the predecessor of this file
  103. :return: another file
  104. """
  105. with closing(self.database.con.cursor()) as cursor:
  106. if self.collection_id is None:
  107. cursor.execute('''
  108. SELECT * FROM files
  109. WHERE id < ? AND project = ? AND collection IS NULL
  110. ORDER BY id DESC
  111. LIMIT 1
  112. ''', (self.identifier, self.project_id))
  113. else:
  114. cursor.execute('''
  115. SELECT * FROM files
  116. WHERE id < ? AND project = ? AND collection = ?
  117. ORDER BY id DESC
  118. LIMIT 1
  119. ''', (self.identifier, self.project_id, self.collection_id))
  120. row = cursor.fetchone()
  121. if row is not None:
  122. return File(self.database, row)
  123. return None
  124. def next_in_collection(self):
  125. """
  126. get the successor of this file
  127. :return: another file
  128. """
  129. with closing(self.database.con.cursor()) as cursor:
  130. if self.collection_id is None:
  131. cursor.execute('''
  132. SELECT * FROM files
  133. WHERE id > ? AND project = ? AND collection IS NULL
  134. ORDER BY id ASC
  135. LIMIT 1
  136. ''', (self.identifier, self.project_id))
  137. else:
  138. cursor.execute('''
  139. SELECT * FROM files
  140. WHERE id > ? AND project = ? AND collection = ?
  141. ORDER BY id ASC
  142. LIMIT 1
  143. ''', (self.identifier, self.project_id, self.collection_id))
  144. row = cursor.fetchone()
  145. if row is not None:
  146. return File(self.database, row)
  147. return None
  148. def results(self) -> List[Result]:
  149. """
  150. get a list of all results associated with this file
  151. :return: list of results
  152. """
  153. with closing(self.database.con.cursor()) as cursor:
  154. cursor.execute('SELECT * FROM results WHERE file = ?', [self.identifier])
  155. return list(map(
  156. lambda row: Result(self.database, row),
  157. cursor.fetchall()
  158. ))
  159. def result(self, identifier) -> Optional[Result]:
  160. """
  161. get a specific result using its unique identifier
  162. :param identifier: unique identifier
  163. :return: result
  164. """
  165. with closing(self.database.con.cursor()) as cursor:
  166. cursor.execute('''
  167. SELECT * FROM results WHERE id = ? AND file = ?
  168. ''', (identifier, self.identifier))
  169. row = cursor.fetchone()
  170. if row is not None:
  171. return Result(self.database, row)
  172. return None
  173. def create_result(self, origin, result_type, label, data=None):
  174. """
  175. create a result
  176. :param origin:
  177. :param result_type:
  178. :param label:
  179. :param data:
  180. :return:
  181. """
  182. if data is not None:
  183. data = dumps(data)
  184. with closing(self.database.con.cursor()) as cursor:
  185. cursor.execute('''
  186. INSERT INTO results (file, origin, type, label, data)
  187. VALUES ( ?, ?, ?, ?, ?)
  188. ''', (self.identifier, origin, result_type, label, data))
  189. return self.result(cursor.lastrowid)
  190. def remove_results(self, origin='pipeline') -> List[Result]:
  191. """
  192. remove all results with the specified origin
  193. :param origin: either 'pipeline' or 'user'
  194. :return: list of removed results
  195. """
  196. with closing(self.database.con.cursor()) as cursor:
  197. cursor.execute('''
  198. SELECT * FROM results WHERE file = ? AND origin = ?
  199. ''', (self.identifier, origin))
  200. results = list(map(lambda row: Result(self.database, row), cursor.fetchall()))
  201. cursor.execute('''
  202. DELETE FROM results WHERE file = ? AND origin = ?
  203. ''', (self.identifier, origin))
  204. return results