From 6467df96f45b434227b674d96cad810cebb878f6 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:43:53 +0200 Subject: [PATCH 1/5] fill task short name using project entity --- .../ayon_core/pipeline/create/product_name.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/client/ayon_core/pipeline/create/product_name.py b/client/ayon_core/pipeline/create/product_name.py index fecda867e5..6f8a43cdbe 100644 --- a/client/ayon_core/pipeline/create/product_name.py +++ b/client/ayon_core/pipeline/create/product_name.py @@ -1,3 +1,5 @@ +import ayon_api + from ayon_core.settings import get_project_settings from ayon_core.lib import filter_profiles, prepare_template_data @@ -88,6 +90,7 @@ def get_product_name( dynamic_data=None, project_settings=None, product_type_filter=None, + project_entity=None, ): """Calculate product name based on passed context and AYON settings. @@ -120,6 +123,8 @@ def get_product_name( product_type_filter (Optional[str]): Use different product type for product template filtering. Value of `product_type` is used when not passed. + project_entity (Optional[Dict[str, Any]]): Project entity used when + task short name is required by template. Raises: TemplateFillError: If filled template contains placeholder key which @@ -150,6 +155,18 @@ def get_product_name( if "{task}" in template.lower(): task_value = task_name + elif "{task[short]}" in template.lower(): + # NOTE this is very inefficient approach + # - project entity should be required + if project_entity is None: + project_entity = ayon_api.get_project(project_name) + task_types_by_name = { + task["name"]: task for task in + project_entity["taskTypes"] + } + task_short = task_types_by_name.get(task_type, {}).get("shortName") + task_value["short"] = task_short + fill_pairs = { "variant": variant, "family": product_type, From 3dffcaff01534c3eceaf8306c6398a3d70cb85cf Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:34:36 +0200 Subject: [PATCH 2/5] create context does pass in project entity --- client/ayon_core/pipeline/create/context.py | 29 ++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 0d8722dab1..066a147479 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -13,6 +13,7 @@ import pyblish.api import ayon_api from ayon_core.settings import get_project_settings +from ayon_core.lib import is_func_signature_supported from ayon_core.lib.attribute_definitions import ( UnknownDef, serialize_attr_defs, @@ -1404,6 +1405,7 @@ class CreateContext: self._current_workfile_path = None self._current_project_settings = None + self._current_project_entity = _NOT_SET self._current_folder_entity = _NOT_SET self._current_task_entity = _NOT_SET self._current_task_type = _NOT_SET @@ -1592,6 +1594,22 @@ class CreateContext: self._current_task_type = task_type return self._current_task_type + def get_current_project_entity(self): + """Project entity for current context project. + + Returns: + Union[dict[str, Any], None]: Folder entity. + + """ + if self._current_project_entity is not _NOT_SET: + return copy.deepcopy(self._current_project_entity) + project_entity = None + project_name = self.get_current_project_name() + if project_name: + project_entity = ayon_api.get_project(project_name) + self._current_project_entity = project_entity + return copy.deepcopy(self._current_project_entity) + def get_current_folder_entity(self): """Folder entity for current context folder. @@ -1788,6 +1806,7 @@ class CreateContext: self._current_task_name = task_name self._current_workfile_path = workfile_path + self._current_project_entity = _NOT_SET self._current_folder_entity = _NOT_SET self._current_task_entity = _NOT_SET self._current_task_type = _NOT_SET @@ -2083,13 +2102,21 @@ class CreateContext: # TODO validate types _pre_create_data.update(pre_create_data) - product_name = creator.get_product_name( + project_entity = self.get_current_project_entity() + args = ( project_name, folder_entity, task_entity, variant, self.host_name, ) + kwargs = {"project_entity": project_entity} + # Backwards compatibility for 'project_entity' argument + if not is_func_signature_supported( + creator.get_product_name, *args, **kwargs + ): + kwargs.pop("project_entity") + product_name = creator.get_product_name(*args, **kwargs) instance_data = { "folderPath": folder_entity["path"], From 2f0a6847ab4d72cf65329b0bcac5234d35db519d Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 8 Jul 2024 17:43:44 +0200 Subject: [PATCH 3/5] prefill project entity where we know it may be used --- client/ayon_core/pipeline/create/context.py | 1 + .../pipeline/create/creator_plugins.py | 10 ++++++---- .../ayon_core/pipeline/create/product_name.py | 8 +++++--- client/ayon_core/tools/publisher/abstract.py | 6 ++++++ client/ayon_core/tools/publisher/control.py | 3 +++ .../tools/publisher/models/create.py | 19 ++++++++++++++++--- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 066a147479..f97d34d305 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -2112,6 +2112,7 @@ class CreateContext: ) kwargs = {"project_entity": project_entity} # Backwards compatibility for 'project_entity' argument + # - 'get_product_name' signature changed 24/07/08 if not is_func_signature_supported( creator.get_product_name, *args, **kwargs ): diff --git a/client/ayon_core/pipeline/create/creator_plugins.py b/client/ayon_core/pipeline/create/creator_plugins.py index e0b30763d0..8cacf7a1d0 100644 --- a/client/ayon_core/pipeline/create/creator_plugins.py +++ b/client/ayon_core/pipeline/create/creator_plugins.py @@ -297,7 +297,6 @@ class BaseCreator: )) setattr(self, key, value) - @property def identifier(self): """Identifier of creator (must be unique). @@ -493,7 +492,8 @@ class BaseCreator: task_entity, variant, host_name=None, - instance=None + instance=None, + project_entity=None, ): """Return product name for passed context. @@ -510,8 +510,9 @@ class BaseCreator: instance (Optional[CreatedInstance]): Object of 'CreatedInstance' for which is product name updated. Passed only on product name update. - """ + project_entity (Optional[dict[str, Any]]): Project entity. + """ if host_name is None: host_name = self.create_context.host_name @@ -537,7 +538,8 @@ class BaseCreator: self.product_type, variant, dynamic_data=dynamic_data, - project_settings=self.project_settings + project_settings=self.project_settings, + project_entity=project_entity, ) def get_instance_attr_defs(self): diff --git a/client/ayon_core/pipeline/create/product_name.py b/client/ayon_core/pipeline/create/product_name.py index 6f8a43cdbe..cd28a6eef0 100644 --- a/client/ayon_core/pipeline/create/product_name.py +++ b/client/ayon_core/pipeline/create/product_name.py @@ -126,11 +126,15 @@ def get_product_name( project_entity (Optional[Dict[str, Any]]): Project entity used when task short name is required by template. + Returns: + str: Product name. + Raises: + TaskNotSetError: If template requires task which is not provided. TemplateFillError: If filled template contains placeholder key which is not collected. - """ + """ if not product_type: return "" @@ -156,8 +160,6 @@ def get_product_name( task_value = task_name elif "{task[short]}" in template.lower(): - # NOTE this is very inefficient approach - # - project entity should be required if project_entity is None: project_entity = ayon_api.get_project(project_name) task_types_by_name = { diff --git a/client/ayon_core/tools/publisher/abstract.py b/client/ayon_core/tools/publisher/abstract.py index a9142396f5..768f4b052f 100644 --- a/client/ayon_core/tools/publisher/abstract.py +++ b/client/ayon_core/tools/publisher/abstract.py @@ -166,6 +166,12 @@ class AbstractPublisherBackend(AbstractPublisherCommon): ) -> Union[TaskItem, None]: pass + @abstractmethod + def get_project_entity( + self, project_name: str + ) -> Union[Dict[str, Any], None]: + pass + @abstractmethod def get_folder_entity( self, project_name: str, folder_id: str diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index f26f8fc524..257b45de08 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -193,6 +193,9 @@ class PublisherController( def get_convertor_items(self): return self._create_model.get_convertor_items() + def get_project_entity(self, project_name): + return self._projects_model.get_project_entity(project_name) + def get_folder_type_items(self, project_name, sender=None): return self._projects_model.get_folder_type_items( project_name, sender diff --git a/client/ayon_core/tools/publisher/models/create.py b/client/ayon_core/tools/publisher/models/create.py index 6da3a51a31..ab2bf07614 100644 --- a/client/ayon_core/tools/publisher/models/create.py +++ b/client/ayon_core/tools/publisher/models/create.py @@ -9,6 +9,7 @@ from ayon_core.lib.attribute_definitions import ( ) from ayon_core.lib.profiles_filtering import filter_profiles from ayon_core.lib.attribute_definitions import UIDef +from ayon_core.lib import is_func_signature_supported from ayon_core.pipeline.create import ( BaseCreator, AutoCreator, @@ -26,6 +27,7 @@ from ayon_core.tools.publisher.abstract import ( AbstractPublisherBackend, CardMessageTypes, ) + CREATE_EVENT_SOURCE = "publisher.create.model" @@ -356,13 +358,24 @@ class CreateModel: project_name, task_item.task_id ) - return creator.get_product_name( + project_entity = self._controller.get_project_entity(project_name) + args = ( project_name, folder_entity, task_entity, - variant, - instance=instance + variant ) + kwargs = { + "instance": instance, + "project_entity": project_entity, + } + # Backwards compatibility for 'project_entity' argument + # - 'get_product_name' signature changed 24/07/08 + if not is_func_signature_supported( + creator.get_product_name, *args, **kwargs + ): + kwargs.pop("project_entity") + return creator.get_product_name(*args, **kwargs) def create( self, From 8b2600fb39e4f86931267e089a949209873e5854 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 9 Jul 2024 23:18:48 +0300 Subject: [PATCH 4/5] fix typo --- .../pipeline/workfile/workfile_template_builder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/pipeline/workfile/workfile_template_builder.py b/client/ayon_core/pipeline/workfile/workfile_template_builder.py index bb94d87483..ab19e940d9 100644 --- a/client/ayon_core/pipeline/workfile/workfile_template_builder.py +++ b/client/ayon_core/pipeline/workfile/workfile_template_builder.py @@ -3,7 +3,7 @@ Build templates are manually prepared using plugin definitions which create placeholders inside the template which are populated on import. -This approach is very explicit to achive very specific build logic that can be +This approach is very explicit to achieve very specific build logic that can be targeted by task types and names. Placeholders are created using placeholder plugins which should care about @@ -87,7 +87,7 @@ class AbstractTemplateBuilder(object): """Abstraction of Template Builder. Builder cares about context, shared data, cache, discovery of plugins - and trigger logic. Provides public api for host workfile build systen. + and trigger logic. Provides public api for host workfile build system. Rest of logic is based on plugins that care about collection and creation of placeholder items. @@ -806,7 +806,7 @@ class AbstractTemplateBuilder(object): ) def get_template_preset(self): - """Unified way how template preset is received usign settings. + """Unified way how template preset is received using settings. Method is dependent on '_get_build_profiles' which should return filter profiles to resolve path to a template. Default implementation looks @@ -1427,7 +1427,7 @@ class PlaceholderLoadMixin(object): placeholder='{"camera":"persp", "lights":True}', tooltip=( "Loader" - "\nDefines a dictionnary of arguments used to load assets." + "\nDefines a dictionary of arguments used to load assets." "\nUseable arguments depend on current placeholder Loader." "\nField should be a valid python dict." " Anything else will be ignored." @@ -1472,7 +1472,7 @@ class PlaceholderLoadMixin(object): ] def parse_loader_args(self, loader_args): - """Helper function to parse string of loader arugments. + """Helper function to parse string of loader arguments. Empty dictionary is returned if conversion fails. From 2e44f15dabeb4b147a25ea8bd6cce4a539831393 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Tue, 9 Jul 2024 23:19:32 +0300 Subject: [PATCH 5/5] replace task_name with task_entity --- client/ayon_core/pipeline/workfile/workfile_template_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/pipeline/workfile/workfile_template_builder.py b/client/ayon_core/pipeline/workfile/workfile_template_builder.py index ab19e940d9..4a1f3a84da 100644 --- a/client/ayon_core/pipeline/workfile/workfile_template_builder.py +++ b/client/ayon_core/pipeline/workfile/workfile_template_builder.py @@ -1872,7 +1872,7 @@ class PlaceholderCreateMixin(object): creator_plugin.identifier, create_variant, folder_entity, - task_name=task_name, + task_entity, pre_create_data=pre_create_data )