from contextlib import closing from flask import make_response, request, abort from flask.views import View from pycs.database.Database import Database from pycs.database.LabelProvider import LabelProvider from pycs.database.Project import Project from pycs.frontend.notifications.NotificationManager import NotificationManager from pycs.jobs.JobGroupBusyException import JobGroupBusyException from pycs.jobs.JobRunner import JobRunner class ExecuteLabelProvider(View): """ execute the label provider associated with a passed project identifier """ # pylint: disable=arguments-differ methods = ['POST'] def __init__(self, db: Database, nm: NotificationManager, jobs: JobRunner): # pylint: disable=invalid-name self.db = db self.nm = nm self.jobs = jobs def dispatch_request(self, identifier): # extract request data data = request.get_json(force=True) if 'execute' not in data or data['execute'] is not True: return abort(400) # find project project = self.db.project(identifier) if project is None: return abort(404) # get label provider label_provider = project.label_provider() if label_provider is None: return abort(400) # execute label provider and add labels to project try: self.execute_label_provider(self.db, self.nm, self.jobs, project, label_provider) except JobGroupBusyException: return abort(400) return make_response() @staticmethod def execute_label_provider(db: Database, nm: NotificationManager, jobs: JobRunner, project: Project, label_provider: LabelProvider): """ start a job that loads and executes a label provider and saves its results to the database afterwards :param db: database object :param nm: notification manager object :param jobs: job runner object :param project: project :param label_provider: label provider :return: """ # pylint: disable=invalid-name # receive loads and executes the given label provider def receive(): with closing(label_provider.load()) as label_provider_impl: provided_labels = label_provider_impl.get_labels() return provided_labels # result adds the received labels to the database and fires events def result(provided_labels): with db: for label in provided_labels: created_label, insert = project.create_label( label['name'], label['reference'], label['parent'], label['hierarchy_level'] ) if insert: nm.create_label(created_label) else: nm.edit_label(created_label) # run job with given functions jobs.run(project, 'Label Provider', f'{project.name} ({label_provider.name})', f'{project.identifier}/label-provider', receive, result=result)