From 2695c218fb9d6345b845e021805d28dad5161032 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:10:13 +0100 Subject: [PATCH 01/20] nuke: add color space check functionality to api --- openpype/hosts/nuke/api/__init__.py | 7 +++++ openpype/hosts/nuke/api/utils.py | 47 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index f7ebcb41da..b571c4098c 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -29,6 +29,10 @@ from .lib import ( maintained_selection ) +from .utils import ( + colorspace_exists_on_node, + get_colorspace_list +) __all__ = ( "file_extensions", @@ -54,4 +58,7 @@ __all__ = ( "update_container", "maintained_selection", + + "colorspace_exists_on_node", + "get_colorspace_list" ) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 0ed84f9560..5b0c607292 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -82,3 +82,50 @@ def bake_gizmos_recursively(in_group=None): if node.Class() == "Group": bake_gizmos_recursively(node) + + +def colorspace_exists_on_node(node, colorspace_name): + """ Check if colorspace exists on node + + Look through all options in the colorpsace knob, and see if we have an + exact match to one of the items. + + Args: + node (nuke.Node): nuke node object + colorspace_name (str): color profile name + + Returns: + bool: True if exists + """ + try: + colorspace_knob = node['colorspace'] + except ValueError: + # knob is not available on input node + return False + all_clrs = get_colorspace_list(colorspace_knob) + + return colorspace_name in all_clrs + + +def get_colorspace_list(colorspace_knob): + """Get available colorspace profile names + + Args: + colorspace_knob (nuke.Knob): nuke knob object + + Returns: + list: list of strings names of profiles + """ + + all_clrs = list(colorspace_knob.values()) + reduced_clrs = [] + + if not colorspace_knob.getFlag(nuke.STRIP_CASCADE_PREFIX): + return all_clrs + + # strip colorspace with nested path + for clrs in all_clrs: + clrs = clrs.split('/')[-1] + reduced_clrs.append(clrs) + + return reduced_clrs From 9f5057aafe678fa41f67620a9c18252eac5902a6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:10:42 +0100 Subject: [PATCH 02/20] nuke: load clip with colorspace from representation data --- openpype/hosts/nuke/plugins/load/load_clip.py | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 3a9c9ca691..621a464c69 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -9,7 +9,8 @@ from openpype.hosts.nuke.api.lib import ( from openpype.hosts.nuke.api import ( containerise, update_container, - viewer_update_and_undo_stop + viewer_update_and_undo_stop, + colorspace_exists_on_node ) from openpype.hosts.nuke.api import plugin @@ -65,12 +66,37 @@ class LoadClip(plugin.NukeLoader): + plugin.get_review_presets_config() ) - def load(self, context, name, namespace, options): + def _set_colorspace(self, node, version_data, repre_data, path=None): + output_color = None + path = path or self.fname.replace("\\", "/") + # get colorspace + colorspace = repre_data.get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + # colorspace from `project_anatomy/imageio/nuke/regexInputs` + iio_colorspace = get_imageio_input_colorspace(path) + + # Set colorspace defined in version data + if ( + colorspace is not None + and colorspace_exists_on_node( + node, str(colorspace)) is not False + ): + node["colorspace"].setValue(str(colorspace)) + output_color = str(colorspace) + elif iio_colorspace is not None: + node["colorspace"].setValue(iio_colorspace) + output_color = iio_colorspace + + return output_color + + + def load(self, context, name, namespace, options): + repres = context["representation"] # reste container id so it is always unique for each instance self.reset_container_id() - is_sequence = len(context["representation"]["files"]) > 1 + is_sequence = len(repres["files"]) > 1 file = self.fname.replace("\\", "/") @@ -79,10 +105,9 @@ class LoadClip(plugin.NukeLoader): version = context['version'] version_data = version.get("data", {}) - repr_id = context["representation"]["_id"] - colorspace = version_data.get("colorspace") - iio_colorspace = get_imageio_input_colorspace(file) - repr_cont = context["representation"]["context"] + repr_id = repres["_id"] + + repr_cont = repres["context"] self.log.info("version_data: {}\n".format(version_data)) self.log.debug( @@ -116,7 +141,7 @@ class LoadClip(plugin.NukeLoader): "Representation id `{}` is failing to load".format(repr_id)) return - read_name = self._get_node_name(context["representation"]) + read_name = self._get_node_name(repres) # Create the Loader with the filename path set read_node = nuke.createNode( @@ -128,11 +153,8 @@ class LoadClip(plugin.NukeLoader): with viewer_update_and_undo_stop(): read_node["file"].setValue(file) - # Set colorspace defined in version data - if colorspace: - read_node["colorspace"].setValue(str(colorspace)) - elif iio_colorspace is not None: - read_node["colorspace"].setValue(iio_colorspace) + set_colorspace = self._set_colorspace( + read_node, version_data, repres["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -145,6 +167,13 @@ class LoadClip(plugin.NukeLoader): for k in add_keys: if k == 'version': data_imprint.update({k: context["version"]['name']}) + elif k == 'colorspace': + colorspace = repres["data"].get(k) + colorspace = colorspace or version_data.get(k) + data_imprint.update({ + "db_colorspace": colorspace, + "set_colorspace": set_colorspace + }) else: data_imprint.update( {k: context["version"]['data'].get(k, str(None))}) @@ -193,10 +222,13 @@ class LoadClip(plugin.NukeLoader): }) version_data = version.get("data", {}) repr_id = representation["_id"] - colorspace = version_data.get("colorspace") - iio_colorspace = get_imageio_input_colorspace(file) + repr_cont = representation["context"] + # colorspace profile + colorspace = representation["data"].get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) @@ -229,12 +261,9 @@ class LoadClip(plugin.NukeLoader): # to avoid multiple undo steps for rest of process # we will switch off undo-ing with viewer_update_and_undo_stop(): - - # Set colorspace defined in version data - if colorspace: - read_node["colorspace"].setValue(str(colorspace)) - elif iio_colorspace is not None: - read_node["colorspace"].setValue(iio_colorspace) + set_colorspace = self._set_colorspace( + read_node, version_data, representation["data"], + path=file) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -243,7 +272,8 @@ class LoadClip(plugin.NukeLoader): "frameStart": str(first), "frameEnd": str(last), "version": str(version.get("name")), - "colorspace": colorspace, + "db_colorspace": colorspace, + "set_colorspace": set_colorspace, "source": version_data.get("source"), "handleStart": str(self.handle_start), "handleEnd": str(self.handle_end), From 9746cb4eb87c459c0975e57e2c6b14ef6a325220 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Jan 2022 15:18:06 +0100 Subject: [PATCH 03/20] nuke: load clip internal method moved to the end of class methods --- openpype/hosts/nuke/plugins/load/load_clip.py | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 621a464c69..c94fbd59b5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -66,31 +66,6 @@ class LoadClip(plugin.NukeLoader): + plugin.get_review_presets_config() ) - def _set_colorspace(self, node, version_data, repre_data, path=None): - output_color = None - path = path or self.fname.replace("\\", "/") - # get colorspace - colorspace = repre_data.get("colorspace") - colorspace = colorspace or version_data.get("colorspace") - - # colorspace from `project_anatomy/imageio/nuke/regexInputs` - iio_colorspace = get_imageio_input_colorspace(path) - - # Set colorspace defined in version data - if ( - colorspace is not None - and colorspace_exists_on_node( - node, str(colorspace)) is not False - ): - node["colorspace"].setValue(str(colorspace)) - output_color = str(colorspace) - elif iio_colorspace is not None: - node["colorspace"].setValue(iio_colorspace) - output_color = iio_colorspace - - return output_color - - def load(self, context, name, namespace, options): repres = context["representation"] # reste container id so it is always unique for each instance @@ -406,3 +381,27 @@ class LoadClip(plugin.NukeLoader): } return self.node_name_template.format(**name_data) + + def _set_colorspace(self, node, version_data, repre_data, path=None): + output_color = None + path = path or self.fname.replace("\\", "/") + # get colorspace + colorspace = repre_data.get("colorspace") + colorspace = colorspace or version_data.get("colorspace") + + # colorspace from `project_anatomy/imageio/nuke/regexInputs` + iio_colorspace = get_imageio_input_colorspace(path) + + # Set colorspace defined in version data + if ( + colorspace is not None + and colorspace_exists_on_node( + node, str(colorspace)) is not False + ): + node["colorspace"].setValue(str(colorspace)) + output_color = str(colorspace) + elif iio_colorspace is not None: + node["colorspace"].setValue(iio_colorspace) + output_color = iio_colorspace + + return output_color \ No newline at end of file From c400c79c6a1cb46dc2714beaad8e28b7a75f8e8e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 25 Jan 2022 15:13:11 +0100 Subject: [PATCH 04/20] nuke: keep consistent variable names --- openpype/hosts/nuke/plugins/load/load_clip.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index c94fbd59b5..13fa4f84c5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -67,11 +67,11 @@ class LoadClip(plugin.NukeLoader): ) def load(self, context, name, namespace, options): - repres = context["representation"] + repre = context["representation"] # reste container id so it is always unique for each instance self.reset_container_id() - is_sequence = len(repres["files"]) > 1 + is_sequence = len(repre["files"]) > 1 file = self.fname.replace("\\", "/") @@ -80,13 +80,13 @@ class LoadClip(plugin.NukeLoader): version = context['version'] version_data = version.get("data", {}) - repr_id = repres["_id"] + repre_id = repre["_id"] - repr_cont = repres["context"] + repre_cont = repre["context"] self.log.info("version_data: {}\n".format(version_data)) self.log.debug( - "Representation id `{}` ".format(repr_id)) + "Representation id `{}` ".format(repre_id)) self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) @@ -101,7 +101,7 @@ class LoadClip(plugin.NukeLoader): first = 1 last = first + duration elif "#" not in file: - frame = repr_cont.get("frame") + frame = repre_cont.get("frame") assert frame, "Representation is not sequence" padding = len(frame) @@ -113,10 +113,10 @@ class LoadClip(plugin.NukeLoader): if not file: self.log.warning( - "Representation id `{}` is failing to load".format(repr_id)) + "Representation id `{}` is failing to load".format(repre_id)) return - read_name = self._get_node_name(repres) + read_name = self._get_node_name(repre) # Create the Loader with the filename path set read_node = nuke.createNode( @@ -129,7 +129,7 @@ class LoadClip(plugin.NukeLoader): read_node["file"].setValue(file) set_colorspace = self._set_colorspace( - read_node, version_data, repres["data"]) + read_node, version_data, repre["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -143,7 +143,7 @@ class LoadClip(plugin.NukeLoader): if k == 'version': data_imprint.update({k: context["version"]['name']}) elif k == 'colorspace': - colorspace = repres["data"].get(k) + colorspace = repre["data"].get(k) colorspace = colorspace or version_data.get(k) data_imprint.update({ "db_colorspace": colorspace, @@ -196,9 +196,9 @@ class LoadClip(plugin.NukeLoader): "_id": representation["parent"] }) version_data = version.get("data", {}) - repr_id = representation["_id"] + repre_id = representation["_id"] - repr_cont = representation["context"] + repre_cont = representation["context"] # colorspace profile colorspace = representation["data"].get("colorspace") @@ -217,7 +217,7 @@ class LoadClip(plugin.NukeLoader): first = 1 last = first + duration elif "#" not in file: - frame = repr_cont.get("frame") + frame = repre_cont.get("frame") assert frame, "Representation is not sequence" padding = len(frame) @@ -225,7 +225,7 @@ class LoadClip(plugin.NukeLoader): if not file: self.log.warning( - "Representation id `{}` is failing to load".format(repr_id)) + "Representation id `{}` is failing to load".format(repre_id)) return read_name = self._get_node_name(representation) @@ -370,12 +370,12 @@ class LoadClip(plugin.NukeLoader): def _get_node_name(self, representation): - repr_cont = representation["context"] + repre_cont = representation["context"] name_data = { - "asset": repr_cont["asset"], - "subset": repr_cont["subset"], + "asset": repre_cont["asset"], + "subset": repre_cont["subset"], "representation": representation["name"], - "ext": repr_cont["representation"], + "ext": repre_cont["representation"], "id": representation["_id"], "class_name": self.__class__.__name__ } From 28128f3827e810886fac74238987af9e48156971 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 25 Jan 2022 15:14:12 +0100 Subject: [PATCH 05/20] flake8: new line at the end --- openpype/hosts/nuke/plugins/load/load_clip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 13fa4f84c5..4fc49e4cee 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -404,4 +404,4 @@ class LoadClip(plugin.NukeLoader): node["colorspace"].setValue(iio_colorspace) output_color = iio_colorspace - return output_color \ No newline at end of file + return output_color From 8bbf9eb7068d1f12af142480b6ede453e95c6c74 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 2 Feb 2022 12:18:36 +0100 Subject: [PATCH 06/20] nuke: improving logic --- openpype/hosts/nuke/plugins/load/load_clip.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 4fc49e4cee..16df3e27d5 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -128,7 +128,7 @@ class LoadClip(plugin.NukeLoader): with viewer_update_and_undo_stop(): read_node["file"].setValue(file) - set_colorspace = self._set_colorspace( + used_colorspace = self._set_colorspace( read_node, version_data, repre["data"]) self._set_range_to_node(read_node, first, last, start_at_workfile) @@ -145,10 +145,9 @@ class LoadClip(plugin.NukeLoader): elif k == 'colorspace': colorspace = repre["data"].get(k) colorspace = colorspace or version_data.get(k) - data_imprint.update({ - "db_colorspace": colorspace, - "set_colorspace": set_colorspace - }) + data_imprint["db_colorspace"] = colorspace + if used_colorspace: + data_imprint["used_colorspace"] = used_colorspace else: data_imprint.update( {k: context["version"]['data'].get(k, str(None))}) @@ -236,7 +235,7 @@ class LoadClip(plugin.NukeLoader): # to avoid multiple undo steps for rest of process # we will switch off undo-ing with viewer_update_and_undo_stop(): - set_colorspace = self._set_colorspace( + used_colorspace = self._set_colorspace( read_node, version_data, representation["data"], path=file) @@ -248,7 +247,6 @@ class LoadClip(plugin.NukeLoader): "frameEnd": str(last), "version": str(version.get("name")), "db_colorspace": colorspace, - "set_colorspace": set_colorspace, "source": version_data.get("source"), "handleStart": str(self.handle_start), "handleEnd": str(self.handle_end), @@ -256,6 +254,10 @@ class LoadClip(plugin.NukeLoader): "author": version_data.get("author") } + # add used colorspace if found any + if used_colorspace: + updated_dict["used_colorspace"] = used_colorspace + # change color of read_node # get all versions in list versions = io.find({ From c6b109bcdb9fb6e5b0d3cb52d7121bfde5d7cdf7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 15:39:32 +0100 Subject: [PATCH 07/20] created project_backpack in openpype lib --- openpype/lib/project_backpack.py | 232 +++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 openpype/lib/project_backpack.py diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py new file mode 100644 index 0000000000..045e8b4ea1 --- /dev/null +++ b/openpype/lib/project_backpack.py @@ -0,0 +1,232 @@ +"""These lib functions are primarily for development purposes. + +WARNING: This is not meant for production data. + +Goal is to be able create package of current state of project with related +documents from mongo and files from disk to zip file and then be able recreate +the project based on the zip. + +This gives ability to create project where a changes and tests can be done. + +Keep in mind that to be able create a package of project has few requirements. +Possible requirement should be listed in 'pack_project' function. +""" +import os +import json +import platform +import tempfile +import shutil +import datetime + +import zipfile +from bson.json_util import ( + loads, + dumps, + CANONICAL_JSON_OPTIONS +) + +from avalon.api import AvalonMongoDB + +DOCUMENTS_FILE_NAME = "database" +METADATA_FILE_NAME = "metadata" +PROJECT_FILES_DIR = "project_files" + + +def add_timestamp(filepath): + """Add timestamp string to a file.""" + base, ext = os.path.splitext(filepath) + timestamp = datetime.datetime.now().strftime("%y%m%d_%H%M%S") + new_base = "{}_{}".format(base, timestamp) + return new_base + ext + + +def pack_project(project_name, destination_dir=None): + """Make a package of a project with mongo documents and files. + + This function has few restrictions: + - project must have only one root + - project must have all templates starting with + "{root[...]}/{project[name]}" + + Args: + project_name(str): Project that should be packaged. + destination_dir(str): Optinal path where zip will be stored. Project's + root is used if not passed. + """ + # Validate existence of project + dbcon = AvalonMongoDB() + dbcon.Session["AVALON_PROJECT"] = project_name + project_doc = dbcon.find_one({"type": "project"}) + if not project_doc: + raise ValueError("Project \"{}\" was not found in database".format( + project_name + )) + + roots = project_doc["config"]["roots"] + # Determine root directory of project + source_root = None + for root_name, root_value in roots.items(): + if source_root is not None: + raise ValueError( + "Packaging is supported only for single root projects" + ) + source_root = root_value + + root_path = source_root[platform.system().lower()] + print("Using root \"{}\" with path \"{}\"".format( + root_name, root_value + )) + + project_source_path = os.path.join(root_path, project_name) + if not os.path.exists(project_source_path): + raise ValueError("Didn't find source of project files") + + # Determine zip filepath where data will be stored + if not destination_dir: + destination_dir = root_path + + if not os.path.exists(destination_dir): + os.makedirs(destination_dir) + + zip_path = os.path.join(destination_dir, project_name + ".zip") + + print("Project will be packaged into {}".format(zip_path)) + # Rename already existing zip + if os.path.exists(zip_path): + dst_filepath = add_timestamp(zip_path) + os.rename(zip_path, dst_filepath) + + # We can add more data + metadata = { + "project_name": project_name, + "root": source_root, + "version": 1 + } + # Create temp json file where metadata are stored + with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as s: + temp_metadata_json = s.name + + with open(temp_metadata_json, "w") as stream: + json.dump(metadata, stream) + + # Create temp json file where database documents are stored + with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as s: + temp_docs_json = s.name + + # Query all project documents and store them to temp json + docs = list(dbcon.find({})) + data = dumps( + docs, json_options=CANONICAL_JSON_OPTIONS + ) + with open(temp_docs_json, "w") as stream: + stream.write(data) + + # Write all to zip file + with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zip_stream: + # Add metadata file + zip_stream.write(temp_metadata_json, METADATA_FILE_NAME + ".json") + # Add database documents + zip_stream.write(temp_docs_json, DOCUMENTS_FILE_NAME + ".json") + # Add project files to zip + for root, _, filenames in os.walk(project_source_path): + for filename in filenames: + filepath = os.path.join(root, filename) + # TODO add one more folder + archive_name = os.path.join( + PROJECT_FILES_DIR, + os.path.relpath(filepath, root_path) + ) + zip_stream.write(filepath, archive_name) + + # Cleanup + os.remove(temp_docs_json) + os.remove(temp_metadata_json) + dbcon.uninstall() + + +def unpack_project(path_to_zip, new_root=None): + """Unpack project zip file to recreate project. + + Args: + path_to_zip(str): Path to zip which was created using 'pack_project' + function. + new_root(str): Optional way how to set different root path for unpacked + project. + """ + if not os.path.exists(path_to_zip): + print("Zip file does not exists: {}".format(path_to_zip)) + return + + tmp_dir = tempfile.mkdtemp(prefix="unpack_") + print("Zip is extracted to: {}".format(tmp_dir)) + with zipfile.ZipFile(path_to_zip, "r") as zip_stream: + zip_stream.extractall(tmp_dir) + + metadata_json_path = os.path.join(tmp_dir, METADATA_FILE_NAME + ".json") + with open(metadata_json_path, "r") as stream: + metadata = json.load(stream) + + docs_json_path = os.path.join(tmp_dir, DOCUMENTS_FILE_NAME + ".json") + with open(docs_json_path, "r") as stream: + content = stream.readlines() + docs = loads("".join(content)) + + low_platform = platform.system().lower() + project_name = metadata["project_name"] + source_root = metadata["root"] + root_path = source_root[low_platform] + + # Drop existing collection + dbcon = AvalonMongoDB() + database = dbcon.database + if project_name in database.list_collection_names(): + database.drop_collection(project_name) + print("Removed existing project collection") + + collection = database[project_name] + # Create new collection with loaded docs + print("Creating project documents ({})".format(len(docs))) + collection.insert_many(docs) + + # Skip change of root if is the same as the one stored in metadata + if ( + new_root + and (os.path.normpath(new_root) == os.path.normpath(root_path)) + ): + new_root = None + + if new_root: + print("Using different root path {}".format(new_root)) + root_path = new_root + + project_doc = collection.find_one({"type": "project"}) + roots = project_doc["config"]["roots"] + key = tuple(roots.keys())[0] + update_key = "config.roots.{}.{}".format(key, low_platform) + collection.update_one( + {"_id": project_doc["_id"]}, + {"$set": { + update_key: new_root + }} + ) + + # Make sure root path exists + if not os.path.exists(root_path): + os.makedirs(root_path) + + src_project_files_dir = os.path.join( + tmp_dir, PROJECT_FILES_DIR, project_name + ) + dst_project_files_dir = os.path.join(root_path, project_name) + if os.path.exists(dst_project_files_dir): + new_path = add_timestamp(dst_project_files_dir) + os.rename(dst_project_files_dir, new_path) + + print("Moving {} -> {}".format( + src_project_files_dir, dst_project_files_dir + )) + shutil.move(src_project_files_dir, dst_project_files_dir) + + # CLeanup + shutil.rmtree(tmp_dir) + dbcon.uninstall() From 7d19db96c4c3cc9625ab8303d7d0777cb72fea90 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 15:39:53 +0100 Subject: [PATCH 08/20] create cli commands for project backpack functions --- openpype/cli.py | 20 ++++++++++++++++++++ openpype/pype_commands.py | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/openpype/cli.py b/openpype/cli.py index 6e9c237b0e..f15306e3d3 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -412,3 +412,23 @@ def repack_version(directory): directory name. """ PypeCommands().repack_version(directory) + + +@main.command() +@click.option("--project", help="Project name") +@click.option( + "--dirpath", help="Directory where package is stored", default=None +) +def pack_project(project_name, dirpath): + """Create a package of project with all files and database dump.""" + PypeCommands().pack_project(project_name, dirpath) + + +@main.command() +@click.option("--zipfile", help="Path to zip file") +@click.option( + "--root", help="Replace root which was stored in project", default=None +) +def uppack_project(zipfile, root): + """Create a package of project with all files and database dump.""" + PypeCommands().unpack_project(zipfile, root) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index de0336be2b..e5db036c04 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -433,3 +433,13 @@ class PypeCommands: version_packer = VersionRepacker(directory) version_packer.process() + + def pack_project(project_name, dirpath): + from openpype.lib.project_backpack import pack_project + + pack_project(project_name, dirpath) + + def unpack_project(zip_filepath, new_root): + from openpype.lib.project_backpack import unpack_project + + unpack_project(zip_filepath, new_root) From ea4e5b040776ac560904752325b7505886a04bc9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 16:21:13 +0100 Subject: [PATCH 09/20] few fixes and smaller modifications --- openpype/cli.py | 6 +++--- openpype/lib/project_backpack.py | 27 ++++++++++++++++++++------- openpype/pype_commands.py | 4 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/openpype/cli.py b/openpype/cli.py index f15306e3d3..0597c387d0 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -419,9 +419,9 @@ def repack_version(directory): @click.option( "--dirpath", help="Directory where package is stored", default=None ) -def pack_project(project_name, dirpath): +def pack_project(project, dirpath): """Create a package of project with all files and database dump.""" - PypeCommands().pack_project(project_name, dirpath) + PypeCommands().pack_project(project, dirpath) @main.command() @@ -429,6 +429,6 @@ def pack_project(project_name, dirpath): @click.option( "--root", help="Replace root which was stored in project", default=None ) -def uppack_project(zipfile, root): +def unpack_project(zipfile, root): """Create a package of project with all files and database dump.""" PypeCommands().unpack_project(zipfile, root) diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py index 045e8b4ea1..42dc8a4f63 100644 --- a/openpype/lib/project_backpack.py +++ b/openpype/lib/project_backpack.py @@ -53,6 +53,7 @@ def pack_project(project_name, destination_dir=None): destination_dir(str): Optinal path where zip will be stored. Project's root is used if not passed. """ + print("Creating package of project \"{}\"".format(project_name)) # Validate existence of project dbcon = AvalonMongoDB() dbcon.Session["AVALON_PROJECT"] = project_name @@ -74,7 +75,7 @@ def pack_project(project_name, destination_dir=None): root_path = source_root[platform.system().lower()] print("Using root \"{}\" with path \"{}\"".format( - root_name, root_value + root_name, root_path )) project_source_path = os.path.join(root_path, project_name) @@ -85,12 +86,13 @@ def pack_project(project_name, destination_dir=None): if not destination_dir: destination_dir = root_path + destination_dir = os.path.normpath(destination_dir) if not os.path.exists(destination_dir): os.makedirs(destination_dir) zip_path = os.path.join(destination_dir, project_name + ".zip") - print("Project will be packaged into {}".format(zip_path)) + print("Project will be packaged into \"{}\"".format(zip_path)) # Rename already existing zip if os.path.exists(zip_path): dst_filepath = add_timestamp(zip_path) @@ -121,6 +123,7 @@ def pack_project(project_name, destination_dir=None): with open(temp_docs_json, "w") as stream: stream.write(data) + print("Packing files into zip") # Write all to zip file with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zip_stream: # Add metadata file @@ -138,10 +141,12 @@ def pack_project(project_name, destination_dir=None): ) zip_stream.write(filepath, archive_name) + print("Cleaning up") # Cleanup os.remove(temp_docs_json) os.remove(temp_metadata_json) dbcon.uninstall() + print("*** Packing finished ***") def unpack_project(path_to_zip, new_root=None): @@ -153,12 +158,13 @@ def unpack_project(path_to_zip, new_root=None): new_root(str): Optional way how to set different root path for unpacked project. """ + print("Unpacking project from zip {}".format(path_to_zip)) if not os.path.exists(path_to_zip): print("Zip file does not exists: {}".format(path_to_zip)) return tmp_dir = tempfile.mkdtemp(prefix="unpack_") - print("Zip is extracted to: {}".format(tmp_dir)) + print("Zip is extracted to temp: {}".format(tmp_dir)) with zipfile.ZipFile(path_to_zip, "r") as zip_stream: zip_stream.extractall(tmp_dir) @@ -183,9 +189,9 @@ def unpack_project(path_to_zip, new_root=None): database.drop_collection(project_name) print("Removed existing project collection") - collection = database[project_name] - # Create new collection with loaded docs print("Creating project documents ({})".format(len(docs))) + # Create new collection with loaded docs + collection = database[project_name] collection.insert_many(docs) # Skip change of root if is the same as the one stored in metadata @@ -217,16 +223,23 @@ def unpack_project(path_to_zip, new_root=None): src_project_files_dir = os.path.join( tmp_dir, PROJECT_FILES_DIR, project_name ) - dst_project_files_dir = os.path.join(root_path, project_name) + dst_project_files_dir = os.path.normpath( + os.path.join(root_path, project_name) + ) if os.path.exists(dst_project_files_dir): new_path = add_timestamp(dst_project_files_dir) + print("Project folder already exists. Renamed \"{}\" -> \"{}\"".format( + dst_project_files_dir, new_path + )) os.rename(dst_project_files_dir, new_path) - print("Moving {} -> {}".format( + print("Moving project files from temp \"{}\" -> \"{}\"".format( src_project_files_dir, dst_project_files_dir )) shutil.move(src_project_files_dir, dst_project_files_dir) # CLeanup + print("Cleaning up") shutil.rmtree(tmp_dir) dbcon.uninstall() + print("*** Unpack finished ***") diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index e5db036c04..1ed6cc9344 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -434,12 +434,12 @@ class PypeCommands: version_packer = VersionRepacker(directory) version_packer.process() - def pack_project(project_name, dirpath): + def pack_project(self, project_name, dirpath): from openpype.lib.project_backpack import pack_project pack_project(project_name, dirpath) - def unpack_project(zip_filepath, new_root): + def unpack_project(self, zip_filepath, new_root): from openpype.lib.project_backpack import unpack_project unpack_project(zip_filepath, new_root) From 9a3f74735eda5f17e1f4b6239a33ee29ac22dbaa Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 2 Feb 2022 16:41:07 +0100 Subject: [PATCH 10/20] fix unset variable name --- openpype/lib/project_backpack.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/lib/project_backpack.py b/openpype/lib/project_backpack.py index 42dc8a4f63..11fd0c0c3e 100644 --- a/openpype/lib/project_backpack.py +++ b/openpype/lib/project_backpack.py @@ -66,16 +66,18 @@ def pack_project(project_name, destination_dir=None): roots = project_doc["config"]["roots"] # Determine root directory of project source_root = None + source_root_name = None for root_name, root_value in roots.items(): if source_root is not None: raise ValueError( "Packaging is supported only for single root projects" ) source_root = root_value + source_root_name = root_name root_path = source_root[platform.system().lower()] print("Using root \"{}\" with path \"{}\"".format( - root_name, root_path + source_root_name, root_path )) project_source_path = os.path.join(root_path, project_name) From 5e050b6d5d3777076277638c805a35049d3a3246 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 2 Feb 2022 18:52:02 +0100 Subject: [PATCH 11/20] OP-2505 - fix skip already created subset --- .../publish/collect_remote_instances.py | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py index 2a07c684da..97634678df 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py @@ -9,7 +9,7 @@ from openpype.hosts.photoshop import api as photoshop class CollectRemoteInstances(pyblish.api.ContextPlugin): - """Gather instances configured color code of a layer. + """Creates instances for configured color code of a layer. Used in remote publishing when artists marks publishable layers by color- coding. @@ -46,6 +46,11 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): stub = photoshop.stub() layers = stub.get_layers() + existing_subset_names = [] + for instance in context: + if instance.data.get('publish'): + existing_subset_names.append(instance.data.get('subset')) + asset, task_name, task_type = get_batch_asset_task_info( task_data["context"]) @@ -70,21 +75,27 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): self.log.debug("!!! Not a top layer, skip") continue + fill_pairs = { + "variant": variant, + "family": resolved_family, + "task": task_name, + "layer": layer.name + } + + subset = resolved_subset_template.format( + **prepare_template_data(fill_pairs)) + + if subset in existing_subset_names: + self.log.info( + "Subset {} already created, skipping.".format(subset)) + continue + instance = context.create_instance(layer.name) instance.append(layer) instance.data["family"] = resolved_family instance.data["publish"] = layer.visible instance.data["asset"] = asset instance.data["task"] = task_name - - fill_pairs = { - "variant": variant, - "family": instance.data["family"], - "task": instance.data["task"], - "layer": layer.name - } - subset = resolved_subset_template.format( - **prepare_template_data(fill_pairs)) instance.data["subset"] = subset instance_names.append(layer.name) From de2d6dd83d9b89574bdfb28d0f9a61fffa8956cc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 3 Feb 2022 10:45:59 +0100 Subject: [PATCH 12/20] image loaders also work on review family --- openpype/hosts/tvpaint/plugins/load/load_image.py | 2 +- openpype/hosts/tvpaint/plugins/load/load_reference_image.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/load/load_image.py b/openpype/hosts/tvpaint/plugins/load/load_image.py index 1246fe8248..7dba1e3619 100644 --- a/openpype/hosts/tvpaint/plugins/load/load_image.py +++ b/openpype/hosts/tvpaint/plugins/load/load_image.py @@ -5,7 +5,7 @@ from openpype.hosts.tvpaint.api import lib, plugin class ImportImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" - families = ["render", "image", "background", "plate"] + families = ["render", "image", "background", "plate", "review"] representations = ["*"] label = "Import Image" diff --git a/openpype/hosts/tvpaint/plugins/load/load_reference_image.py b/openpype/hosts/tvpaint/plugins/load/load_reference_image.py index b5e0a86686..0a85e5dc76 100644 --- a/openpype/hosts/tvpaint/plugins/load/load_reference_image.py +++ b/openpype/hosts/tvpaint/plugins/load/load_reference_image.py @@ -7,7 +7,7 @@ from openpype.hosts.tvpaint.api import lib, pipeline, plugin class LoadImage(plugin.Loader): """Load image or image sequence to TVPaint as new layer.""" - families = ["render", "image", "background", "plate"] + families = ["render", "image", "background", "plate", "review"] representations = ["*"] label = "Load Image" From b39b5e58c173d52a4d3a7473a1e53f01582fc3e2 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:44:09 +0100 Subject: [PATCH 13/20] OP-2505 - better validation message --- .../plugins/publish/validate_unique_subsets.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py index 15ae5fbcea..e000352601 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py @@ -1,3 +1,4 @@ +import collections import pyblish.api import openpype.api @@ -16,11 +17,16 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): subset_names = [] for instance in context: + self.log.info("instance:: {}".format(instance.data)) if instance.data.get('publish'): subset_names.append(instance.data.get('subset')) + non_unique = \ + [item + for item, count in collections.Counter(subset_names).items() + if count > 1] msg = ( - "Instance subset names are not unique. " + - "Remove duplicates via SubsetManager." + "Instance subset names {} are not unique. " + + "Remove duplicates via SubsetManager.".format(non_unique) ) - assert len(subset_names) == len(set(subset_names)), msg + assert not non_unique, msg From 3089438234b64347c3a7b1a33bf42167eb7b761a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:45:34 +0100 Subject: [PATCH 14/20] OP-2505 - better order --- .../photoshop/plugins/publish/collect_remote_instances.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py index 97634678df..48c6f583a4 100644 --- a/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py +++ b/openpype/hosts/photoshop/plugins/publish/collect_remote_instances.py @@ -60,6 +60,10 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): instance_names = [] for layer in layers: self.log.debug("Layer:: {}".format(layer)) + if layer.parents: + self.log.debug("!!! Not a top layer, skip") + continue + resolved_family, resolved_subset_template = self._resolve_mapping( layer ) @@ -71,10 +75,6 @@ class CollectRemoteInstances(pyblish.api.ContextPlugin): self.log.debug("!!! Not found family or template, skip") continue - if layer.parents: - self.log.debug("!!! Not a top layer, skip") - continue - fill_pairs = { "variant": variant, "family": resolved_family, From 1c700faacfc6ee23e6bcd0b7fc33841f100c6368 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 11:46:27 +0100 Subject: [PATCH 15/20] OP-2505 - safer initialization --- openpype/pype_commands.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/pype_commands.py b/openpype/pype_commands.py index de0336be2b..2b19075341 100644 --- a/openpype/pype_commands.py +++ b/openpype/pype_commands.py @@ -251,7 +251,10 @@ class PypeCommands: data = { "last_workfile_path": workfile_path, - "start_last_workfile": True + "start_last_workfile": True, + "project_name": project, + "asset_name": asset, + "task_name": task_name } launched_app = application_manager.launch(app_name, **data) From 78b3e9dad86b58bd3eda378c18037f4726f2c934 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 12:14:13 +0100 Subject: [PATCH 16/20] OP-2505 - fixed message --- .../photoshop/plugins/publish/validate_unique_subsets.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py index e000352601..40abfb1bbd 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_unique_subsets.py @@ -25,8 +25,6 @@ class ValidateSubsetUniqueness(pyblish.api.ContextPlugin): [item for item, count in collections.Counter(subset_names).items() if count > 1] - msg = ( - "Instance subset names {} are not unique. " + - "Remove duplicates via SubsetManager.".format(non_unique) - ) + msg = ("Instance subset names {} are not unique. ".format(non_unique) + + "Remove duplicates via SubsetManager.") assert not non_unique, msg From 4103654c4ca2fc4775f226454797cb09c47daa2a Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 14:20:52 +0100 Subject: [PATCH 17/20] OP-2505 - removed explicit exit, breaks closing of console --- openpype/lib/remote_publish.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/lib/remote_publish.py b/openpype/lib/remote_publish.py index 9632e63ea0..ced03ea613 100644 --- a/openpype/lib/remote_publish.py +++ b/openpype/lib/remote_publish.py @@ -88,7 +88,6 @@ def publish(log, close_plugin_name=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) - sys.exit(1) def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): @@ -137,7 +136,6 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) - sys.exit(1) elif processed % log_every == 0: # pyblish returns progress in 0.0 - 2.0 progress = min(round(result["progress"] / 2 * 100), 99) From 13519cfcda8cf71ee772328f8aaa689d9168523b Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 3 Feb 2022 14:54:19 +0100 Subject: [PATCH 18/20] OP-2505 - added return --- openpype/lib/remote_publish.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/lib/remote_publish.py b/openpype/lib/remote_publish.py index ced03ea613..871eb82f11 100644 --- a/openpype/lib/remote_publish.py +++ b/openpype/lib/remote_publish.py @@ -136,6 +136,7 @@ def publish_and_log(dbcon, _id, log, close_plugin_name=None, batch_id=None): if close_plugin: # close host app explicitly after error context = pyblish.api.Context() close_plugin().process(context) + return elif processed % log_every == 0: # pyblish returns progress in 0.0 - 2.0 progress = min(round(result["progress"] / 2 * 100), 99) From 99eb61abaf727cf3aada1c971f872bb484da52b7 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Thu, 3 Feb 2022 18:28:54 +0100 Subject: [PATCH 19/20] fix pyenv, enhance dockerfile metadata --- Dockerfile | 35 ++++++++++++++++++++++++----------- Dockerfile.centos7 | 6 +++++- tools/docker_build.sh | 2 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index cef83b5811..7232223c3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,18 @@ # Build Pype docker image -FROM debian:bookworm-slim AS builder +FROM ubuntu:focal AS builder ARG OPENPYPE_PYTHON_VERSION=3.7.12 +ARG BUILD_DATE +ARG VERSION LABEL maintainer="info@openpype.io" -LABEL description="Docker Image to build and run OpenPype" +LABEL description="Docker Image to build and run OpenPype under Ubuntu 20.04" LABEL org.opencontainers.image.name="pypeclub/openpype" LABEL org.opencontainers.image.title="OpenPype Docker Image" LABEL org.opencontainers.image.url="https://openpype.io/" -LABEL org.opencontainers.image.source="https://github.com/pypeclub/pype" +LABEL org.opencontainers.image.source="https://github.com/pypeclub/OpenPype" +LABEL org.opencontainers.image.documentation="https://openpype.io/docs/system_introduction" +LABEL org.opencontainers.image.created=$BUILD_DATE +LABEL org.opencontainers.image.version=$VERSION USER root @@ -42,14 +47,19 @@ RUN apt-get update \ SHELL ["/bin/bash", "-c"] + RUN mkdir /opt/openpype +# download and install pyenv RUN curl https://pyenv.run | bash \ - && echo 'export PATH="$HOME/.pyenv/bin:$PATH"'>> $HOME/.bashrc \ - && echo 'eval "$(pyenv init -)"' >> $HOME/.bashrc \ - && echo 'eval "$(pyenv virtualenv-init -)"' >> $HOME/.bashrc \ - && echo 'eval "$(pyenv init --path)"' >> $HOME/.bashrc \ - && source $HOME/.bashrc && pyenv install ${OPENPYPE_PYTHON_VERSION} + && echo 'export PATH="$HOME/.pyenv/bin:$PATH"'>> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv init -)"' >> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv virtualenv-init -)"' >> $HOME/init_pyenv.sh \ + && echo 'eval "$(pyenv init --path)"' >> $HOME/init_pyenv.sh + +# install python with pyenv +RUN source $HOME/init_pyenv.sh \ + && pyenv install ${OPENPYPE_PYTHON_VERSION} COPY . /opt/openpype/ @@ -57,13 +67,16 @@ RUN chmod +x /opt/openpype/tools/create_env.sh && chmod +x /opt/openpype/tools/b WORKDIR /opt/openpype +# set local python version RUN cd /opt/openpype \ - && source $HOME/.bashrc \ + && source $HOME/init_pyenv.sh \ && pyenv local ${OPENPYPE_PYTHON_VERSION} -RUN source $HOME/.bashrc \ +# fetch third party tools/libraries +RUN source $HOME/init_pyenv.sh \ && ./tools/create_env.sh \ && ./tools/fetch_thirdparty_libs.sh -RUN source $HOME/.bashrc \ +# build openpype +RUN source $HOME/init_pyenv.sh \ && bash ./tools/build.sh diff --git a/Dockerfile.centos7 b/Dockerfile.centos7 index 736a42663c..16cb02cd20 100644 --- a/Dockerfile.centos7 +++ b/Dockerfile.centos7 @@ -1,11 +1,15 @@ # Build Pype docker image FROM centos:7 AS builder -ARG OPENPYPE_PYTHON_VERSION=3.7.10 +ARG OPENPYPE_PYTHON_VERSION=3.7.12 LABEL org.opencontainers.image.name="pypeclub/openpype" LABEL org.opencontainers.image.title="OpenPype Docker Image" LABEL org.opencontainers.image.url="https://openpype.io/" LABEL org.opencontainers.image.source="https://github.com/pypeclub/pype" +LABEL org.opencontainers.image.documentation="https://openpype.io/docs/system_introduction" +LABEL org.opencontainers.image.created=$BUILD_DATE +LABEL org.opencontainers.image.version=$VERSION + USER root diff --git a/tools/docker_build.sh b/tools/docker_build.sh index 04c26424eb..7d61986883 100755 --- a/tools/docker_build.sh +++ b/tools/docker_build.sh @@ -68,7 +68,7 @@ main () { echo -e "${BIGreen}>>>${RST} Running docker build ..." # docker build --pull --no-cache -t pypeclub/openpype:$openpype_version . - docker build --pull --iidfile $openpype_root/build/docker-image.id -t pypeclub/openpype:$openpype_version -f $dockerfile . + docker build --pull --iidfile $openpype_root/build/docker-image.id --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VERSION=$openpype_version -t pypeclub/openpype:$openpype_version -f $dockerfile . if [ $? -ne 0 ] ; then echo $? echo -e "${BIRed}!!!${RST} Docker build failed." From b81a7f2a97bf790a1c23158422d2a201e2054dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Fri, 4 Feb 2022 15:36:19 +0100 Subject: [PATCH 20/20] Update openpype/hosts/nuke/plugins/load/load_clip.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/nuke/plugins/load/load_clip.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/plugins/load/load_clip.py b/openpype/hosts/nuke/plugins/load/load_clip.py index 16df3e27d5..21b7a6a816 100644 --- a/openpype/hosts/nuke/plugins/load/load_clip.py +++ b/openpype/hosts/nuke/plugins/load/load_clip.py @@ -397,8 +397,7 @@ class LoadClip(plugin.NukeLoader): # Set colorspace defined in version data if ( colorspace is not None - and colorspace_exists_on_node( - node, str(colorspace)) is not False + and colorspace_exists_on_node(node, str(colorspace)) ): node["colorspace"].setValue(str(colorspace)) output_color = str(colorspace)