123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import os
- import uuid
- from flask import abort
- from flask import make_response
- from flask import request
- from flask.views import View
- from pycs import db
- from pycs.database.Project import Project
- from pycs.frontend.notifications.NotificationManager import NotificationManager
- from pycs.jobs.JobGroupBusyException import JobGroupBusyException
- from pycs.jobs.JobRunner import JobRunner
- from pycs.util.FileOperations import file_info
- class ExecuteExternalStorage(View):
- """
- find media files stored in a projects data_folder
- """
- # pylint: disable=arguments-differ
- methods = ['POST']
- def __init__(self, nm: NotificationManager, jobs: JobRunner):
- # pylint: disable=invalid-name
- self.nm = nm
- self.jobs = jobs
- def dispatch_request(self, project_id: int):
- # extract request data
- data = request.get_json(force=True)
- if not data.get('execute', False):
- return abort(400)
- # find project
- project = Project.get_or_404(project_id)
- if not project.external_data:
- return abort(400, "External data is not set!")
- # execute label provider and add labels to project
- try:
- ExecuteExternalStorage.find_media_files(self.nm, self.jobs, project)
- except JobGroupBusyException:
- return abort(400, "Job is already running!")
- return make_response()
- @staticmethod
- def find_media_files(nm: NotificationManager, jobs: JobRunner, project: Project):
- """
- start a job that finds media files in the projects data_folder and adds them to the
- database afterwards
- :param nm: notification manager object
- :param jobs: job runner object
- :param project: project
- :return:
- """
- # pylint: disable=invalid-name
- # find lists the given data folder and prepares item dictionaries
- def find(data_folder):
- files = os.listdir(data_folder)
- length = len(files)
- elements = []
- current = 0
- for file_name in files:
- file_path = os.path.join(data_folder, file_name)
- if not os.path.isfile(file_path):
- continue
- file_name, file_extension = os.path.splitext(file_name)
- file_size = os.path.getsize(file_path)
- try:
- ftype, frames, fps = file_info(data_folder, file_name, file_extension)
- except ValueError:
- continue
- file_attrs = dict(
- uuid=str(uuid.uuid1()),
- file_type=ftype,
- name=file_name,
- extension=file_extension,
- size=file_size,
- frames=frames,
- fps=fps)
- elements.append(file_attrs)
- current += 1
- if len(elements) >= 200:
- yield elements, current, length
- elements = []
- if len(elements) > 0:
- yield elements, current, length
- # progress inserts elements into the database and fires events
- def progress(elements, current, length):
- with db.session.begin_nested():
- for file_attrs in elements:
- file, is_new = project.add_file(commit=False, **file_attrs)
- if is_new:
- nm.create_file(file)
- return current / length
- # run job with given functions
- jobs.run(project,
- 'Find Media Files',
- project.name,
- f'{project.id}/find-files',
- find, project.data_folder,
- progress=progress)
|