From b5053734dd77d256dd979fdb0c9ac808b0bee244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Mon, 14 Mar 2022 16:59:29 +0100 Subject: [PATCH] Addon: submit job to Manager after packing the files --- addon/flamenco/job_submission.py | 29 +++++++++++++++++++++++++ addon/flamenco/job_types.py | 31 ++++++++------------------- addon/flamenco/job_types_propgroup.py | 9 ++++++++ addon/flamenco/operators.py | 25 +++++++++++++++++++-- 4 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 addon/flamenco/job_submission.py diff --git a/addon/flamenco/job_submission.py b/addon/flamenco/job_submission.py new file mode 100644 index 00000000..74ebbdfc --- /dev/null +++ b/addon/flamenco/job_submission.py @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .manager import ApiClient as _ApiClient + from .manager.models import ( + Job as _Job, + SubmittedJob as _SubmittedJob, + ) +else: + _ApiClient = object + _Job = object + _SubmittedJob = object + + +def submit_job(job: _SubmittedJob, api_client: _ApiClient) -> _Job: + """Send the given job to Flamenco Manager.""" + from flamenco.manager import ApiClient + from flamenco.manager.api import jobs_api + from flamenco.manager.models import SubmittedJob, Job + + assert isinstance(job, SubmittedJob), "got %s" % type(job) + assert isinstance(api_client, ApiClient), "got %s" % type(api_client) + + job_api_instance = jobs_api.JobsApi(api_client) + response: Job = job_api_instance.submit_job(job) + print("Job submitted: %s (%s)" % (response.name, response.id)) + + return response diff --git a/addon/flamenco/job_types.py b/addon/flamenco/job_types.py index 829e5fdf..29f7a677 100644 --- a/addon/flamenco/job_types.py +++ b/addon/flamenco/job_types.py @@ -12,6 +12,7 @@ from . import job_types_propgroup _log = logging.getLogger(__name__) if TYPE_CHECKING: + from flamenco.manager import ApiClient as _ApiClient from flamenco.manager.models import ( AvailableJobType as _AvailableJobType, AvailableJobTypes as _AvailableJobTypes, @@ -19,6 +20,7 @@ if TYPE_CHECKING: JobSettings as _JobSettings, ) else: + _ApiClient = object _AvailableJobTypes = object _AvailableJobType = object _SubmittedJob = object @@ -131,35 +133,20 @@ def update_job_type_properties(scene: bpy.types.Scene) -> None: ) -def get_job_settings(scene: bpy.types.Scene) -> Optional[_JobSettings]: - from flamenco.manager.models import JobSettings - - job_settings = getattr(scene, "flamenco_job_settings", None) - if job_settings is None: - return None - assert isinstance(job_settings, JobSettings), "expected JobSettings, got %s" % ( - type(job_settings) - ) - return job_settings - - def job_for_scene(scene: bpy.types.Scene) -> Optional[_SubmittedJob]: - from flamenco.manager.models import SubmittedJob, JobSettings, JobMetadata + from flamenco.manager.models import SubmittedJob, JobMetadata - settings_propgroup = get_job_settings(scene) - if settings_propgroup is None: - return None + propgroup = getattr(scene, "flamenco_job_settings", None) + assert isinstance( + propgroup, job_types_propgroup.JobTypePropertyGroup + ), "did not expect %s" % (type(propgroup)) - # TODO: convert settings_propgroup to JobSettings. - # dict(settings_propgroup) only includes the user-modified items, which - # isn't enough; the JobSettings() object should also have explicit values - # for the still-default ones. - settings = JobSettings() + settings = propgroup.as_jobsettings() metadata = JobMetadata() job: SubmittedJob = SubmittedJob( name=scene.flamenco_job_name, - type=settings_propgroup.job_type.name, + type=propgroup.job_type.name, priority=50, id=str(uuid.uuid4()), settings=settings, diff --git a/addon/flamenco/job_types_propgroup.py b/addon/flamenco/job_types_propgroup.py index 458c0db5..8f2b8480 100644 --- a/addon/flamenco/job_types_propgroup.py +++ b/addon/flamenco/job_types_propgroup.py @@ -38,6 +38,15 @@ class JobTypePropertyGroup: def unregister_property_group(cls): bpy.utils.unregister_class(cls) + def as_jobsettings(self) -> _JobSettings: + from flamenco.manager.models import JobSettings + + js: JobSettings = JobSettings() + for setting in self.job_type.settings: + js[setting.key] = getattr(self, setting.key) + + return js + # Mapping from AvailableJobType.setting.type to a callable that converts a value # to the appropriate type. This is necessary due to the ambiguity between floats diff --git a/addon/flamenco/operators.py b/addon/flamenco/operators.py index dc7ecc52..533109d9 100644 --- a/addon/flamenco/operators.py +++ b/addon/flamenco/operators.py @@ -7,16 +7,18 @@ from typing import Optional, TYPE_CHECKING import bpy -from . import preferences +from . import job_submission if TYPE_CHECKING: from .bat_interface import ( PackThread as _PackThread, Message as _Message, ) + from .manager.models import SubmittedJob as _SubmittedJob else: _PackThread = object _Message = object + _SubmittedJob = object _log = logging.getLogger(__name__) @@ -110,6 +112,7 @@ class FLAMENCO_OT_submit_job(FlamencoOpMixin, bpy.types.Operator): bl_options = {"REGISTER"} # No UNDO. job_name: bpy.props.StringProperty(name="Job Name") # type: ignore + job: Optional[_SubmittedJob] = None timer: Optional[bpy.types.Timer] = None packthread: Optional[_PackThread] = None @@ -118,6 +121,15 @@ class FLAMENCO_OT_submit_job(FlamencoOpMixin, bpy.types.Operator): def invoke(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]: filepath = self._save_blendfile(context) + + # Construct the Job locally before trying to pack. If any validations fail, better fail early. + from . import job_types + + self.job = job_types.job_for_scene(context.scene) + if self.job is None: + self.report({"ERROR"}, "Unable to create job") + return {"CANCELLED"} + return self._bat_pack(context, filepath) def modal(self, context: bpy.types.Context, event: bpy.types.Event) -> set[str]: @@ -212,7 +224,7 @@ class FLAMENCO_OT_submit_job(FlamencoOpMixin, bpy.types.Operator): if isinstance(msg, bat_interface.MsgDone): self.report({"INFO"}, "BAT pack is done") - # TODO: actually send the job to Flamenco! + self._submit_job(context) return self._quit(context) if isinstance(msg, bat_interface.MsgException): @@ -229,6 +241,15 @@ class FLAMENCO_OT_submit_job(FlamencoOpMixin, bpy.types.Operator): return {"RUNNING_MODAL"} + def _submit_job(self, context: bpy.types.Context) -> None: + """Use the Flamenco API to submit the new Job.""" + assert self.job is not None + + api_client = self.get_api_client(context) + job = job_submission.submit_job(self.job, api_client) + + self.report({"INFO"}, "Job submitted") + def _quit(self, context: bpy.types.Context) -> set[str]: """Stop any timer and return a 'FINISHED' status.