mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
wrap get_product_name function
This commit is contained in:
parent
f7e9f6e7c9
commit
348e11f968
1 changed files with 235 additions and 74 deletions
|
|
@ -1,4 +1,8 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
from functools import wraps
|
||||||
|
from typing import Optional, Any
|
||||||
|
|
||||||
import ayon_api
|
import ayon_api
|
||||||
from ayon_core.lib import (
|
from ayon_core.lib import (
|
||||||
|
|
@ -6,7 +10,9 @@ from ayon_core.lib import (
|
||||||
filter_profiles,
|
filter_profiles,
|
||||||
prepare_template_data,
|
prepare_template_data,
|
||||||
Logger,
|
Logger,
|
||||||
|
is_func_signature_supported,
|
||||||
)
|
)
|
||||||
|
from ayon_core.lib.path_templates import TemplateResult
|
||||||
from ayon_core.settings import get_project_settings
|
from ayon_core.settings import get_project_settings
|
||||||
|
|
||||||
from .constants import DEFAULT_PRODUCT_TEMPLATE
|
from .constants import DEFAULT_PRODUCT_TEMPLATE
|
||||||
|
|
@ -74,68 +80,27 @@ def get_product_name_template(
|
||||||
return template
|
return template
|
||||||
|
|
||||||
|
|
||||||
def get_product_name(
|
def _get_product_name_old(
|
||||||
project_name,
|
project_name: str,
|
||||||
task_name,
|
task_name: Optional[str],
|
||||||
task_type,
|
task_type: Optional[str],
|
||||||
host_name,
|
host_name: str,
|
||||||
product_type,
|
product_type: str,
|
||||||
variant,
|
variant: str,
|
||||||
default_template=None,
|
default_template: Optional[str] = None,
|
||||||
dynamic_data=None,
|
dynamic_data: Optional[dict[str, Any]] = None,
|
||||||
project_settings=None,
|
project_settings: Optional[dict[str, Any]] = None,
|
||||||
product_type_filter=None,
|
product_type_filter: Optional[str] = None,
|
||||||
project_entity=None,
|
project_entity: Optional[dict[str, Any]] = None,
|
||||||
folder_entity=None,
|
) -> TemplateResult:
|
||||||
task_entity=None,
|
warnings.warn(
|
||||||
):
|
"Used deprecated 'task_name' and 'task_type' arguments."
|
||||||
"""Calculate product name based on passed context and AYON settings.
|
" Please use new signature with 'folder_entity' and 'task_entity'.",
|
||||||
|
DeprecationWarning,
|
||||||
Subst name templates are defined in `project_settings/global/tools/creator
|
stacklevel=2
|
||||||
/product_name_profiles` where are profiles with host name, product type,
|
)
|
||||||
task name and task type filters. If context does not match any profile
|
|
||||||
then `DEFAULT_PRODUCT_TEMPLATE` is used as default template.
|
|
||||||
|
|
||||||
That's main reason why so many arguments are required to calculate product
|
|
||||||
name.
|
|
||||||
|
|
||||||
Todos:
|
|
||||||
Find better filtering options to avoid requirement of
|
|
||||||
argument 'family_filter'.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
project_name (str): Project name.
|
|
||||||
task_name (Union[str, None]): Task name. Deprecated use 'task_entity'.
|
|
||||||
task_type (Union[str, None]): Task type. Deprecated use 'task_entity'.
|
|
||||||
host_name (str): Host name.
|
|
||||||
product_type (str): Product type.
|
|
||||||
variant (str): In most of the cases it is user input during creation.
|
|
||||||
default_template (Optional[str]): Default template if any profile does
|
|
||||||
not match passed context. Constant 'DEFAULT_PRODUCT_TEMPLATE'
|
|
||||||
is used if is not passed.
|
|
||||||
dynamic_data (Optional[Dict[str, Any]]): Dynamic data specific for
|
|
||||||
a creator which creates instance.
|
|
||||||
project_settings (Optional[Union[Dict[str, Any]]]): Prepared settings
|
|
||||||
for project. Settings are queried if not passed.
|
|
||||||
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.
|
|
||||||
folder_entity (Optional[Dict[str, Any]]): Folder entity.
|
|
||||||
task_entity (Optional[Dict[str, Any]]): Task entity.
|
|
||||||
|
|
||||||
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:
|
if not product_type:
|
||||||
return ""
|
return StringTemplate("").format({})
|
||||||
|
|
||||||
template = get_product_name_template(
|
template = get_product_name_template(
|
||||||
project_name,
|
project_name,
|
||||||
|
|
@ -146,17 +111,6 @@ def get_product_name(
|
||||||
default_template=default_template,
|
default_template=default_template,
|
||||||
project_settings=project_settings
|
project_settings=project_settings
|
||||||
)
|
)
|
||||||
if task_name and not task_entity:
|
|
||||||
warnings.warn(
|
|
||||||
"Used deprecated 'task' argument. Please use"
|
|
||||||
" 'task_entity' instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=2
|
|
||||||
)
|
|
||||||
|
|
||||||
if task_entity:
|
|
||||||
task_name = task_entity["name"]
|
|
||||||
task_type = task_entity["taskType"]
|
|
||||||
|
|
||||||
template_low = template.lower()
|
template_low = template.lower()
|
||||||
# Simple check of task name existence for template with {task[name]} in
|
# Simple check of task name existence for template with {task[name]} in
|
||||||
|
|
@ -194,6 +148,106 @@ def get_product_name(
|
||||||
"type": product_type
|
"type": product_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dynamic_data:
|
||||||
|
# Dynamic data may override default values
|
||||||
|
for key, value in dynamic_data.items():
|
||||||
|
fill_pairs[key] = value
|
||||||
|
|
||||||
|
try:
|
||||||
|
return StringTemplate.format_strict_template(
|
||||||
|
template=template,
|
||||||
|
data=prepare_template_data(fill_pairs)
|
||||||
|
)
|
||||||
|
except KeyError as exp:
|
||||||
|
raise TemplateFillError(
|
||||||
|
"Value for {} key is missing in template '{}'."
|
||||||
|
" Available values are {}".format(str(exp), template, fill_pairs)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_product_name(
|
||||||
|
project_name: str,
|
||||||
|
folder_entity: dict[str, Any],
|
||||||
|
task_entity: Optional[dict[str, Any]],
|
||||||
|
host_name: str,
|
||||||
|
product_type: str,
|
||||||
|
variant: str,
|
||||||
|
*,
|
||||||
|
default_template: Optional[str] = None,
|
||||||
|
dynamic_data: Optional[dict[str, Any]] = None,
|
||||||
|
project_settings: Optional[dict[str, Any]] = None,
|
||||||
|
product_type_filter: Optional[str] = None,
|
||||||
|
project_entity: Optional[dict[str, Any]] = None,
|
||||||
|
# Ignore unused kwargs passed to 'get_product_name'
|
||||||
|
task_name: Optional[str] = None,
|
||||||
|
task_type: Optional[str] = None,
|
||||||
|
) -> TemplateResult:
|
||||||
|
"""Future replacement of 'get_product_name' function."""
|
||||||
|
# Future warning when 'task_name' and 'task_type' are deprecated
|
||||||
|
# if task_name is None:
|
||||||
|
# warnings.warn(
|
||||||
|
# "Still using deprecated 'task_name' argument. Please use"
|
||||||
|
# " 'task_entity' only.",
|
||||||
|
# DeprecationWarning,
|
||||||
|
# stacklevel=2
|
||||||
|
# )
|
||||||
|
|
||||||
|
if not product_type:
|
||||||
|
return StringTemplate("").format({})
|
||||||
|
|
||||||
|
task_name = task_type = None
|
||||||
|
if task_entity:
|
||||||
|
task_name = task_entity["name"]
|
||||||
|
task_type = task_entity["taskType"]
|
||||||
|
|
||||||
|
template = get_product_name_template(
|
||||||
|
project_name,
|
||||||
|
product_type_filter or product_type,
|
||||||
|
task_name,
|
||||||
|
task_type,
|
||||||
|
host_name,
|
||||||
|
default_template=default_template,
|
||||||
|
project_settings=project_settings
|
||||||
|
)
|
||||||
|
|
||||||
|
template_low = template.lower()
|
||||||
|
# Simple check of task name existence for template with {task[name]} in
|
||||||
|
if not task_name and "{task" in template_low:
|
||||||
|
raise TaskNotSetError()
|
||||||
|
|
||||||
|
task_value = {
|
||||||
|
"name": task_name,
|
||||||
|
"type": task_type,
|
||||||
|
}
|
||||||
|
if "{task}" in template_low:
|
||||||
|
task_value = task_name
|
||||||
|
# NOTE this is message for TDs and Admins -> not really for users
|
||||||
|
# TODO validate this in settings and not allow it
|
||||||
|
log.warning(
|
||||||
|
"Found deprecated task key '{task}' in product name template."
|
||||||
|
" Please use '{task[name]}' instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
elif "{task[short]}" in template_low:
|
||||||
|
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,
|
||||||
|
# TODO We should stop support 'family' key.
|
||||||
|
"family": product_type,
|
||||||
|
"task": task_value,
|
||||||
|
"product": {
|
||||||
|
"type": product_type
|
||||||
|
}
|
||||||
|
}
|
||||||
if folder_entity:
|
if folder_entity:
|
||||||
fill_pairs["folder"] = {
|
fill_pairs["folder"] = {
|
||||||
"name": folder_entity["name"],
|
"name": folder_entity["name"],
|
||||||
|
|
@ -212,6 +266,113 @@ def get_product_name(
|
||||||
)
|
)
|
||||||
except KeyError as exp:
|
except KeyError as exp:
|
||||||
raise TemplateFillError(
|
raise TemplateFillError(
|
||||||
"Value for {} key is missing in template '{}'."
|
f"Value for {exp} key is missing in template '{template}'."
|
||||||
" Available values are {}".format(str(exp), template, fill_pairs)
|
f" Available values are {fill_pairs}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_product_name_decorator(func):
|
||||||
|
"""Helper to decide which variant of 'get_product_name' to use.
|
||||||
|
|
||||||
|
The old version expected 'task_name' and 'task_type' arguments. The new
|
||||||
|
version expects 'folder_entity' and 'task_entity' arguments instead.
|
||||||
|
"""
|
||||||
|
@wraps(_get_product_name)
|
||||||
|
def inner(*args, **kwargs):
|
||||||
|
# ---
|
||||||
|
# Decide which variant of the function is used based on
|
||||||
|
# passed arguments.
|
||||||
|
# ---
|
||||||
|
|
||||||
|
# Entities in key-word arguments mean that the new function is used
|
||||||
|
if "folder_entity" in kwargs or "task_entity" in kwargs:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
# Using more than 6 positional arguments is not allowed
|
||||||
|
# in the new function
|
||||||
|
if len(args) > 6:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
if len(args) > 1:
|
||||||
|
arg_2 = args[1]
|
||||||
|
# Second argument is dictionary -> folder entity
|
||||||
|
if isinstance(arg_2, dict):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
|
if is_func_signature_supported(func, *args, **kwargs):
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return _get_product_name_old(*args, **kwargs)
|
||||||
|
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
def get_product_name(
|
||||||
|
project_name: str,
|
||||||
|
folder_entity: dict[str, Any],
|
||||||
|
task_entity: Optional[dict[str, Any]],
|
||||||
|
host_name: str,
|
||||||
|
product_type: str,
|
||||||
|
variant: str,
|
||||||
|
*,
|
||||||
|
default_template: Optional[str] = None,
|
||||||
|
dynamic_data: Optional[dict[str, Any]] = None,
|
||||||
|
project_settings: Optional[dict[str, Any]] = None,
|
||||||
|
product_type_filter: Optional[str] = None,
|
||||||
|
project_entity: Optional[dict[str, Any]] = None,
|
||||||
|
) -> TemplateResult:
|
||||||
|
"""Calculate product name based on passed context and AYON settings.
|
||||||
|
|
||||||
|
Subst name templates are defined in `project_settings/global/tools/creator
|
||||||
|
/product_name_profiles` where are profiles with host name, product type,
|
||||||
|
task name and task type filters. If context does not match any profile
|
||||||
|
then `DEFAULT_PRODUCT_TEMPLATE` is used as default template.
|
||||||
|
|
||||||
|
That's main reason why so many arguments are required to calculate product
|
||||||
|
name.
|
||||||
|
|
||||||
|
Todos:
|
||||||
|
Find better filtering options to avoid requirement of
|
||||||
|
argument 'family_filter'.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_name (str): Project name.
|
||||||
|
folder_entity (Optional[Dict[str, Any]]): Folder entity.
|
||||||
|
task_entity (Optional[Dict[str, Any]]): Task entity.
|
||||||
|
host_name (str): Host name.
|
||||||
|
product_type (str): Product type.
|
||||||
|
variant (str): In most of the cases it is user input during creation.
|
||||||
|
default_template (Optional[str]): Default template if any profile does
|
||||||
|
not match passed context. Constant 'DEFAULT_PRODUCT_TEMPLATE'
|
||||||
|
is used if is not passed.
|
||||||
|
dynamic_data (Optional[Dict[str, Any]]): Dynamic data specific for
|
||||||
|
a creator which creates instance.
|
||||||
|
project_settings (Optional[Union[Dict[str, Any]]]): Prepared settings
|
||||||
|
for project. Settings are queried if not passed.
|
||||||
|
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.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TemplateResult: Product name.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
TaskNotSetError: If template requires task which is not provided.
|
||||||
|
TemplateFillError: If filled template contains placeholder key which
|
||||||
|
is not collected.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return _get_product_name(
|
||||||
|
project_name,
|
||||||
|
folder_entity,
|
||||||
|
task_entity,
|
||||||
|
host_name,
|
||||||
|
product_type,
|
||||||
|
variant,
|
||||||
|
default_template=default_template,
|
||||||
|
dynamic_data=dynamic_data,
|
||||||
|
project_settings=project_settings,
|
||||||
|
product_type_filter=product_type_filter,
|
||||||
|
project_entity=project_entity,
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue