6
0

ExecuteExternalStorage.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import os
  2. from uuid import uuid1
  3. from flask import abort
  4. from flask import make_response
  5. from flask import request
  6. from flask.views import View
  7. from pycs import db
  8. from pycs.database.Project import Project
  9. from pycs.frontend.notifications.NotificationManager import NotificationManager
  10. from pycs.jobs.JobGroupBusyException import JobGroupBusyException
  11. from pycs.jobs.JobRunner import JobRunner
  12. from pycs.util.FileParser import file_info
  13. class ExecuteExternalStorage(View):
  14. """
  15. find media files stored in a projects data_folder
  16. """
  17. # pylint: disable=arguments-differ
  18. methods = ['POST']
  19. def __init__(self, nm: NotificationManager, jobs: JobRunner):
  20. # pylint: disable=invalid-name
  21. self.nm = nm
  22. self.jobs = jobs
  23. def dispatch_request(self, identifier):
  24. # extract request data
  25. data = request.get_json(force=True)
  26. if not data.get('execute', False):
  27. return abort(400)
  28. # find project
  29. project = Project.query.get(identifier)
  30. if project is None:
  31. return abort(404)
  32. if not project.external_data:
  33. return abort(400)
  34. # execute label provider and add labels to project
  35. try:
  36. self.find_media_files(self.nm, self.jobs, project)
  37. except JobGroupBusyException:
  38. return abort(400)
  39. return make_response()
  40. @staticmethod
  41. def find_media_files(nm: NotificationManager, jobs: JobRunner, project: Project):
  42. """
  43. start a job that finds media files in the projects data_folder and adds them to the
  44. database afterwards
  45. :param nm: notification manager object
  46. :param jobs: job runner object
  47. :param project: project
  48. :return:
  49. """
  50. data_folder = project.data_folder
  51. project_id = project.id
  52. # pylint: disable=invalid-name
  53. # find lists the given data folder and prepares item dictionaries
  54. def find():
  55. files = os.listdir(data_folder)
  56. length = len(files)
  57. elements = []
  58. current = 0
  59. for file_name in files:
  60. file_path = os.path.join(data_folder, file_name)
  61. if not os.path.isfile(file_path):
  62. continue
  63. file_name, file_extension = os.path.splitext(file_name)
  64. file_size = os.path.getsize(file_path)
  65. try:
  66. ftype, frames, fps = file_info(data_folder, file_name, file_extension)
  67. except ValueError:
  68. continue
  69. elements.append((ftype, file_name, file_extension, file_size, frames, fps))
  70. current += 1
  71. if len(elements) >= 200:
  72. yield elements, current, length
  73. elements = []
  74. if len(elements) > 0:
  75. yield elements, current, length
  76. # progress inserts elements into the database and fires events
  77. def progress(elements, current, length):
  78. with db.session.start():
  79. project = Project.query.get(project_id)
  80. for ftype, file_name, file_extension, file_size, frames, fps in elements:
  81. file, is_new = project.add_file(str(uuid1()), ftype, file_name,
  82. file_extension, file_size, file_name,
  83. frames, fps)
  84. if is_new:
  85. nm.create_file(file.id)
  86. return current / length
  87. # run job with given functions
  88. jobs.run(project,
  89. 'Find Media Files',
  90. project.name,
  91. f'{project.id}/find-files',
  92. find,
  93. progress=progress)