6
0

CreateProject.py 4.6 KB

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