From d1214478781d689d5057f4d9e5a1e254989eaff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Fri, 7 Jun 2024 21:06:21 +0200 Subject: [PATCH 01/17] Pass status and author when integrating version --- client/ayon_core/plugins/publish/integrate.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/plugins/publish/integrate.py b/client/ayon_core/plugins/publish/integrate.py index 865b566e6e..89164255dc 100644 --- a/client/ayon_core/plugins/publish/integrate.py +++ b/client/ayon_core/plugins/publish/integrate.py @@ -380,29 +380,29 @@ class IntegrateAsset(pyblish.api.InstancePlugin): data = { "families": get_instance_families(instance) } - attribibutes = {} + attributes = {} product_group = instance.data.get("productGroup") if product_group: - attribibutes["productGroup"] = product_group + attributes["productGroup"] = product_group elif existing_product_entity: # Preserve previous product group if new version does not set it product_group = existing_product_entity.get("attrib", {}).get( "productGroup" ) if product_group is not None: - attribibutes["productGroup"] = product_group + attributes["productGroup"] = product_group product_id = None if existing_product_entity: product_id = existing_product_entity["id"] - + product_entity = new_product_entity( product_name, product_type, folder_entity["id"], data=data, - attribs=attribibutes, + attribs=attributes, entity_id=product_id ) @@ -464,6 +464,8 @@ class IntegrateAsset(pyblish.api.InstancePlugin): version_number, product_entity["id"], task_id=task_id, + author=instance.context.data.get("user"), + status=instance.data.get("status"), data=version_data, attribs=version_attributes, entity_id=version_id, From 43787fd9c39f16bc8bf75d401b038a5a2fb56988 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Sat, 8 Jun 2024 10:52:37 +0200 Subject: [PATCH 02/17] use AYON_USERNAME during publishing --- client/ayon_core/cli_commands.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/cli_commands.py b/client/ayon_core/cli_commands.py index 0fb18be687..c56ed16f1c 100644 --- a/client/ayon_core/cli_commands.py +++ b/client/ayon_core/cli_commands.py @@ -64,9 +64,10 @@ class Commands: get_global_context, ) - # Register target and host + import ayon_api import pyblish.util + # Register target and host if not isinstance(path, str): raise RuntimeError("Path to JSON must be a string.") @@ -86,6 +87,18 @@ class Commands: log = Logger.get_logger("CLI-publish") + # Make public ayon api behave as other user + # - this works only if public ayon api is using service user + username = os.environ.get("AYON_USERNAME") + if username: + # NOTE: ayon-python-api does not have public api function to find + # out if is used service user. So we need to have try > except + # block. + try: + ayon_api.set_default_service_username(username) + except ValueError: + pass + install_ayon_plugins() manager = AddonsManager() From b413a04cab65132aefe20cd9b56bf111265e497f Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:27:25 +0200 Subject: [PATCH 03/17] skip import from hosts folder --- client/ayon_core/addon/base.py | 106 +++++++++++------------------ client/ayon_core/hosts/__init__.py | 0 2 files changed, 40 insertions(+), 66 deletions(-) delete mode 100644 client/ayon_core/hosts/__init__.py diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index b10629ede8..6d0dd94df0 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -411,82 +411,56 @@ def _load_addons_in_core( ): # Add current directory at first place # - has small differences in import logic - hosts_dir = os.path.join(AYON_CORE_ROOT, "hosts") modules_dir = os.path.join(AYON_CORE_ROOT, "modules") + if not os.path.exists(modules_dir): + log.warning(( + "Could not find path when loading AYON addons \"{}\"" + ).format(modules_dir)) + return - for dirpath in {hosts_dir, modules_dir}: - if not os.path.exists(dirpath): - log.warning(( - "Could not find path when loading AYON addons \"{}\"" - ).format(dirpath)) + ignored_filenames = set(IGNORED_DEFAULT_FILENAMES) + + for filename in os.listdir(modules_dir): + # Ignore filenames + if filename in IGNORED_FILENAMES or filename in ignored_filenames: continue - is_in_modules_dir = dirpath == modules_dir - ignored_filenames = set() - if is_in_modules_dir: - ignored_filenames = set(IGNORED_DEFAULT_FILENAMES) + fullpath = os.path.join(modules_dir, filename) + basename, ext = os.path.splitext(filename) - for filename in os.listdir(dirpath): - # Ignore filenames - if filename in IGNORED_FILENAMES or filename in ignored_filenames: + if basename in ignore_addon_names: + continue + + # Validations + if os.path.isdir(fullpath): + # Check existence of init file + init_path = os.path.join(fullpath, "__init__.py") + if not os.path.exists(init_path): + log.debug(( + "Addon directory does not contain __init__.py" + " file {}" + ).format(fullpath)) continue - fullpath = os.path.join(dirpath, filename) - basename, ext = os.path.splitext(filename) + elif ext not in (".py", ): + continue - if basename in ignore_addon_names: - continue + # TODO add more logic how to define if folder is addon or not + # - check manifest and content of manifest + try: + # Don't import dynamically current directory modules + new_import_str = "{}.{}".format(modules_key, basename) - # Validations - if os.path.isdir(fullpath): - # Check existence of init file - init_path = os.path.join(fullpath, "__init__.py") - if not os.path.exists(init_path): - log.debug(( - "Addon directory does not contain __init__.py" - " file {}" - ).format(fullpath)) - continue + import_str = "ayon_core.modules.{}".format(basename) + default_module = __import__(import_str, fromlist=("", )) + sys.modules[new_import_str] = default_module + setattr(openpype_modules, basename, default_module) - elif ext not in (".py", ): - continue - - # TODO add more logic how to define if folder is addon or not - # - check manifest and content of manifest - try: - # Don't import dynamically current directory modules - new_import_str = "{}.{}".format(modules_key, basename) - if is_in_modules_dir: - import_str = "ayon_core.modules.{}".format(basename) - default_module = __import__(import_str, fromlist=("", )) - sys.modules[new_import_str] = default_module - setattr(openpype_modules, basename, default_module) - - else: - import_str = "ayon_core.hosts.{}".format(basename) - # Until all hosts are converted to be able use them as - # modules is this error check needed - try: - default_module = __import__( - import_str, fromlist=("", ) - ) - sys.modules[new_import_str] = default_module - setattr(openpype_modules, basename, default_module) - - except Exception: - log.warning( - "Failed to import host folder {}".format(basename), - exc_info=True - ) - - except Exception: - if is_in_modules_dir: - msg = "Failed to import in-core addon '{}'.".format( - basename - ) - else: - msg = "Failed to import addon '{}'.".format(fullpath) - log.error(msg, exc_info=True) + except Exception: + log.error( + f"Failed to import in-core addon '{basename}'.", + exc_info=True + ) def _load_addons(): diff --git a/client/ayon_core/hosts/__init__.py b/client/ayon_core/hosts/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 From df3670f30fc595fd14f5aab73ff8f17ec54ec4a1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:27:32 +0200 Subject: [PATCH 04/17] use sets --- client/ayon_core/addon/base.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 6d0dd94df0..1f1e749865 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -28,16 +28,16 @@ from .interfaces import ( ) # Files that will be always ignored on addons import -IGNORED_FILENAMES = ( +IGNORED_FILENAMES = { "__pycache__", -) +} # Files ignored on addons import from "./ayon_core/modules" -IGNORED_DEFAULT_FILENAMES = ( +IGNORED_DEFAULT_FILENAMES = { "__init__.py", "base.py", "interfaces.py", "click_wrap.py", -) +} # When addon was moved from ayon-core codebase # - this is used to log the missing addon @@ -418,11 +418,11 @@ def _load_addons_in_core( ).format(modules_dir)) return - ignored_filenames = set(IGNORED_DEFAULT_FILENAMES) + ignored_filenames = IGNORED_FILENAMES | IGNORED_DEFAULT_FILENAMES for filename in os.listdir(modules_dir): # Ignore filenames - if filename in IGNORED_FILENAMES or filename in ignored_filenames: + if filename in ignored_filenames: continue fullpath = os.path.join(modules_dir, filename) From cbac60598985697079f78f9b7edbc5b0141f4f23 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:28:24 +0200 Subject: [PATCH 05/17] use f-strings --- client/ayon_core/addon/base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 1f1e749865..878c50e039 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -438,8 +438,8 @@ def _load_addons_in_core( if not os.path.exists(init_path): log.debug(( "Addon directory does not contain __init__.py" - " file {}" - ).format(fullpath)) + f" file {fullpath}" + )) continue elif ext not in (".py", ): @@ -449,9 +449,9 @@ def _load_addons_in_core( # - check manifest and content of manifest try: # Don't import dynamically current directory modules - new_import_str = "{}.{}".format(modules_key, basename) + new_import_str = f"{modules_key}.{basename}" - import_str = "ayon_core.modules.{}".format(basename) + import_str = f"ayon_core.modules.{basename}" default_module = __import__(import_str, fromlist=("", )) sys.modules[new_import_str] = default_module setattr(openpype_modules, basename, default_module) From ef3068a4c205767e47398a225497dae13bc08a09 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:28:32 +0200 Subject: [PATCH 06/17] use direct comparison --- client/ayon_core/addon/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 878c50e039..8c5158a712 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -442,7 +442,7 @@ def _load_addons_in_core( )) continue - elif ext not in (".py", ): + elif ext != ".py": continue # TODO add more logic how to define if folder is addon or not From b14c041cf86b5bded6d4bbf26becbfe0456be166 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:37:52 +0200 Subject: [PATCH 07/17] more f-string --- client/ayon_core/addon/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ayon_core/addon/base.py b/client/ayon_core/addon/base.py index 8c5158a712..b9ecff4233 100644 --- a/client/ayon_core/addon/base.py +++ b/client/ayon_core/addon/base.py @@ -413,9 +413,9 @@ def _load_addons_in_core( # - has small differences in import logic modules_dir = os.path.join(AYON_CORE_ROOT, "modules") if not os.path.exists(modules_dir): - log.warning(( - "Could not find path when loading AYON addons \"{}\"" - ).format(modules_dir)) + log.warning( + f"Could not find path when loading AYON addons \"{modules_dir}\"" + ) return ignored_filenames = IGNORED_FILENAMES | IGNORED_DEFAULT_FILENAMES From c7a2cb95a1c37f16a0c262a479edc7c5a9636310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 10 Jun 2024 15:43:40 +0200 Subject: [PATCH 08/17] Update client/ayon_core/plugins/publish/integrate.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- client/ayon_core/plugins/publish/integrate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/integrate.py b/client/ayon_core/plugins/publish/integrate.py index 89164255dc..229dea7ecd 100644 --- a/client/ayon_core/plugins/publish/integrate.py +++ b/client/ayon_core/plugins/publish/integrate.py @@ -396,7 +396,6 @@ class IntegrateAsset(pyblish.api.InstancePlugin): product_id = None if existing_product_entity: product_id = existing_product_entity["id"] - product_entity = new_product_entity( product_name, product_type, From f6e3dcb4742e083664744de016476d8c134f5ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 10 Jun 2024 17:34:41 +0200 Subject: [PATCH 09/17] Remove `author` kwarg from new_version_entity as it's being resolved at https://github.com/ynput/ayon-core/commit/43787fd9c39f16bc8bf75d401b038a5a2fb56988 now --- client/ayon_core/plugins/publish/integrate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/integrate.py b/client/ayon_core/plugins/publish/integrate.py index 229dea7ecd..1a4cda4dbb 100644 --- a/client/ayon_core/plugins/publish/integrate.py +++ b/client/ayon_core/plugins/publish/integrate.py @@ -463,7 +463,6 @@ class IntegrateAsset(pyblish.api.InstancePlugin): version_number, product_entity["id"], task_id=task_id, - author=instance.context.data.get("user"), status=instance.data.get("status"), data=version_data, attribs=version_attributes, From 8f305cddb529d89594cdf9eeb7c7a53d10ff6e9a Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:13:44 +0200 Subject: [PATCH 10/17] added websocket-client requirement --- client/pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/client/pyproject.toml b/client/pyproject.toml index 72e5dd2794..5c8f831794 100644 --- a/client/pyproject.toml +++ b/client/pyproject.toml @@ -17,3 +17,4 @@ Click = "^8" OpenTimelineIO = "0.16.0" opencolorio = "2.2.1" Pillow = "9.5.0" +websocket-client = ">=0.40.0,<1" From 6b1b19d5c9a8388bfaead32eb44dfd3af003a6ee Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:00:48 +0200 Subject: [PATCH 11/17] added more range of supported versions --- client/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pyproject.toml b/client/pyproject.toml index 5c8f831794..ca88a37125 100644 --- a/client/pyproject.toml +++ b/client/pyproject.toml @@ -17,4 +17,4 @@ Click = "^8" OpenTimelineIO = "0.16.0" opencolorio = "2.2.1" Pillow = "9.5.0" -websocket-client = ">=0.40.0,<1" +websocket-client = ">=0.40.0,<2" From ba90adbfba75c407b39fbf7b2ca6da47c56d2fee Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 11 Jun 2024 15:16:33 +0200 Subject: [PATCH 12/17] Only report errors for not found addons if no valid farm addon found --- .../plugins/publish/collect_farm_target.py | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_farm_target.py b/client/ayon_core/plugins/publish/collect_farm_target.py index 3bf89450ec..bd7dfdcd46 100644 --- a/client/ayon_core/plugins/publish/collect_farm_target.py +++ b/client/ayon_core/plugins/publish/collect_farm_target.py @@ -14,22 +14,20 @@ class CollectFarmTarget(pyblish.api.InstancePlugin): if not instance.data.get("farm"): return - context = instance.context + addons_manager = instance.context.data.get("ayonAddonsManager") - farm_name = "" - addons_manager = context.data.get("ayonAddonsManager") - - for farm_renderer in ["deadline", "royalrender"]: + farm_renderer_addons = ["deadline", "royalrender"] + for farm_renderer in farm_renderer_addons: addon = addons_manager.get(farm_renderer, False) - - if not addon: - self.log.error("Cannot find AYON addon '{0}'.".format( - farm_renderer)) - elif addon.enabled: + if addon.enabled: farm_name = farm_renderer - - if farm_name: - self.log.debug("Collected render target: {0}".format(farm_name)) - instance.data["toBeRenderedOn"] = farm_name + break else: + # No enabled farm render addon found, then report all farm + # addons that were searched for yet not found + for farm_renderer in farm_renderer_addons: + self.log.error(f"Cannot find AYON addon '{farm_renderer}'.") AssertionError("No AYON renderer addon found") + + self.log.debug("Collected render target: {0}".format(farm_name)) + instance.data["toBeRenderedOn"] = farm_name From a0ce95f935a06cafa97cbdbd2d619e023a4e697c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 11 Jun 2024 15:21:20 +0200 Subject: [PATCH 13/17] Actually raise an error instead of just creating an `AssertionError` instance and doing nothing with it --- client/ayon_core/plugins/publish/collect_farm_target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/collect_farm_target.py b/client/ayon_core/plugins/publish/collect_farm_target.py index bd7dfdcd46..708f1b45a4 100644 --- a/client/ayon_core/plugins/publish/collect_farm_target.py +++ b/client/ayon_core/plugins/publish/collect_farm_target.py @@ -27,7 +27,7 @@ class CollectFarmTarget(pyblish.api.InstancePlugin): # addons that were searched for yet not found for farm_renderer in farm_renderer_addons: self.log.error(f"Cannot find AYON addon '{farm_renderer}'.") - AssertionError("No AYON renderer addon found") + raise RuntimeError("No AYON renderer addon found.") self.log.debug("Collected render target: {0}".format(farm_name)) instance.data["toBeRenderedOn"] = farm_name From 3b5791a8e08c8b9831b2ad95a2511006fcf3478c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 11 Jun 2024 15:27:28 +0200 Subject: [PATCH 14/17] Fix logic --- client/ayon_core/plugins/publish/collect_farm_target.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_farm_target.py b/client/ayon_core/plugins/publish/collect_farm_target.py index 708f1b45a4..e0edd795d8 100644 --- a/client/ayon_core/plugins/publish/collect_farm_target.py +++ b/client/ayon_core/plugins/publish/collect_farm_target.py @@ -18,8 +18,8 @@ class CollectFarmTarget(pyblish.api.InstancePlugin): farm_renderer_addons = ["deadline", "royalrender"] for farm_renderer in farm_renderer_addons: - addon = addons_manager.get(farm_renderer, False) - if addon.enabled: + addon = addons_manager.get(farm_renderer) + if addon and addon.enabled: farm_name = farm_renderer break else: From 8a5a078c29eaefbd08358d7f7b3bea41cb0cb0e5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:50:37 +0200 Subject: [PATCH 15/17] use 'get_server_api_connection' to get connection --- client/ayon_core/cli_commands.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/cli_commands.py b/client/ayon_core/cli_commands.py index c56ed16f1c..ca0693db2f 100644 --- a/client/ayon_core/cli_commands.py +++ b/client/ayon_core/cli_commands.py @@ -94,8 +94,9 @@ class Commands: # NOTE: ayon-python-api does not have public api function to find # out if is used service user. So we need to have try > except # block. + con = ayon_api.get_server_api_connection() try: - ayon_api.set_default_service_username(username) + con.set_default_service_username(username) except ValueError: pass From 3cb6b869e3483d44f30f0ae407c621d62c1092ae Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 11 Jun 2024 23:07:36 +0800 Subject: [PATCH 16/17] fix scene inventory not shown up --- .../max/client/ayon_max/api/pipeline.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/server_addon/max/client/ayon_max/api/pipeline.py b/server_addon/max/client/ayon_max/api/pipeline.py index 5f5e896e86..324de9fba1 100644 --- a/server_addon/max/client/ayon_max/api/pipeline.py +++ b/server_addon/max/client/ayon_max/api/pipeline.py @@ -145,7 +145,27 @@ attributes "OpenPypeContext" rt.saveMaxFile(dst_path) -def ls() -> list: +def parse_container(container): + """Return the container node's full container data. + + Args: + container (str): A container node name. + + Returns: + dict: The container schema data for this container node. + + """ + data = lib.read(container) + + # Backwards compatibility pre-schemas for containers + data["schema"] = data.get("schema", "openpype:container-1.0") + + # Append transient data + data["objectName"] = container.Name + return data + + +def ls(): """Get all AYON containers.""" objs = rt.objects containers = [ @@ -156,7 +176,7 @@ def ls() -> list: ] for container in sorted(containers, key=attrgetter("name")): - yield lib.read(container) + yield parse_container(container) def on_new(): From 6d42703cf4d47d43c32027c2c4d5ca88b35e4f98 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 11 Jun 2024 23:11:03 +0800 Subject: [PATCH 17/17] Update server_addon/max/client/ayon_max/api/pipeline.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server_addon/max/client/ayon_max/api/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/max/client/ayon_max/api/pipeline.py b/server_addon/max/client/ayon_max/api/pipeline.py index 324de9fba1..a87cd657ce 100644 --- a/server_addon/max/client/ayon_max/api/pipeline.py +++ b/server_addon/max/client/ayon_max/api/pipeline.py @@ -158,7 +158,7 @@ def parse_container(container): data = lib.read(container) # Backwards compatibility pre-schemas for containers - data["schema"] = data.get("schema", "openpype:container-1.0") + data["schema"] = data.get("schema", "openpype:container-3.0") # Append transient data data["objectName"] = container.Name