From efcb5c4928435babfd49f3f84cd12a79e518040e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 30 Dec 2022 13:13:30 +0100 Subject: [PATCH] global: making colorspace module compatible to all python versions --- openpype/pipeline/colorspace.py | 84 ++++++++++++++++++++++++------ openpype/scripts/ocio_config_op.py | 52 ++++++++++++++++++ 2 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 openpype/scripts/ocio_config_op.py diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index e79a31de55..c53835b4c8 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -1,16 +1,58 @@ from copy import deepcopy import re import os +import json import platform -import PyOpenColorIO as ocio +import contextlib +import tempfile +from openpype import PACKAGE_DIR from openpype.settings import get_project_settings -from openpype.lib import StringTemplate +from openpype.lib import ( + StringTemplate, + run_openpype_process +) from openpype.pipeline import Anatomy from openpype.lib.log import Logger log = Logger.get_logger(__name__) +@contextlib.contextmanager +def make_temp_file(): + try: + # Store dumped json to temporary file + temporary_json_file = tempfile.NamedTemporaryFile( + mode="w", suffix=".json", delete=False + ) + temporary_json_file.close() + temporary_json_filepath = temporary_json_file.name.replace( + "\\", "/" + ) + + yield temporary_json_filepath + + except IOError as _error: + raise IOError( + "Not able to create temp json file: {}".format( + _error + ) + ) + + finally: + # Remove the temporary json + os.remove(temporary_json_filepath) + + +def get_ocio_config_script_path(): + return os.path.normpath( + os.path.join( + PACKAGE_DIR, + "scripts", + "ocio_config_op.py" + ) + ) + + def get_imageio_colorspace_from_filepath( path, host_name, project_name, config_data=None, file_rules=None, @@ -49,8 +91,6 @@ def get_imageio_colorspace_from_filepath( # validate matching colorspace with config if validate and config_data: - validate_imageio_config_from_path( - config_data["path"]) validate_imageio_colorspace_in_config( config_data["path"], colorspace_name) @@ -58,26 +98,36 @@ def get_imageio_colorspace_from_filepath( def validate_imageio_colorspace_in_config(config_path, colorspace_name): - config_obj = get_ocio_config(config_path) - if not config_obj.getColorSpace(colorspace_name): - raise ocio.Exception( + colorspaces = get_ocio_config_colorspaces(config_path) + if colorspace_name not in colorspaces: + raise KeyError( "Missing colorspace '{}' in config file '{}'".format( - colorspace_name, config_obj.getWorkingDir()) + colorspace_name, config_path) ) -def validate_imageio_config_from_path(config_path): - try: - config_obj = get_ocio_config(config_path) - except ocio.Exception: - raise ocio.ExceptionMissingFile( - "Missing ocio config file at: {}".format(config_path)) +def get_ocio_config_colorspaces(config_path): + with make_temp_file() as tmp_json_path: + # Prepare subprocess arguments + args = [ + "run", get_ocio_config_script_path(), + "config", "get_colorspace", + "--in_path", config_path, + "--out_path", tmp_json_path - return config_obj + ] + log.info("Executing: {}".format(" ".join(args))) + process_kwargs = { + "logger": log, + "env": {} + } -def get_ocio_config(config_path): - return ocio.Config().CreateFromFile(config_path) + run_openpype_process(*args, **process_kwargs) + + # return all colorspaces + return_json_data = open(tmp_json_path).read() + return json.loads(return_json_data) def get_imageio_config( diff --git a/openpype/scripts/ocio_config_op.py b/openpype/scripts/ocio_config_op.py new file mode 100644 index 0000000000..987b862a1e --- /dev/null +++ b/openpype/scripts/ocio_config_op.py @@ -0,0 +1,52 @@ +import click +import json +from pathlib2 import Path +import PyOpenColorIO as ocio + + +@click.group() +def config(): + pass + + +@config.command( + name="get_colorspace", + help=( + "return all colorspaces from config file " + "--path input arg is required" + ) +) +@click.option("--in_path", required=True, + help="path where to read ocio config file", + type=click.Path(exists=True)) +@click.option("--out_path", required=True, + help="path where to write output json file", + type=click.Path()) +def get_colorspace(in_path, out_path): + config_path = Path(in_path) + json_path = Path(out_path) + print(config_path, json_path) + if not config_path.is_file(): + raise IOError("Input path should be `config.ocio` file") + + config = ocio.Config().CreateFromFile(str(config_path)) + + out_data = { + c.getName(): c.getFamily() + for c in config.getColorSpaces() + } + + with open(json_path, "w") as f: + json.dump(out_data, f) + + print(f"Data are saved to '{json_path}'") + + +@click.group() +def cli(): + pass + + +if __name__ == '__main__': + cli.add_command(config) + cli()