Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publisher: filter creators based on task #560

Merged
merged 41 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ddd998f
AY-5539 - new Settings for filtering of creators
kalisp May 28, 2024
cd11db2
AY-5539 - use configured profiles to filter creators
kalisp May 28, 2024
2cf7f36
AY-5539 - do not use profiles for traypublisher
kalisp May 28, 2024
ce13e2e
AY-5539 - provide better method signature
kalisp May 28, 2024
170b1ab
Fix default factory
kalisp May 29, 2024
ea626e1
Fix formatting
kalisp May 29, 2024
34041b3
Fix formatting
kalisp May 29, 2024
5e95565
Fix formatting
kalisp May 29, 2024
1ac4223
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
kalisp May 29, 2024
e074268
Merge remote-tracking branch 'origin/enhancement/AY-5539_define-creat…
kalisp May 29, 2024
719e5aa
AY-5539 - remove explicit check for traypublisher
kalisp May 29, 2024
3c287e1
AY-5539 - added project settings to CreatorContext
kalisp May 29, 2024
cafb4c9
Use host_names in Settings
kalisp May 29, 2024
e899dd0
AY-5539 - changed value from Settings
kalisp May 29, 2024
2cdb980
Merge remote-tracking branch 'origin/enhancement/AY-5539_define-creat…
kalisp May 29, 2024
62f43bf
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
kalisp May 30, 2024
63a2e8f
AY-5539 - removed get_current_task_entity
kalisp May 30, 2024
4d812df
AY-5539 - reset project_setting when necessary
kalisp May 30, 2024
7b6f8d2
AY-5539 - use internal method for settings
kalisp May 30, 2024
739d459
CreateContext has methods to get folder & task entity and task type
iLLiCiTiT May 30, 2024
ec0327f
use new method in publish controller
iLLiCiTiT May 30, 2024
6e2cdf3
'_get_allowed_creator_identifiers' does not expect any arguments
iLLiCiTiT May 30, 2024
8eb1c89
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
kalisp May 30, 2024
b83f8b8
Merge remote-tracking branch 'origin/enhancement/AY-5539_define-creat…
kalisp May 30, 2024
31c2d7e
removed unused import
iLLiCiTiT May 30, 2024
3ffc19c
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
kalisp May 31, 2024
96c11e6
AY-5539 - used labels instead of identifiers
kalisp May 31, 2024
5a31435
AY-5539 - support regex in creator label
kalisp May 31, 2024
2794190
AY-5539 - added logging on profile match
kalisp May 31, 2024
0e4918d
Merge remote-tracking branch 'origin/enhancement/AY-5539_define-creat…
kalisp May 31, 2024
d2d05f6
Updated description
kalisp May 31, 2024
0fe6526
AY-5539 - possible speedup of resolution
kalisp May 31, 2024
0fa9041
AY-5539 - update resolution logic
kalisp Jun 3, 2024
c7f0e97
AY-5539 - refactor variable position
kalisp Jun 3, 2024
4e07b75
AY-5539 - fix wrong logic
kalisp Jun 3, 2024
577da3f
AY-5539 - protect from empty field in Settings
kalisp Jun 3, 2024
dd02631
AY-5539 - do only single re compile
kalisp Jun 3, 2024
cbc0516
AY-5539 - refactor argument name
kalisp Jun 6, 2024
909d6e7
AY-5539 - refactor name of method
kalisp Jun 6, 2024
4640f26
Merge branch 'develop' into enhancement/AY-5539_define-creators-per-task
kalisp Jun 7, 2024
e6fed33
Merge branch 'develop' into enhancement/AY-5539_define-creators-per-task
kalisp Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion client/ayon_core/pipeline/create/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

# Changes of instances and context are send as tuple of 2 information
UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"])
_NOT_SET = object()


class UnavailableSharedData(Exception):
Expand Down Expand Up @@ -1401,6 +1402,11 @@ def __init__(
self._current_folder_path = None
self._current_task_name = None
iLLiCiTiT marked this conversation as resolved.
Show resolved Hide resolved
self._current_workfile_path = None
self._current_project_settings = None
iLLiCiTiT marked this conversation as resolved.
Show resolved Hide resolved

self._current_folder_entity = _NOT_SET
self._current_task_entity = _NOT_SET
self._current_task_type = _NOT_SET

self._current_project_anatomy = None

Expand Down Expand Up @@ -1571,6 +1577,64 @@ def get_current_task_name(self):

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.

Expand All @@ -1592,6 +1656,12 @@ def get_current_project_anatomy(self):
self._current_project_name)
return self._current_project_anatomy

def get_current_project_settings(self):
kalisp marked this conversation as resolved.
Show resolved Hide resolved
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.
Expand Down Expand Up @@ -1718,7 +1788,12 @@ def reset_current_context(self):
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.
Expand Down Expand Up @@ -1772,7 +1847,7 @@ def _reset_publish_plugins(self, discover_publish_plugins):

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 = {}
Expand Down
70 changes: 70 additions & 0 deletions client/ayon_core/tools/publisher/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import shutil
import inspect
from abc import ABCMeta, abstractmethod
import re

import six
import arrow
Expand Down Expand Up @@ -39,6 +40,7 @@
)
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
Expand Down Expand Up @@ -1686,6 +1688,15 @@ def _publish_plugins(self):
"""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)
Expand Down Expand Up @@ -1827,8 +1838,13 @@ def _reset_plugins(self):
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(
Expand All @@ -1839,6 +1855,60 @@ def _collect_creator_items(self):

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"]
iLLiCiTiT marked this conversation as resolved.
Show resolved Hide resolved
)
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
)

kalisp marked this conversation as resolved.
Show resolved Hide resolved
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:
Expand Down
32 changes: 31 additions & 1 deletion server/settings/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ class ProductNameProfile(BaseSettingsModel):
template: str = SettingsField("", title="Template")


class FilterCreatorProfile(BaseSettingsModel):
kalisp marked this conversation as resolved.
Show resolved Hide resolved
"""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] = (
Expand All @@ -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)
Expand Down Expand Up @@ -420,7 +449,8 @@ class GlobalToolsModel(BaseSettingsModel):
"tasks": [],
"template": "SK_{folder[name]}{variant}"
}
]
],
"filter_creator_profiles": []
},
"Workfiles": {
"workfile_template_profiles": [
Expand Down