6
0

ExecuteExternalStorage.py 3.6 KB

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