From c73b6d1da7fa1ae69558806eea740e206ef9ccdd Mon Sep 17 00:00:00 2001 From: Brett Williams Date: Mon, 22 May 2023 18:53:19 -0500 Subject: [PATCH] BaseRenderWorker split into BaseRenderWorker & BaseRenderEngine --- lib/render_workers/render_worker.py | 93 +++++++++++++++++------------ 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/lib/render_workers/render_worker.py b/lib/render_workers/render_worker.py index 4ee6cb6..94ac298 100644 --- a/lib/render_workers/render_worker.py +++ b/lib/render_workers/render_worker.py @@ -30,27 +30,24 @@ def string_to_status(string): class BaseRenderWorker(object): - renderer = 'BaseRenderWorker' - render_engine = None - render_engine_version = None - supported_extensions = [] - install_paths = [] - supported_export_formats = [] + engine = None def __init__(self, input_path, output_path, args=None, ignore_extensions=True): if not ignore_extensions: - if not any(ext in input_path for ext in self.supported_extensions): - err_meg = f'Cannot find valid project with supported file extension for {self.renderer} renderer' + if not any(ext in input_path for ext in self.engine.supported_extensions): + err_meg = f'Cannot find valid project with supported file extension for {self.engine.name} renderer' logger.error(err_meg) raise ValueError(err_meg) + if not self.engine: + raise NotImplementedError("Engine not defined") # Essential Info self.input_path = input_path self.output_path = output_path self.args = args or {} self.date_created = datetime.now() - self.renderer_version = self.version() + self.renderer_version = self.engine.version() # Frame Ranges self.total_frames = 0 @@ -75,23 +72,6 @@ class BaseRenderWorker(object): self.is_finished = False self.last_output = None - @classmethod - def version(cls): - raise NotImplementedError("Unknown version") - - @classmethod - def renderer_path(cls): - path = None - try: - path = subprocess.check_output(['which', cls.render_engine]).decode('utf-8').strip() - except subprocess.CalledProcessError: - for p in cls.install_paths: - if os.path.exists(p): - path = p - except Exception as e: - logging.exception(e) - return path - def validate(self): if not os.path.exists(self.input_path): raise FileNotFoundError(f"Cannot find input path: {self.input_path}") @@ -128,9 +108,9 @@ class BaseRenderWorker(object): self.errors.append(msg) return - if not self.renderer_path(): + if not self.engine.renderer_path(): self.status = RenderStatus.ERROR - msg = 'Cannot find render engine path for {}'.format(self.render_engine) + msg = 'Cannot find render engine path for {}'.format(self.engine.name()) logger.error(msg) self.errors.append(msg) return @@ -166,12 +146,12 @@ class BaseRenderWorker(object): with open(self.log_path, "a") as f: - f.write("{3} - Starting {0} {1} Render for {2}\n".format(self.renderer, self.version(), self.input_path, - self.start_time.isoformat())) + f.write(f"{self.start_time.isoformat()} - Starting {self.engine.name()} {self.engine.version()} " + f"Render for {self.input_path}") f.write(f"Running command: {' '.join(subprocess_cmds)}\n") for c in io.TextIOWrapper(self.__process.stdout, encoding="utf-8"): # or another encoding f.write(c) - logger.debug(f"{self.renderer}Worker: {c.strip()}") + logger.debug(f"{self.engine.name()}Worker: {c.strip()}") self.last_output = c.strip() self._parse_stdout(c.strip()) f.write('\n') @@ -187,18 +167,19 @@ class BaseRenderWorker(object): duration = self.end_time - self.start_time if return_code: - message = f"{self.renderer} render failed with return_code {return_code} after {duration}" + message = f"{self.engine.name()} render failed with return_code {return_code} after {duration}" logger.error(message) self.failed_attempts = self.failed_attempts + 1 else: - message = f"{self.renderer} render completed successfully in {duration}" + message = f"{self.engine.name()} render completed successfully in {duration}" logger.info(message) self.status = RenderStatus.COMPLETED f.write(message) if self.failed_attempts >= self.maximum_attempts and self.status is not RenderStatus.CANCELLED: - logger.error('{} Render of {} failed after {} attempts'.format(self.renderer, self.input_path, self.failed_attempts)) + logger.error('{} Render of {} failed after {} attempts'.format(self.engine.name(), self.input_path, + self.failed_attempts)) self.status = RenderStatus.ERROR if not self.errors: self.errors = [self.last_output] @@ -237,6 +218,45 @@ class BaseRenderWorker(object): return elapsed +class BaseRenderEngine(object): + + install_paths = [] + supported_extensions = [] + + @classmethod + def name(cls): + return cls.__name__.lower() + + @classmethod + def renderer_path(cls): + path = None + try: + path = subprocess.check_output(['which', cls.name()]).decode('utf-8').strip() + except subprocess.CalledProcessError: + for p in cls.install_paths: + if os.path.exists(p): + path = p + except Exception as e: + logging.exception(e) + return path + + @classmethod + def version(cls): + raise NotImplementedError("version not implemented") + + @classmethod + def get_help(cls): + path = cls.renderer_path() + if not path: + raise FileNotFoundError("renderer path not found") + help_doc = subprocess.check_output([path, '-h'], stderr=subprocess.STDOUT).decode('utf-8') + return help_doc + + @classmethod + def get_formats(cls): + raise NotImplementedError("get_formats not implemented") + + class RenderWorkerFactory: @staticmethod @@ -255,15 +275,14 @@ class RenderWorkerFactory: @staticmethod def supported_renderers(): - return [x.render_engine for x in RenderWorkerFactory.supported_classes()] + return [x.engine.name() for x in RenderWorkerFactory.supported_classes()] @staticmethod def class_for_name(name): name = name.lower() for render_class in RenderWorkerFactory.supported_classes(): - if render_class.render_engine == name: + if render_class.engine.name() == name: return render_class - raise LookupError(f'Cannot find class for name: {name}')