CreateProject.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. from contextlib import closing
  2. from os import mkdir
  3. from os import path
  4. from shutil import copytree
  5. from uuid import uuid1
  6. from flask import make_response, request, abort
  7. from flask.views import View
  8. from pycs.database.Database import Database
  9. from pycs.frontend.endpoints.projects.ExecuteExternalStorage import ExecuteExternalStorage
  10. from pycs.frontend.endpoints.projects.ExecuteLabelProvider import ExecuteLabelProvider
  11. from pycs.frontend.notifications.NotificationManager import NotificationManager
  12. from pycs.jobs.JobRunner import JobRunner
  13. from pycs.util.PipelineUtil import load_from_root_folder as load_pipeline
  14. class CreateProject(View):
  15. """
  16. create a project, insert data into database and create directories
  17. """
  18. # pylint: disable=arguments-differ
  19. methods = ['POST']
  20. def __init__(self, db: Database, nm: NotificationManager, jobs: JobRunner):
  21. # pylint: disable=invalid-name
  22. self.db = db
  23. self.nm = nm
  24. self.jobs = jobs
  25. def dispatch_request(self):
  26. # extract request data
  27. data = request.get_json(force=True)
  28. name = data['name']
  29. description = data['description']
  30. # start transaction
  31. with self.db:
  32. # find model
  33. model_id = int(data['model'])
  34. model = self.db.model(model_id)
  35. if model is None:
  36. abort(404)
  37. # find label provider
  38. if data['label'] is None:
  39. label_provider = None
  40. else:
  41. label_provider_id = int(data['label'])
  42. label_provider = self.db.label_provider(label_provider_id)
  43. if label_provider is None:
  44. abort(404)
  45. # create project folder
  46. project_folder = path.join('projects', str(uuid1()))
  47. mkdir(project_folder)
  48. temp_folder = path.join(project_folder, 'temp')
  49. mkdir(temp_folder)
  50. # check project data directory
  51. if data['external'] is None:
  52. external_data = False
  53. data_folder = path.join(project_folder, 'data')
  54. mkdir(data_folder)
  55. else:
  56. external_data = True
  57. data_folder = data['external']
  58. # check if exists
  59. if not path.exists(data_folder):
  60. return abort(400)
  61. # copy model to project folder
  62. model_folder = path.join(project_folder, 'model')
  63. copytree(model.root_folder, model_folder)
  64. model, _ = model.copy_to(f'{model.name} ({name})', model_folder)
  65. # create entry in database
  66. created = self.db.create_project(name, description, model, label_provider,
  67. project_folder, external_data, data_folder)
  68. # execute label provider and add labels to project
  69. if label_provider is not None:
  70. ExecuteLabelProvider.execute_label_provider(self.db, self.nm, self.jobs, created,
  71. label_provider)
  72. # load model and add collections to the project
  73. def load_model_and_get_collections():
  74. with closing(load_pipeline(model.root_folder)) as pipeline:
  75. return pipeline.collections()
  76. def add_collections_to_project(provided_collections):
  77. with self.db:
  78. for position, collection in enumerate(provided_collections):
  79. created.create_collection(collection['reference'],
  80. collection['name'],
  81. collection['description'],
  82. position + 1,
  83. collection['autoselect'])
  84. self.jobs.run(created,
  85. 'Media Collections',
  86. f'{created.name}',
  87. f'{created.identifier}/media-collections',
  88. executable=load_model_and_get_collections,
  89. result=add_collections_to_project)
  90. # find media files
  91. if external_data:
  92. ExecuteExternalStorage.find_media_files(self.db, self.nm, self.jobs, created)
  93. # fire event
  94. self.nm.create_model(model)
  95. self.nm.create_project(created)
  96. # return success response
  97. return make_response()