Merge pull request #3723 from pypeclub/feature/OP-3819_Move-subset-name-functionality

Genetal: Move subset name functionality
This commit is contained in:
Jakub Trllo 2022-08-26 15:00:09 +02:00 committed by GitHub
commit 52fdba85da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 230 additions and 116 deletions

View file

@ -1,8 +1,8 @@
import os
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline import legacy_io
from openpype.pipeline.create import get_subset_name
class CollectWorkfile(pyblish.api.ContextPlugin):
@ -71,13 +71,14 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
# workfile instance
family = "workfile"
subset = get_subset_name_with_asset_doc(
subset = get_subset_name(
family,
self.default_variant,
context.data["anatomyData"]["task"]["name"],
context.data["assetEntity"],
context.data["anatomyData"]["project"]["name"],
host_name=context.data["hostName"]
host_name=context.data["hostName"],
project_settings=context.data["project_settings"]
)
# Create instance
instance = context.create_instance(subset)

View file

@ -1,9 +1,9 @@
import pyblish.api
import openpype.lib as oplib
from openpype.pipeline import legacy_io
import openpype.hosts.flame.api as opfapi
from openpype.hosts.flame.otio import flame_export
from openpype.pipeline import legacy_io
from openpype.pipeline.create import get_subset_name
class CollecTimelineOTIO(pyblish.api.ContextPlugin):
@ -24,11 +24,14 @@ class CollecTimelineOTIO(pyblish.api.ContextPlugin):
sequence = opfapi.get_current_sequence(opfapi.CTX.selection)
# create subset name
subset_name = oplib.get_subset_name_with_asset_doc(
subset_name = get_subset_name(
family,
variant,
task_name,
asset_doc,
context.data["projectName"],
context.data["hostName"],
project_settings=context.data["project_settings"]
)
# adding otio timeline to context

View file

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
"""Collect current workfile from Harmony."""
import pyblish.api
import os
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
class CollectWorkfile(pyblish.api.ContextPlugin):
@ -17,13 +17,14 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
"""Plugin entry point."""
family = "workfile"
basename = os.path.basename(context.data["currentFile"])
subset = get_subset_name_with_asset_doc(
subset = get_subset_name(
family,
"",
context.data["anatomyData"]["task"]["name"],
context.data["assetEntity"],
context.data["anatomyData"]["project"]["name"],
host_name=context.data["hostName"]
host_name=context.data["hostName"],
project_settings=context.data["project_settings"]
)
# Create instance

View file

@ -10,7 +10,7 @@ import os
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
class CollectReview(pyblish.api.ContextPlugin):
@ -27,13 +27,14 @@ class CollectReview(pyblish.api.ContextPlugin):
def process(self, context):
family = "review"
subset = get_subset_name_with_asset_doc(
subset = get_subset_name(
family,
context.data.get("variant", ''),
context.data["anatomyData"]["task"]["name"],
context.data["assetEntity"],
context.data["anatomyData"]["project"]["name"],
host_name=context.data["hostName"]
host_name=context.data["hostName"],
project_settings=context.data["project_settings"]
)
instance = context.create_instance(subset)

View file

@ -1,7 +1,7 @@
import os
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
class CollectWorkfile(pyblish.api.ContextPlugin):
@ -24,13 +24,14 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
family = "workfile"
# context.data["variant"] might come only from collect_batch_data
variant = context.data.get("variant") or self.default_variant
subset = get_subset_name_with_asset_doc(
subset = get_subset_name(
family,
variant,
context.data["anatomyData"]["task"]["name"],
context.data["assetEntity"],
context.data["anatomyData"]["project"]["name"],
host_name=context.data["hostName"]
host_name=context.data["hostName"],
project_settings=context.data["project_settings"]
)
file_path = context.data["currentFile"]

View file

@ -2,8 +2,8 @@ import copy
import json
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.client import get_asset_by_name
from openpype.pipeline.create import get_subset_name
class CollectBulkMovInstances(pyblish.api.InstancePlugin):
@ -44,12 +44,14 @@ class CollectBulkMovInstances(pyblish.api.InstancePlugin):
task_name = available_task_names[_task_name_low]
break
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
self.new_instance_family,
self.subset_name_variant,
task_name,
asset_doc,
project_name
project_name,
host_name=context.data["hostName"],
project_settings=context.data["project_settings"]
)
instance_name = f"{asset_name}_{subset_name}"

View file

@ -6,13 +6,15 @@ from openpype.client import get_assets, get_asset_by_name
from openpype.lib import (
FileDef,
BoolDef,
get_subset_name_with_asset_doc,
TaskNotSetError,
)
from openpype.pipeline import (
CreatedInstance,
CreatorError
)
from openpype.pipeline.create import (
get_subset_name,
TaskNotSetError,
)
from openpype.hosts.traypublisher.api.plugin import TrayPublishCreator
@ -130,7 +132,7 @@ class BatchMovieCreator(TrayPublishCreator):
task_name = self._get_task_name(asset_doc)
try:
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
self.family,
variant,
task_name,
@ -143,7 +145,7 @@ class BatchMovieCreator(TrayPublishCreator):
# but user have ability to change it
# NOTE: This expect that there is not task 'Undefined' on asset
task_name = "Undefined"
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
self.family,
variant,
task_name,

View file

@ -3,8 +3,8 @@ import copy
import pyblish.api
from openpype.client import get_asset_by_name
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline import legacy_io
from openpype.pipeline.create import get_subset_name
class CollectInstances(pyblish.api.ContextPlugin):
@ -107,13 +107,14 @@ class CollectInstances(pyblish.api.ContextPlugin):
# Use empty variant value
variant = ""
task_name = legacy_io.Session["AVALON_TASK"]
new_subset_name = get_subset_name_with_asset_doc(
new_subset_name = get_subset_name(
family,
variant,
task_name,
asset_doc,
project_name,
host_name
host_name,
project_settings=context.data["project_settings"]
)
instance_data["subset"] = new_subset_name

View file

@ -3,7 +3,7 @@ import copy
import pyblish.api
from openpype.client import get_asset_by_name
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
class CollectRenderScene(pyblish.api.ContextPlugin):
@ -75,14 +75,15 @@ class CollectRenderScene(pyblish.api.ContextPlugin):
dynamic_data["render_pass"] = dynamic_data["renderpass"]
task_name = workfile_context["task"]
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
"render",
variant,
task_name,
asset_doc,
project_name,
host_name,
dynamic_data=dynamic_data
dynamic_data=dynamic_data,
project_settings=context.data["project_settings"]
)
instance_data = {

View file

@ -3,8 +3,8 @@ import json
import pyblish.api
from openpype.client import get_asset_by_name
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline import legacy_io
from openpype.pipeline.create import get_subset_name
class CollectWorkfile(pyblish.api.ContextPlugin):
@ -39,13 +39,14 @@ class CollectWorkfile(pyblish.api.ContextPlugin):
# Use empty variant value
variant = ""
task_name = legacy_io.Session["AVALON_TASK"]
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
family,
variant,
task_name,
asset_doc,
project_name,
host_name
host_name,
project_settings=context.data["project_settings"]
)
# Create Workfile instance

View file

@ -23,7 +23,7 @@ from openpype.lib import (
get_ffprobe_streams,
convert_ffprobe_fps_value,
)
from openpype.lib.plugin_tools import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
from openpype_modules.webpublisher.lib import parse_json
@ -78,9 +78,14 @@ class CollectPublishedFiles(pyblish.api.ContextPlugin):
is_sequence,
extension.replace(".", ''))
subset_name = get_subset_name_with_asset_doc(
family, variant, task_name, asset_doc,
project_name=project_name, host_name="webpublisher"
subset_name = get_subset_name(
family,
variant,
task_name,
asset_doc,
project_name=project_name,
host_name="webpublisher",
project_settings=context.data["project_settings"]
)
version = self._get_next_version(
project_name, asset_doc, subset_name

View file

@ -10,7 +10,7 @@ import re
import copy
import pyblish.api
from openpype.lib import get_subset_name_with_asset_doc
from openpype.pipeline.create import get_subset_name
class CollectTVPaintInstances(pyblish.api.ContextPlugin):
@ -47,13 +47,14 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
new_instances = []
# Workfile instance
workfile_subset_name = get_subset_name_with_asset_doc(
workfile_subset_name = get_subset_name(
self.workfile_family,
self.workfile_variant,
task_name,
asset_doc,
project_name,
host_name
host_name,
project_settings=context.data["project_settings"]
)
workfile_instance = self._create_workfile_instance(
context, workfile_subset_name
@ -61,13 +62,14 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
new_instances.append(workfile_instance)
# Review instance
review_subset_name = get_subset_name_with_asset_doc(
review_subset_name = get_subset_name(
self.review_family,
self.review_variant,
task_name,
asset_doc,
project_name,
host_name
host_name,
project_settings=context.data["project_settings"]
)
review_instance = self._create_review_instance(
context, review_subset_name
@ -114,14 +116,15 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
"family": "render"
}
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
self.render_pass_family,
render_pass,
task_name,
asset_doc,
project_name,
host_name,
dynamic_data=dynamic_data
dynamic_data=dynamic_data,
project_settings=context.data["project_settings"]
)
instance = self._create_render_pass_instance(
@ -137,14 +140,15 @@ class CollectTVPaintInstances(pyblish.api.ContextPlugin):
# Override family for subset name
"family": "render"
}
subset_name = get_subset_name_with_asset_doc(
subset_name = get_subset_name(
self.render_layer_family,
variant,
task_name,
asset_doc,
project_name,
host_name,
dynamic_data=dynamic_data
dynamic_data=dynamic_data,
project_settings=context.data["project_settings"]
)
instance = self._create_render_layer_instance(
context, layers, subset_name

View file

@ -11,13 +11,8 @@ import functools
from openpype.client import get_asset_by_id
from openpype.settings import get_project_settings
from .profiles_filtering import filter_profiles
log = logging.getLogger(__name__)
# Subset name template used when plugin does not have defined any
DEFAULT_SUBSET_TEMPLATE = "{family}{Variant}"
class PluginToolsDeprecatedWarning(DeprecationWarning):
pass
@ -64,13 +59,14 @@ def deprecated(new_destination):
return _decorator(func)
class TaskNotSetError(KeyError):
def __init__(self, msg=None):
if not msg:
msg = "Creator's subset name template requires task name."
super(TaskNotSetError, self).__init__(msg)
@deprecated("openpype.pipeline.create.TaskNotSetError")
def TaskNotSetError(*args, **kwargs):
from openpype.pipeline.create import TaskNotSetError
return TaskNotSetError(*args, **kwargs)
@deprecated("openpype.pipeline.create.get_subset_name")
def get_subset_name_with_asset_doc(
family,
variant,
@ -109,61 +105,22 @@ def get_subset_name_with_asset_doc(
dbcon (AvalonMongoDB): Mongo connection to be able query asset document
if 'asset_doc' is not passed.
"""
if not family:
return ""
if not host_name:
host_name = os.environ["AVALON_APP"]
from openpype.pipeline.create import get_subset_name
# Use only last part of class family value split by dot (`.`)
family = family.rsplit(".", 1)[-1]
if project_name is None:
from openpype.pipeline import legacy_io
project_name = legacy_io.Session["AVALON_PROJECT"]
asset_tasks = asset_doc.get("data", {}).get("tasks") or {}
task_info = asset_tasks.get(task_name) or {}
task_type = task_info.get("type")
# Get settings
tools_settings = get_project_settings(project_name)["global"]["tools"]
profiles = tools_settings["creator"]["subset_name_profiles"]
filtering_criteria = {
"families": family,
"hosts": host_name,
"tasks": task_name,
"task_types": task_type
}
matching_profile = filter_profiles(profiles, filtering_criteria)
template = None
if matching_profile:
template = matching_profile["template"]
# Make sure template is set (matching may have empty string)
if not template:
template = default_template or DEFAULT_SUBSET_TEMPLATE
# Simple check of task name existence for template with {task} in
# - missing task should be possible only in Standalone publisher
if not task_name and "{task" in template.lower():
raise TaskNotSetError()
fill_pairs = {
"variant": variant,
"family": family,
"task": task_name
}
if dynamic_data:
# Dynamic data may override default values
for key, value in dynamic_data.items():
fill_pairs[key] = value
return template.format(**prepare_template_data(fill_pairs))
return get_subset_name(
family,
variant,
task_name,
asset_doc,
project_name,
host_name,
default_template,
dynamic_data
)
@deprecated
def get_subset_name(
family,
variant,
@ -183,16 +140,18 @@ def get_subset_name(
`get_subset_name_with_asset_doc` where asset document is expected.
"""
from openpype.pipeline.create import get_subset_name
if project_name is None:
project_name = dbcon.project_name
asset_doc = get_asset_by_id(project_name, asset_id, fields=["data.tasks"])
return get_subset_name_with_asset_doc(
return get_subset_name(
family,
variant,
task_name,
asset_doc or {},
asset_doc,
project_name,
host_name,
default_template,
@ -254,6 +213,9 @@ def filter_pyblish_plugins(plugins):
Args:
plugins (dict): Dictionary of plugins produced by :mod:`pyblish-base`
`discover()` method.
Deprecated:
Function will be removed after release version 3.15.*
"""
from openpype.pipeline.publish.lib import filter_pyblish_plugins
@ -277,6 +239,9 @@ def set_plugin_attributes_from_settings(
Value from environment `AVALON_APP` is used if not entered.
project_name (str): Name of project for which settings will be loaded.
Value from environment `AVALON_PROJECT` is used if not entered.
Deprecated:
Function will be removed after release version 3.15.*
"""
# Function is not used anymore

View file

@ -1,6 +1,13 @@
from .constants import (
SUBSET_NAME_ALLOWED_SYMBOLS
SUBSET_NAME_ALLOWED_SYMBOLS,
DEFAULT_SUBSET_TEMPLATE,
)
from .subset_name import (
TaskNotSetError,
get_subset_name,
)
from .creator_plugins import (
CreatorError,
@ -32,6 +39,10 @@ from .legacy_create import (
__all__ = (
"SUBSET_NAME_ALLOWED_SYMBOLS",
"DEFAULT_SUBSET_TEMPLATE",
"TaskNotSetError",
"get_subset_name",
"CreatorError",

View file

@ -1,6 +1,8 @@
SUBSET_NAME_ALLOWED_SYMBOLS = "a-zA-Z0-9_."
DEFAULT_SUBSET_TEMPLATE = "{family}{Variant}"
__all__ = (
"SUBSET_NAME_ALLOWED_SYMBOLS",
"DEFAULT_SUBSET_TEMPLATE",
)

View file

@ -0,0 +1,109 @@
import os
from openpype.settings import get_project_settings
from openpype.lib import filter_profiles, prepare_template_data
from openpype.pipeline import legacy_io
from .constants import DEFAULT_SUBSET_TEMPLATE
class TaskNotSetError(KeyError):
def __init__(self, msg=None):
if not msg:
msg = "Creator's subset name template requires task name."
super(TaskNotSetError, self).__init__(msg)
def get_subset_name(
family,
variant,
task_name,
asset_doc,
project_name=None,
host_name=None,
default_template=None,
dynamic_data=None,
project_settings=None
):
"""Calculate subset name based on passed context and OpenPype settings.
Subst name templates are defined in `project_settings/global/tools/creator
/subset_name_profiles` where are profiles with host name, family, task name
and task type filters. If context does not match any profile then
`DEFAULT_SUBSET_TEMPLATE` is used as default template.
That's main reason why so many arguments are required to calculate subset
name.
Args:
family (str): Instance family.
variant (str): In most of cases it is user input during creation.
task_name (str): Task name on which context is instance created.
asset_doc (dict): Queried asset document with it's tasks in data.
Used to get task type.
project_name (str): Name of project on which is instance created.
Important for project settings that are loaded.
host_name (str): One of filtering criteria for template profile
filters.
default_template (str): Default template if any profile does not match
passed context. Constant 'DEFAULT_SUBSET_TEMPLATE' is used if
is not passed.
dynamic_data (dict): Dynamic data specific for a creator which creates
instance.
dbcon (AvalonMongoDB): Mongo connection to be able query asset document
if 'asset_doc' is not passed.
"""
if not family:
return ""
if not host_name:
host_name = os.environ["AVALON_APP"]
# Use only last part of class family value split by dot (`.`)
family = family.rsplit(".", 1)[-1]
if project_name is None:
project_name = legacy_io.Session["AVALON_PROJECT"]
asset_tasks = asset_doc.get("data", {}).get("tasks") or {}
task_info = asset_tasks.get(task_name) or {}
task_type = task_info.get("type")
# Get settings
if not project_settings:
project_settings = get_project_settings(project_name)
tools_settings = project_settings["global"]["tools"]
profiles = tools_settings["creator"]["subset_name_profiles"]
filtering_criteria = {
"families": family,
"hosts": host_name,
"tasks": task_name,
"task_types": task_type
}
matching_profile = filter_profiles(profiles, filtering_criteria)
template = None
if matching_profile:
template = matching_profile["template"]
# Make sure template is set (matching may have empty string)
if not template:
template = default_template or DEFAULT_SUBSET_TEMPLATE
# Simple check of task name existence for template with {task} in
# - missing task should be possible only in Standalone publisher
if not task_name and "{task" in template.lower():
raise TaskNotSetError()
fill_pairs = {
"variant": variant,
"family": family,
"task": task_name
}
if dynamic_data:
# Dynamic data may override default values
for key, value in dynamic_data.items():
fill_pairs[key] = value
return template.format(**prepare_template_data(fill_pairs))

View file

@ -11,10 +11,10 @@ except Exception:
from Qt import QtWidgets, QtCore, QtGui
from openpype.client import get_asset_by_name, get_subsets
from openpype.lib import TaskNotSetError
from openpype.pipeline.create import (
CreatorError,
SUBSET_NAME_ALLOWED_SYMBOLS
SUBSET_NAME_ALLOWED_SYMBOLS,
TaskNotSetError,
)
from openpype.tools.utils import (
ErrorMessageBox,

View file

@ -6,7 +6,6 @@ import collections
from Qt import QtWidgets, QtCore, QtGui
import qtawesome
from openpype.lib import TaskNotSetError
from openpype.widgets.attribute_defs import create_widget_for_attr_def
from openpype.tools import resources
from openpype.tools.flickcharm import FlickCharm
@ -17,7 +16,10 @@ from openpype.tools.utils import (
BaseClickableFrame,
set_style_property,
)
from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS
from openpype.pipeline.create import (
SUBSET_NAME_ALLOWED_SYMBOLS,
TaskNotSetError,
)
from .assets_widget import AssetsDialog
from .tasks_widget import TasksModel
from .icons import (

View file

@ -8,10 +8,12 @@ from openpype.client import (
get_subsets,
get_last_version_by_subset_id,
)
from openpype.api import get_project_settings
from openpype.settings import get_project_settings
from openpype.pipeline import LegacyCreator
from openpype.lib import TaskNotSetError
from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS
from openpype.pipeline.create import (
SUBSET_NAME_ALLOWED_SYMBOLS,
TaskNotSetError,
)
from . import HelpRole, FamilyRole, ExistsRole, PluginRole, PluginKeyRole
from . import FamilyDescriptionWidget