ProjectManager.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from glob import glob
  2. from json import load, dump
  3. from os import path, mkdir
  4. from shutil import rmtree
  5. from time import time
  6. from uuid import uuid1
  7. from eventlet import spawn_after
  8. from pycs import ApplicationStatus
  9. from pycs.observable import ObservableDict
  10. from pycs.pipeline.PipelineManager import PipelineManager
  11. from pycs.projects.Project import Project
  12. class ProjectManager(ObservableDict):
  13. DEFAULT_PIPELINE_TIMEOUT = 120
  14. def __init__(self, app_status: ApplicationStatus):
  15. self.pipeline_manager = None
  16. self.quit_pipeline_thread = None
  17. # TODO create projects folder if it does not exist
  18. self.app_status = app_status
  19. # initialize observable dict with no keys and
  20. # app_status object as parent
  21. super().__init__({}, app_status)
  22. app_status['projects'] = self
  23. # find projects
  24. for folder in glob('projects/*'):
  25. # load project.json
  26. with open(path.join(folder, 'project.json'), 'r') as file:
  27. project = Project(load(file), self)
  28. self[project['id']] = project
  29. def write_project(self, uuid):
  30. with open(path.join('projects', uuid, 'project.json'), 'w') as file:
  31. copy = self[uuid].copy()
  32. del copy['jobs']
  33. dump(copy, file, indent=4)
  34. def create_project(self, name, description, model):
  35. # create dict representation
  36. uuid = str(uuid1())
  37. self[uuid] = Project({
  38. 'id': uuid,
  39. 'name': name,
  40. 'description': description,
  41. 'created': int(time()),
  42. 'pipeline': {
  43. 'model-distribution': model
  44. },
  45. 'data': {},
  46. 'labels': {},
  47. 'jobs': {}
  48. }, self)
  49. # create project directory
  50. folder = path.join('projects', uuid)
  51. mkdir(folder)
  52. # create project.json
  53. self.write_project(uuid)
  54. def update_project(self, uuid, update):
  55. # abort if uuid is no valid key
  56. if uuid not in self.keys():
  57. return
  58. # set values and write to disk
  59. self[uuid].update_properties(update)
  60. self.write_project(uuid)
  61. def delete_project(self, uuid):
  62. # abort if uuid is no valid key
  63. if uuid not in self.keys():
  64. return
  65. # delete project folder
  66. folder = path.join('projects', uuid)
  67. rmtree(folder)
  68. # delete project data
  69. del self[uuid]
  70. def predict(self, uuid, identifiers):
  71. # abort if uuid is no valid key
  72. if uuid not in self.keys():
  73. return
  74. project = self[uuid]
  75. # abort pipeline termination
  76. if self.quit_pipeline_thread is not None:
  77. self.quit_pipeline_thread.cancel()
  78. self.quit_pipeline_thread = None
  79. # create pipeline if it does not exist already
  80. if self.pipeline_manager is None:
  81. # abort if pipeline id is no valid key
  82. pipeline_identifier = project['pipeline']['model-distribution']
  83. pipeline = self.parent['models'][pipeline_identifier]
  84. self.pipeline_manager = PipelineManager(project, pipeline)
  85. # run jobs
  86. for file_id in identifiers:
  87. if file_id in project['data'].keys():
  88. self.pipeline_manager.run(project['data'][file_id])
  89. # quit timeout thread
  90. if self.quit_pipeline_thread is not None:
  91. self.quit_pipeline_thread.cancel()
  92. self.quit_pipeline_thread = None
  93. # schedule timeout thread
  94. self.quit_pipeline_thread = spawn_after(self.DEFAULT_PIPELINE_TIMEOUT, self.__quit_pipeline)
  95. def __quit_pipeline(self):
  96. if self.pipeline_manager is not None:
  97. self.pipeline_manager.close()
  98. self.pipeline_manager = None
  99. self.quit_pipeline_thread = None