ExecuteLabelProvider.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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, project_id: int):
  23. project = Project.get_or_404(project_id)
  24. # extract request data
  25. data = request.get_json(force=True)
  26. if not data.get('execute', False):
  27. abort(400, "execute flag is missing")
  28. # get label provider
  29. label_provider = project.label_provider
  30. if label_provider is None:
  31. abort(400, "This project does not have a label provider.")
  32. # execute label provider and add labels to project
  33. try:
  34. self.execute_label_provider(self.nm, self.jobs, project, label_provider)
  35. except JobGroupBusyException:
  36. abort(400, "Label provider already running.")
  37. return make_response()
  38. @staticmethod
  39. def execute_label_provider(nm: NotificationManager, jobs: JobRunner,
  40. project: Project, label_provider: LabelProvider):
  41. """
  42. start a job that loads and executes a label provider and saves its results to the
  43. database afterwards
  44. :param nm: notification manager object
  45. :param jobs: job runner object
  46. :param project: project
  47. :param label_provider: label provider
  48. :return:
  49. """
  50. # pylint: disable=invalid-name
  51. # receive loads and executes the given label provider
  52. def receive():
  53. with closing(label_provider.load()) as label_provider_impl:
  54. return label_provider_impl.get_labels()
  55. project_id = project.id
  56. # result adds the received labels to the database and fires events
  57. def result(provided_labels):
  58. nonlocal project_id
  59. def _inner(labels, project_id):
  60. project = Project.query.get(project_id)
  61. labels = project.bulk_create_labels(labels)
  62. for label in labels:
  63. nm.create_label(label)
  64. if db.session().in_transaction():
  65. _inner(provided_labels, project_id)
  66. else:
  67. with db.session.begin():
  68. _inner(provided_labels, project_id)
  69. # run job with given functions
  70. jobs.run(project,
  71. 'Label Provider',
  72. f'{project.name} ({label_provider.name})',
  73. f'{project.id}/label-provider',
  74. receive,
  75. result=result)