Merge pull request #3755 from pypeclub/feature/OP-3842_Change-publish-template-settings-location

General: Change publish template settings location
This commit is contained in:
Jakub Trllo 2022-09-12 11:26:00 +02:00 committed by GitHub
commit 31b4b3ffdc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 354 additions and 92 deletions

View file

@ -22,6 +22,8 @@ from .publish_plugins import (
)
from .lib import (
get_publish_template_name,
DiscoverResult,
publish_plugins_discover,
load_help_content_from_plugin,
@ -62,6 +64,8 @@ __all__ = (
"Extractor",
"get_publish_template_name",
"DiscoverResult",
"publish_plugins_discover",
"load_help_content_from_plugin",

View file

@ -0,0 +1,2 @@
DEFAULT_PUBLISH_TEMPLATE = "publish"
DEFAULT_HERO_PUBLISH_TEMPLATE = "hero"

View file

@ -2,6 +2,7 @@ import os
import sys
import types
import inspect
import copy
import tempfile
import xml.etree.ElementTree
@ -9,8 +10,190 @@ import six
import pyblish.plugin
import pyblish.api
from openpype.lib import Logger
from openpype.settings import get_project_settings, get_system_settings
from openpype.lib import Logger, filter_profiles
from openpype.settings import (
get_project_settings,
get_system_settings,
)
from .contants import (
DEFAULT_PUBLISH_TEMPLATE,
DEFAULT_HERO_PUBLISH_TEMPLATE,
)
def get_template_name_profiles(
project_name, project_settings=None, logger=None
):
"""Receive profiles for publish template keys.
At least one of arguments must be passed.
Args:
project_name (str): Name of project where to look for templates.
project_settings(Dic[str, Any]): Prepared project settings.
Returns:
List[Dict[str, Any]]: Publish template profiles.
"""
if not project_name and not project_settings:
raise ValueError((
"Both project name and project settings are missing."
" At least one must be entered."
))
if not project_settings:
project_settings = get_project_settings(project_name)
profiles = (
project_settings
["global"]
["tools"]
["publish"]
["template_name_profiles"]
)
if profiles:
return copy.deepcopy(profiles)
# Use legacy approach for cases new settings are not filled yet for the
# project
legacy_profiles = (
project_settings
["global"]
["publish"]
["IntegrateAssetNew"]
["template_name_profiles"]
)
if legacy_profiles:
if not logger:
logger = Logger.get_logger("get_template_name_profiles")
logger.warning((
"Project \"{}\" is using legacy access to publish template."
" It is recommended to move settings to new location"
" 'project_settings/global/tools/publish/template_name_profiles'."
).format(project_name))
# Replace "tasks" key with "task_names"
profiles = []
for profile in copy.deepcopy(legacy_profiles):
profile["task_names"] = profile.pop("tasks", [])
profiles.append(profile)
return profiles
def get_hero_template_name_profiles(
project_name, project_settings=None, logger=None
):
"""Receive profiles for hero publish template keys.
At least one of arguments must be passed.
Args:
project_name (str): Name of project where to look for templates.
project_settings(Dic[str, Any]): Prepared project settings.
Returns:
List[Dict[str, Any]]: Publish template profiles.
"""
if not project_name and not project_settings:
raise ValueError((
"Both project name and project settings are missing."
" At least one must be entered."
))
if not project_settings:
project_settings = get_project_settings(project_name)
profiles = (
project_settings
["global"]
["tools"]
["publish"]
["hero_template_name_profiles"]
)
if profiles:
return copy.deepcopy(profiles)
# Use legacy approach for cases new settings are not filled yet for the
# project
legacy_profiles = copy.deepcopy(
project_settings
["global"]
["publish"]
["IntegrateHeroVersion"]
["template_name_profiles"]
)
if legacy_profiles:
if not logger:
logger = Logger.get_logger("get_hero_template_name_profiles")
logger.warning((
"Project \"{}\" is using legacy access to hero publish template."
" It is recommended to move settings to new location"
" 'project_settings/global/tools/publish/"
"hero_template_name_profiles'."
).format(project_name))
return legacy_profiles
def get_publish_template_name(
project_name,
host_name,
family,
task_name,
task_type,
project_settings=None,
hero=False,
logger=None
):
"""Get template name which should be used for passed context.
Publish templates are filtered by host name, family, task name and
task type.
Default template which is used at if profiles are not available or profile
has empty value is defined by 'DEFAULT_PUBLISH_TEMPLATE' constant.
Args:
project_name (str): Name of project where to look for settings.
host_name (str): Name of host integration.
family (str): Family for which should be found template.
task_name (str): Task name on which is intance working.
task_type (str): Task type on which is intance working.
project_setting (Dict[str, Any]): Prepared project settings.
logger (logging.Logger): Custom logger used for 'filter_profiles'
function.
Returns:
str: Template name which should be used for integration.
"""
template = None
filter_criteria = {
"hosts": host_name,
"families": family,
"task_names": task_name,
"task_types": task_type,
}
if hero:
default_template = DEFAULT_HERO_PUBLISH_TEMPLATE
profiles = get_hero_template_name_profiles(
project_name, project_settings, logger
)
else:
profiles = get_template_name_profiles(
project_name, project_settings, logger
)
default_template = DEFAULT_PUBLISH_TEMPLATE
profile = filter_profiles(profiles, filter_criteria, logger=logger)
if profile:
template = profile["template_name"]
return template or default_template
class DiscoverResult:

View file

@ -5,6 +5,9 @@ import copy
import clique
import six
from bson.objectid import ObjectId
import pyblish.api
from openpype.client.operations import (
OperationsSession,
new_subset_document,
@ -14,8 +17,6 @@ from openpype.client.operations import (
prepare_version_update_data,
prepare_representation_update_data,
)
from bson.objectid import ObjectId
import pyblish.api
from openpype.client import (
get_representations,
@ -23,10 +24,12 @@ from openpype.client import (
get_version_by_name,
)
from openpype.lib import source_hash
from openpype.lib.profiles_filtering import filter_profiles
from openpype.lib.file_transaction import FileTransaction
from openpype.pipeline import legacy_io
from openpype.pipeline.publish import KnownPublishError
from openpype.pipeline.publish import (
KnownPublishError,
get_publish_template_name,
)
log = logging.getLogger(__name__)
@ -792,52 +795,26 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
def get_template_name(self, instance):
"""Return anatomy template name to use for integration"""
# Define publish template name from profiles
filter_criteria = self.get_profile_filter_criteria(instance)
template_name_profiles = self._get_template_name_profiles(instance)
profile = filter_profiles(
template_name_profiles,
filter_criteria,
logger=self.log
)
if profile:
return profile["template_name"]
return self.default_template_name
def _get_template_name_profiles(self, instance):
"""Receive profiles for publish template keys.
Reuse template name profiles from legacy integrator. Goal is to move
the profile settings out of plugin settings but until that happens we
want to be able set it at one place and don't break backwards
compatibility (more then once).
"""
return (
instance.context.data["project_settings"]
["global"]
["publish"]
["IntegrateAssetNew"]
["template_name_profiles"]
)
def get_profile_filter_criteria(self, instance):
"""Return filter criteria for `filter_profiles`"""
# Anatomy data is pre-filled by Collectors
anatomy_data = instance.data["anatomyData"]
project_name = legacy_io.active_project()
# Task can be optional in anatomy data
task = anatomy_data.get("task", {})
host_name = instance.context.data["hostName"]
anatomy_data = instance.data["anatomyData"]
family = anatomy_data["family"]
task_info = anatomy_data.get("task") or {}
# Return filter criteria
return {
"families": anatomy_data["family"],
"tasks": task.get("name"),
"task_types": task.get("type"),
"hosts": instance.context.data["hostName"],
}
return get_publish_template_name(
project_name,
host_name,
family,
task_name=task_info.get("name"),
task_type=task_info.get("type"),
project_settings=instance.context.data["project_settings"],
logger=self.log
)
def get_rootless_path(self, anatomy, path):
"""Returns, if possible, path without absolute portion from root

View file

@ -14,14 +14,12 @@ from openpype.client import (
get_archived_representations,
get_representations,
)
from openpype.lib import (
create_hard_link,
filter_profiles
)
from openpype.lib import create_hard_link
from openpype.pipeline import (
schema,
legacy_io,
)
from openpype.pipeline.publish import get_publish_template_name
class IntegrateHeroVersion(pyblish.api.InstancePlugin):
@ -68,10 +66,11 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
)
return
template_key = self._get_template_key(instance)
anatomy = instance.context.data["anatomy"]
project_name = anatomy.project_name
template_key = self._get_template_key(project_name, instance)
if template_key not in anatomy.templates:
self.log.warning((
"!!! Anatomy of project \"{}\" does not have set"
@ -527,30 +526,24 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin):
return publish_folder
def _get_template_key(self, instance):
def _get_template_key(self, project_name, instance):
anatomy_data = instance.data["anatomyData"]
task_data = anatomy_data.get("task") or {}
task_name = task_data.get("name")
task_type = task_data.get("type")
task_info = anatomy_data.get("task") or {}
host_name = instance.context.data["hostName"]
# TODO raise error if Hero not set?
family = self.main_family_from_instance(instance)
key_values = {
"families": family,
"task_names": task_name,
"task_types": task_type,
"hosts": host_name
}
profile = filter_profiles(
self.template_name_profiles,
key_values,
return get_publish_template_name(
project_name,
host_name,
family,
task_info.get("name"),
task_info.get("type"),
project_settings=instance.context.data["project_settings"],
hero=True,
logger=self.log
)
if profile:
template_name = profile["template_name"]
else:
template_name = self._default_template_name
return template_name
def main_family_from_instance(self, instance):
"""Returns main family of entered instance."""

View file

@ -15,7 +15,6 @@ from bson.objectid import ObjectId
from pymongo import DeleteOne, InsertOne
import pyblish.api
import openpype.api
from openpype.client import (
get_asset_by_name,
get_subset_by_id,
@ -25,14 +24,17 @@ from openpype.client import (
get_representations,
get_archived_representations,
)
from openpype.lib.profiles_filtering import filter_profiles
from openpype.lib import (
prepare_template_data,
create_hard_link,
StringTemplate,
TemplateUnsolved
TemplateUnsolved,
source_hash,
filter_profiles,
get_local_site_id,
)
from openpype.pipeline import legacy_io
from openpype.pipeline.publish import get_publish_template_name
# this is needed until speedcopy for linux is fixed
if sys.platform == "win32":
@ -138,7 +140,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
integrated_file_sizes = {}
# Attributes set by settings
template_name_profiles = None
subset_grouping_profiles = None
def process(self, instance):
@ -388,22 +389,16 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
family = self.main_family_from_instance(instance)
key_values = {
"families": family,
"tasks": task_name,
"hosts": instance.context.data["hostName"],
"task_types": task_type
}
profile = filter_profiles(
self.template_name_profiles,
key_values,
template_name = get_publish_template_name(
project_name,
instance.context.data["hostName"],
family,
task_name=task_info.get("name"),
task_type=task_info.get("type"),
project_settings=instance.context.data["project_settings"],
logger=self.log
)
template_name = "publish"
if profile:
template_name = profile["template_name"]
published_representations = {}
for idx, repre in enumerate(repres):
published_files = []
@ -1058,7 +1053,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
for _src, dest in resources:
path = self.get_rootless_path(anatomy, dest)
dest = self.get_dest_temp_url(dest)
file_hash = openpype.api.source_hash(dest)
file_hash = source_hash(dest)
if self.TMP_FILE_EXT and \
',{}'.format(self.TMP_FILE_EXT) in file_hash:
file_hash = file_hash.replace(',{}'.format(self.TMP_FILE_EXT),
@ -1168,7 +1163,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
def _get_sites(self, sync_project_presets):
"""Returns tuple (local_site, remote_site)"""
local_site_id = openpype.api.get_local_site_id()
local_site_id = get_local_site_id()
local_site = sync_project_presets["config"]. \
get("active_site", "studio").strip()

View file

@ -418,6 +418,10 @@
"filter_families": []
}
]
},
"publish": {
"template_name_profiles": [],
"hero_template_name_profiles": []
}
},
"project_folder_structure": "{\"__project_root__\": {\"prod\": {}, \"resources\": {\"footage\": {\"plates\": {}, \"offline\": {}}, \"audio\": {}, \"art_dept\": {}}, \"editorial\": {}, \"assets\": {\"characters\": {}, \"locations\": {}}, \"shots\": {}}}",

View file

@ -663,10 +663,14 @@
]
}
},
{
"type": "label",
"label": "<b>NOTE:</b> Publish template profiles settings were moved to <a href=\"settings://project_settings/global/tools/publish/template_name_profiles\"><b>Tools/Publish/Template name profiles</b></a>. Please move values there."
},
{
"type": "list",
"key": "template_name_profiles",
"label": "Template name profiles",
"label": "Template name profiles (DEPRECATED)",
"use_label_wrap": true,
"object_type": {
"type": "dict",
@ -771,10 +775,14 @@
"type": "list",
"object_type": "text"
},
{
"type": "label",
"label": "<b>NOTE:</b> Hero publish template profiles settings were moved to <a href=\"settings://project_settings/global/tools/publish/hero_template_name_profiles\"><b>Tools/Publish/Hero template name profiles</b></a>. Please move values there."
},
{
"type": "list",
"key": "template_name_profiles",
"label": "Template name profiles",
"label": "Template name profiles (DEPRECATED)",
"use_label_wrap": true,
"object_type": {
"type": "dict",

View file

@ -284,6 +284,102 @@
}
}
]
},
{
"type": "dict",
"key": "publish",
"label": "Publish",
"children": [
{
"type": "label",
"label": "<b>NOTE:</b> For backwards compatibility can be value empty and in that case are used values from <a href=\"settings://project_settings/global/publish/IntegrateAssetNew\"><b>IntegrateAssetNew</b></a>. This will change in future so please move all values here as soon as possible."
},
{
"type": "list",
"key": "template_name_profiles",
"label": "Template name profiles",
"use_label_wrap": true,
"object_type": {
"type": "dict",
"children": [
{
"key": "families",
"label": "Families",
"type": "list",
"object_type": "text"
},
{
"type": "hosts-enum",
"key": "hosts",
"label": "Hosts",
"multiselection": true
},
{
"key": "task_types",
"label": "Task types",
"type": "task-types-enum"
},
{
"key": "task_names",
"label": "Task names",
"type": "list",
"object_type": "text"
},
{
"type": "separator"
},
{
"type": "text",
"key": "template_name",
"label": "Template name"
}
]
}
},
{
"type": "list",
"key": "hero_template_name_profiles",
"label": "Hero template name profiles",
"use_label_wrap": true,
"object_type": {
"type": "dict",
"children": [
{
"key": "families",
"label": "Families",
"type": "list",
"object_type": "text"
},
{
"type": "hosts-enum",
"key": "hosts",
"label": "Hosts",
"multiselection": true
},
{
"key": "task_types",
"label": "Task types",
"type": "task-types-enum"
},
{
"key": "task_names",
"label": "Task names",
"type": "list",
"object_type": "text"
},
{
"type": "separator"
},
{
"type": "text",
"key": "template_name",
"label": "Template name",
"tooltip": "Name of template from Anatomy templates"
}
]
}
}
]
}
]
}