From c917cd665c677de8575a3565f0f27659bd49966e Mon Sep 17 00:00:00 2001 From: Brett Williams Date: Tue, 20 Aug 2024 22:55:34 -0500 Subject: [PATCH] More docs for base_engine.py --- src/engines/core/base_engine.py | 145 ++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 62 deletions(-) diff --git a/src/engines/core/base_engine.py b/src/engines/core/base_engine.py index d7875ae..ec09133 100644 --- a/src/engines/core/base_engine.py +++ b/src/engines/core/base_engine.py @@ -8,9 +8,21 @@ SUBPROCESS_TIMEOUT = 5 class BaseRenderEngine(object): + """Base class for render engines. This class provides common functionality and structure for various rendering + engines. Create subclasses and override the methods marked below to add additional renderers + + Attributes: + install_paths (list): A list of default installation paths where the render engine + might be found. This list can be populated with common paths to help locate the + executable on different operating systems or environments. + """ install_paths = [] + # -------------------------------------------- + # Required Overrides for Subclasses: + # -------------------------------------------- + def __init__(self, custom_path=None): self.custom_renderer_path = custom_path if not self.renderer_path() or not os.path.exists(self.renderer_path()): @@ -20,33 +32,8 @@ class BaseRenderEngine(object): logger.warning(f"Path is not executable. Setting permissions to 755 for {self.renderer_path()}") os.chmod(self.renderer_path(), 0o755) - def renderer_path(self): - return self.custom_renderer_path or self.default_renderer_path() - - @classmethod - def name(cls): - return str(cls.__name__).lower() - - @classmethod - def default_renderer_path(cls): - path = None - try: # Linux and macOS - path = subprocess.check_output(['which', cls.name()], timeout=SUBPROCESS_TIMEOUT).decode('utf-8').strip() - except (subprocess.CalledProcessError, FileNotFoundError): - for p in cls.install_paths: - if os.path.exists(p): - path = p - except Exception as e: - logger.exception(e) - return path - - # -------------------------------------------- - # Methods to override in subclasses - # -------------------------------------------- - def version(self): - """ - Should be overridden to return the version number. + """Return the version number as a string. Returns: str: Version number. @@ -56,20 +43,44 @@ class BaseRenderEngine(object): """ raise NotImplementedError(f"version not implemented for {self.__class__.__name__}") - def supported_extensions(self): - return [] + def get_project_info(self, project_path, timeout=10): + """Extracts detailed project information from the given project path. - @staticmethod - def downloader(): # override when subclassing if using a downloader class - return None + Args: + project_path (str): The path to the project file. + timeout (int, optional): The maximum time (in seconds) to wait for the operation. Default is 10 seconds. + + Returns: + dict: A dictionary containing project information (subclasses should define the structure). + + Raises: + NotImplementedError: If the method is not overridden in a subclass. + """ + raise NotImplementedError(f"get_project_info not implemented for {self.__class__.__name__}") + + @classmethod + def get_output_formats(cls): + """Returns a list of available output formats supported by the renderer. + + Returns: + list[str]: A list of strings representing the available output formats. + """ + raise NotImplementedError(f"get_output_formats not implemented for {cls.__name__}") @staticmethod def worker_class(): # override when subclassing to link worker class raise NotImplementedError("Worker class not implemented") - @staticmethod - def ui_options(system_info): # override to return options for ui - return {} + # -------------------------------------------- + # Optional Overrides for Subclasses: + # -------------------------------------------- + + def supported_extensions(self): + """ + Returns: + list[str]: list of supported extensions + """ + return [] def get_help(self): """Retrieves the help documentation for the renderer. @@ -91,31 +102,6 @@ class BaseRenderEngine(object): timeout=SUBPROCESS_TIMEOUT, creationflags=creationflags).decode('utf-8') return help_doc - def get_project_info(self, project_path, timeout=10): - """Retrieves information about the project. - - This method should be overridden in a subclass to implement the logic for extracting - project information from the given project path. - - Args: - project_path (str): The path to the project file. - timeout (int, optional): The maximum time (in seconds) to wait for the operation. Default is 10 seconds. - - Returns: - dict: A dictionary containing project information (subclasses should define the structure). - - Raises: - NotImplementedError: If the method is not overridden in a subclass. - """ - raise NotImplementedError(f"get_project_info not implemented for {self.__class__.__name__}") - - @classmethod - def get_output_formats(cls): - raise NotImplementedError(f"get_output_formats not implemented for {cls.__name__}") - - def get_arguments(self): - pass - def system_info(self): """Return additional information about the system specfic to the engine (configured GPUs, render engines, etc) @@ -128,9 +114,9 @@ class BaseRenderEngine(object): """Perform any pre-submission tasks on a project file before uploading it to a server (pack textures, etc.) Override this method to: - 1. Copy the project file to a temporary location (DO NOT MODIFY ORIGINAL PATH). - 2. Perform additional modifications or tasks. - 3. Return the path to the modified project file. + 1. Copy the project file to a temporary location (DO NOT MODIFY ORIGINAL PATH). + 2. Perform additional modifications or tasks. + 3. Return the path to the modified project file. Args: project_path (str): The original project file path. @@ -139,3 +125,38 @@ class BaseRenderEngine(object): str: The path to the modified project file. """ return project_path + + def get_arguments(self): + pass + + @staticmethod + def downloader(): # override when subclassing if using a downloader class + return None + + @staticmethod + def ui_options(system_info): # override to return options for ui + return {} + + # -------------------------------------------- + # Do Not Override These Methods: + # -------------------------------------------- + + def renderer_path(self): + return self.custom_renderer_path or self.default_renderer_path() + + @classmethod + def name(cls): + return str(cls.__name__).lower() + + @classmethod + def default_renderer_path(cls): + path = None + try: # Linux and macOS + path = subprocess.check_output(['which', cls.name()], timeout=SUBPROCESS_TIMEOUT).decode('utf-8').strip() + except (subprocess.CalledProcessError, FileNotFoundError): + for p in cls.install_paths: + if os.path.exists(p): + path = p + except Exception as e: + logger.exception(e) + return path