mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #560 from ynput/enhancement/AY-5539_define-creators-per-task
Publisher: filter creators based on task
This commit is contained in:
commit
0a702fe09c
3 changed files with 177 additions and 2 deletions
|
|
@ -37,6 +37,7 @@ from .creator_plugins import (
|
|||
|
||||
# Changes of instances and context are send as tuple of 2 information
|
||||
UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"])
|
||||
_NOT_SET = object()
|
||||
|
||||
|
||||
class UnavailableSharedData(Exception):
|
||||
|
|
@ -1401,6 +1402,11 @@ class CreateContext:
|
|||
self._current_folder_path = None
|
||||
self._current_task_name = None
|
||||
self._current_workfile_path = None
|
||||
self._current_project_settings = None
|
||||
|
||||
self._current_folder_entity = _NOT_SET
|
||||
self._current_task_entity = _NOT_SET
|
||||
self._current_task_type = _NOT_SET
|
||||
|
||||
self._current_project_anatomy = None
|
||||
|
||||
|
|
@ -1571,6 +1577,64 @@ class CreateContext:
|
|||
|
||||
return self._current_task_name
|
||||
|
||||
def get_current_task_type(self):
|
||||
"""Task type which was used as current context on context reset.
|
||||
|
||||
Returns:
|
||||
Union[str, None]: Task type.
|
||||
|
||||
"""
|
||||
if self._current_task_type is _NOT_SET:
|
||||
task_type = None
|
||||
task_entity = self.get_current_task_entity()
|
||||
if task_entity:
|
||||
task_type = task_entity["taskType"]
|
||||
self._current_task_type = task_type
|
||||
return self._current_task_type
|
||||
|
||||
def get_current_folder_entity(self):
|
||||
"""Folder entity for current context folder.
|
||||
|
||||
Returns:
|
||||
Union[dict[str, Any], None]: Folder entity.
|
||||
|
||||
"""
|
||||
if self._current_folder_entity is not _NOT_SET:
|
||||
return copy.deepcopy(self._current_folder_entity)
|
||||
folder_entity = None
|
||||
folder_path = self.get_current_folder_path()
|
||||
if folder_path:
|
||||
project_name = self.get_current_project_name()
|
||||
folder_entity = ayon_api.get_folder_by_path(
|
||||
project_name, folder_path
|
||||
)
|
||||
self._current_folder_entity = folder_entity
|
||||
return copy.deepcopy(self._current_folder_entity)
|
||||
|
||||
def get_current_task_entity(self):
|
||||
"""Task entity for current context task.
|
||||
|
||||
Returns:
|
||||
Union[dict[str, Any], None]: Task entity.
|
||||
|
||||
"""
|
||||
if self._current_task_entity is not _NOT_SET:
|
||||
return copy.deepcopy(self._current_task_entity)
|
||||
task_entity = None
|
||||
task_name = self.get_current_task_name()
|
||||
if task_name:
|
||||
folder_entity = self.get_current_folder_entity()
|
||||
if folder_entity:
|
||||
project_name = self.get_current_project_name()
|
||||
task_entity = ayon_api.get_task_by_name(
|
||||
project_name,
|
||||
folder_id=folder_entity["id"],
|
||||
task_name=task_name
|
||||
)
|
||||
self._current_task_entity = task_entity
|
||||
return copy.deepcopy(self._current_task_entity)
|
||||
|
||||
|
||||
def get_current_workfile_path(self):
|
||||
"""Workfile path which was opened on context reset.
|
||||
|
||||
|
|
@ -1592,6 +1656,12 @@ class CreateContext:
|
|||
self._current_project_name)
|
||||
return self._current_project_anatomy
|
||||
|
||||
def get_current_project_settings(self):
|
||||
if self._current_project_settings is None:
|
||||
self._current_project_settings = get_project_settings(
|
||||
self.get_current_project_name())
|
||||
return self._current_project_settings
|
||||
|
||||
@property
|
||||
def context_has_changed(self):
|
||||
"""Host context has changed.
|
||||
|
|
@ -1718,7 +1788,12 @@ class CreateContext:
|
|||
self._current_task_name = task_name
|
||||
self._current_workfile_path = workfile_path
|
||||
|
||||
self._current_folder_entity = _NOT_SET
|
||||
self._current_task_entity = _NOT_SET
|
||||
self._current_task_type = _NOT_SET
|
||||
|
||||
self._current_project_anatomy = None
|
||||
self._current_project_settings = None
|
||||
|
||||
def reset_plugins(self, discover_publish_plugins=True):
|
||||
"""Reload plugins.
|
||||
|
|
@ -1772,7 +1847,7 @@ class CreateContext:
|
|||
|
||||
def _reset_creator_plugins(self):
|
||||
# Prepare settings
|
||||
project_settings = get_project_settings(self.project_name)
|
||||
project_settings = self.get_current_project_settings()
|
||||
|
||||
# Discover and prepare creators
|
||||
creators = {}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import tempfile
|
|||
import shutil
|
||||
import inspect
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import re
|
||||
|
||||
import six
|
||||
import arrow
|
||||
|
|
@ -39,6 +40,7 @@ from ayon_core.pipeline.create.context import (
|
|||
)
|
||||
from ayon_core.pipeline.publish import get_publish_instance_label
|
||||
from ayon_core.tools.common_models import HierarchyModel
|
||||
from ayon_core.lib.profiles_filtering import filter_profiles
|
||||
|
||||
# Define constant for plugin orders offset
|
||||
PLUGIN_ORDER_OFFSET = 0.5
|
||||
|
|
@ -1686,6 +1688,15 @@ class PublisherController(BasePublisherController):
|
|||
"""Publish plugins."""
|
||||
return self._create_context.publish_plugins
|
||||
|
||||
def _get_current_project_settings(self):
|
||||
"""Current project settings.
|
||||
|
||||
Returns:
|
||||
dict
|
||||
"""
|
||||
|
||||
return self._create_context.get_current_project_settings()
|
||||
|
||||
# Hierarchy model
|
||||
def get_folder_items(self, project_name, sender=None):
|
||||
return self._hierarchy_model.get_folder_items(project_name, sender)
|
||||
|
|
@ -1827,8 +1838,13 @@ class PublisherController(BasePublisherController):
|
|||
def _collect_creator_items(self):
|
||||
# TODO add crashed initialization of create plugins to report
|
||||
output = {}
|
||||
allowed_creator_pattern = self._get_allowed_creators_pattern()
|
||||
for identifier, creator in self._create_context.creators.items():
|
||||
try:
|
||||
if (not self._is_label_allowed(
|
||||
creator.label, allowed_creator_pattern)):
|
||||
self.log.debug(f"{creator.label} not allowed for context")
|
||||
continue
|
||||
output[identifier] = CreatorItem.from_creator(creator)
|
||||
except Exception:
|
||||
self.log.error(
|
||||
|
|
@ -1839,6 +1855,60 @@ class PublisherController(BasePublisherController):
|
|||
|
||||
return output
|
||||
|
||||
def _get_allowed_creators_pattern(self):
|
||||
"""Provide regex pattern for configured creator labels in this context
|
||||
|
||||
If no profile matches current context, it shows all creators.
|
||||
Support usage of regular expressions for configured values.
|
||||
Returns:
|
||||
(re.Pattern)[optional]: None or regex compiled patterns
|
||||
into single one ('Render|Image.*')
|
||||
"""
|
||||
|
||||
task_type = self._create_context.get_current_task_type()
|
||||
project_settings = self._get_current_project_settings()
|
||||
|
||||
filter_creator_profiles = (
|
||||
project_settings
|
||||
["core"]
|
||||
["tools"]
|
||||
["creator"]
|
||||
["filter_creator_profiles"]
|
||||
)
|
||||
filtering_criteria = {
|
||||
"task_names": self.current_task_name,
|
||||
"task_types": task_type,
|
||||
"host_names": self._create_context.host_name
|
||||
}
|
||||
profile = filter_profiles(
|
||||
filter_creator_profiles,
|
||||
filtering_criteria,
|
||||
logger=self.log
|
||||
)
|
||||
|
||||
allowed_creator_pattern = None
|
||||
if profile:
|
||||
allowed_creator_labels = {
|
||||
label
|
||||
for label in profile["creator_labels"]
|
||||
if label
|
||||
}
|
||||
self.log.debug(f"Only allowed `{allowed_creator_labels}` creators")
|
||||
allowed_creator_pattern = (
|
||||
re.compile("|".join(allowed_creator_labels)))
|
||||
return allowed_creator_pattern
|
||||
|
||||
def _is_label_allowed(self, label, allowed_labels_regex):
|
||||
"""Implement regex support for allowed labels.
|
||||
|
||||
Args:
|
||||
label (str): Label of creator - shown in Publisher
|
||||
allowed_labels_regex (re.Pattern): compiled regular expression
|
||||
"""
|
||||
if not allowed_labels_regex:
|
||||
return True
|
||||
return bool(allowed_labels_regex.match(label))
|
||||
|
||||
def _reset_instances(self):
|
||||
"""Reset create instances."""
|
||||
if self._resetting_instances:
|
||||
|
|
|
|||
|
|
@ -35,6 +35,28 @@ class ProductNameProfile(BaseSettingsModel):
|
|||
template: str = SettingsField("", title="Template")
|
||||
|
||||
|
||||
class FilterCreatorProfile(BaseSettingsModel):
|
||||
"""Provide list of allowed Creator identifiers for context"""
|
||||
|
||||
_layout = "expanded"
|
||||
host_names: list[str] = SettingsField(
|
||||
default_factory=list, title="Host names"
|
||||
)
|
||||
task_types: list[str] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Task types",
|
||||
enum_resolver=task_types_enum
|
||||
)
|
||||
task_names: list[str] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Task names")
|
||||
creator_labels: list[str] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Allowed Creator Labels",
|
||||
description="Copy creator label from Publisher, regex supported."
|
||||
)
|
||||
|
||||
|
||||
class CreatorToolModel(BaseSettingsModel):
|
||||
# TODO this was dynamic dictionary '{name: task_names}'
|
||||
product_types_smart_select: list[ProductTypeSmartSelectModel] = (
|
||||
|
|
@ -48,6 +70,13 @@ class CreatorToolModel(BaseSettingsModel):
|
|||
title="Product name profiles"
|
||||
)
|
||||
|
||||
filter_creator_profiles: list[FilterCreatorProfile] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Filter creator profiles",
|
||||
description="Allowed list of creator labels that will be only shown if "
|
||||
"profile matches context."
|
||||
)
|
||||
|
||||
@validator("product_types_smart_select")
|
||||
def validate_unique_name(cls, value):
|
||||
ensure_unique_names(value)
|
||||
|
|
@ -420,7 +449,8 @@ DEFAULT_TOOLS_VALUES = {
|
|||
"tasks": [],
|
||||
"template": "SK_{folder[name]}{variant}"
|
||||
}
|
||||
]
|
||||
],
|
||||
"filter_creator_profiles": []
|
||||
},
|
||||
"Workfiles": {
|
||||
"workfile_template_profiles": [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue