ExecuteLabelProvider.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. from contextlib import closing
  2. from flask import abort
  3. from flask import make_response
  4. from flask import request
  5. from flask.views import View
  6. from pycs import db
  7. from pycs.database.LabelProvider import LabelProvider
  8. from pycs.database.Project import Project
  9. from pycs.frontend.notifications.NotificationManager import NotificationManager
  10. from pycs.jobs.JobGroupBusyException import JobGroupBusyException
  11. from pycs.jobs.JobRunner import JobRunner
  12. class ExecuteLabelProvider(View):
  13. """
  14. execute the label provider associated with a passed project identifier
  15. """
  16. # pylint: disable=arguments-differ
  17. methods = ['POST']
  18. def __init__(self, nm: NotificationManager, jobs: JobRunner):
  19. # pylint: disable=invalid-name
  20. self.nm = nm
  21. self.jobs = jobs
  22. def dispatch_request(self, identifier):
  23. # extract request data
  24. data = request.get_json(force=True)
  25. if 'execute' not in data or data['execute'] is not True:
  26. return abort(400)
  27. # find project
  28. project = Project.query.get(identifier)
  29. if project is None:
  30. return abort(404)
  31. # get label provider
  32. label_provider = project.label_provider
  33. if label_provider is None:
  34. return abort(400)
  35. # execute label provider and add labels to project
  36. try:
  37. self.execute_label_provider(self.nm, self.jobs, project, label_provider)
  38. except JobGroupBusyException:
  39. return abort(400)
  40. return make_response()
  41. @staticmethod
  42. def execute_label_provider(nm: NotificationManager, jobs: JobRunner,
  43. project: Project, label_provider: LabelProvider):
  44. """
  45. start a job that loads and executes a label provider and saves its results to the
  46. database afterwards
  47. :param nm: notification manager object
  48. :param jobs: job runner object
  49. :param project: project
  50. :param label_provider: label provider
  51. :return:
  52. """
  53. # pylint: disable=invalid-name
  54. # receive loads and executes the given label provider
  55. def receive():
  56. with closing(label_provider.load()) as label_provider_impl:
  57. provided_labels = label_provider_impl.get_labels()
  58. return provided_labels
  59. project_id = project.id
  60. # result adds the received labels to the database and fires events
  61. def result(provided_labels):
  62. project = Project.query.get(project_id)
  63. for label in provided_labels:
  64. success = False
  65. with db.session.begin_nested():
  66. created_label, is_new = project.create_label(commit=False, **label)
  67. success = True
  68. if not success:
  69. continue
  70. if is_new:
  71. nm.create_label(created_label.id)
  72. else:
  73. nm.edit_label(created_label.id)
  74. # run job with given functions
  75. jobs.run(project,
  76. 'Label Provider',
  77. f'{project.name} ({label_provider.name})',
  78. f'{project.id}/label-provider',
  79. receive,
  80. result=result)