6
0

ExecuteLabelProvider.py 3.2 KB

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