6
0

ExecuteExternalStorage.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. from os import listdir
  2. from os import path
  3. from os.path import isfile
  4. from uuid import uuid1
  5. from flask import make_response, request, abort
  6. from flask.views import View
  7. from pycs.database.Database import Database
  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, db: Database, nm: NotificationManager, jobs: JobRunner):
  20. # pylint: disable=invalid-name
  21. self.db = db
  22. self.nm = nm
  23. self.jobs = jobs
  24. def dispatch_request(self, identifier):
  25. # extract request data
  26. data = request.get_json(force=True)
  27. if 'execute' not in data or data['execute'] is not True:
  28. return abort(400)
  29. # find project
  30. project = self.db.project(identifier)
  31. if project is None:
  32. return abort(404)
  33. if not project.external_data:
  34. return abort(400)
  35. # execute label provider and add labels to project
  36. try:
  37. self.find_media_files(self.db, self.nm, self.jobs, project)
  38. except JobGroupBusyException:
  39. return abort(400)
  40. return make_response()
  41. @staticmethod
  42. def find_media_files(db: Database, nm: NotificationManager, jobs: JobRunner, project: Project):
  43. """
  44. start a job that finds media files in the projects data_folder and adds them to the
  45. database afterwards
  46. :param db: database object
  47. :param nm: notification manager object
  48. :param jobs: job runner object
  49. :param project: project
  50. :return:
  51. """
  52. # pylint: disable=invalid-name
  53. # find lists the given data folder and prepares item dictionaries
  54. def find():
  55. files = listdir(project.data_folder)
  56. length = len(files)
  57. elements = []
  58. current = 0
  59. for file_name in files:
  60. file_path = path.join(project.data_folder, file_name)
  61. if not isfile(file_path):
  62. continue
  63. file_name, file_extension = path.splitext(file_name)
  64. file_size = path.getsize(file_path)
  65. try:
  66. ftype, frames, fps = file_info(project.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:
  79. for ftype, file_name, file_extension, file_size, frames, fps in elements:
  80. uuid = str(uuid1())
  81. file, insert = project.add_file(uuid, ftype, file_name, file_extension,
  82. file_size, file_name, frames, fps)
  83. if insert:
  84. nm.create_file(file)
  85. return current / length
  86. # run job with given functions
  87. jobs.run(project,
  88. 'Find Media Files',
  89. project.name,
  90. f'{project.identifier}/find-files',
  91. find,
  92. progress=progress)