from contextlib import closing from os import mkdir from os import path from shutil import copytree from uuid import uuid1 from pathlib import Path from flask import make_response, request, abort from flask.views import View from pycs import app from pycs.database.Database import Database from pycs.database.Project import Project from pycs.frontend.endpoints.projects.ExecuteExternalStorage import ExecuteExternalStorage from pycs.frontend.endpoints.projects.ExecuteLabelProvider import ExecuteLabelProvider from pycs.frontend.notifications.NotificationManager import NotificationManager from pycs.jobs.JobRunner import JobRunner from pycs.util.PipelineUtil import load_from_root_folder as load_pipeline class CreateProject(View): """ create a project, insert data into database and create directories """ # pylint: disable=arguments-differ methods = ['POST'] def __init__(self, db: Database, nm: NotificationManager, jobs: JobRunner): # pylint: disable=invalid-name self.db = db self.nm = nm self.jobs = jobs @property def project_folder(self): return app.config["TEST_PROJECTS_DIR"] if app.config["TESTING"] else 'projects' def dispatch_request(self): # extract request data data = request.get_json(force=True) if None in [data.get('name'), data.get('description')]: return abort(400, "name and description information missing!") name = data['name'] description = data['description'] model_id = data['model'] label_provider_id = data['label'] data_folder = data['external'] external_data = data_folder is not None # start transaction with self.db: # find model model = self.db.model(int(model_id)) if model is None: return abort(404, "Model not found") # find label provider if label_provider_id is None: label_provider = None else: label_provider = self.db.label_provider(int(label_provider_id)) if label_provider is None: return abort(404, "Label provider not found") # create project folder project_folder = Path(self.project_folder, str(uuid1())) project_folder.mkdir(parents=True) temp_folder = project_folder / 'temp' temp_folder.mkdir() # check project data directory if external_data: # check if exists if not path.exists(data_folder): return abort(400, "Data folder does not exist!") else: data_folder = project_folder / 'data' data_folder.mkdir() # copy model to project folder model_folder = project_folder / 'model' copytree(model.root_folder, str(model_folder)) model, _ = model.copy_to(f'{model.name} ({name})', str(model_folder)) # create entry in database project = self.db.create_project(name, description, model, label_provider, str(project_folder), external_data, str(data_folder)) # execute label provider and add labels to project if label_provider is not None: ExecuteLabelProvider.execute_label_provider(self.db, self.nm, self.jobs, project, label_provider) # load model and add collections to the project def load_model_and_get_collections(): with closing(load_pipeline(model.root_folder)) as pipeline: return pipeline.collections() project_id = project.id def add_collections_to_project(provided_collections): project = Project.query.get(project_id) with self.db: for position, collection in enumerate(provided_collections): project.create_collection(collection['reference'], collection['name'], collection['description'], position + 1, collection['autoselect']) self.jobs.run(project, 'Media Collections', f'{project.name}', f'{project.id}/media-collections', executable=load_model_and_get_collections, result=add_collections_to_project) # find media files if external_data: ExecuteExternalStorage.find_media_files(self.db, self.nm, self.jobs, project) # fire event self.nm.create_model(model.id) self.nm.create_project(project.id) # return success response return make_response()