6
0

CreateProject.py 4.9 KB

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