From 4379dc019e4069ca44240aec565c1d136879f1a8 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 27 Jul 2022 18:05:32 +0200 Subject: [PATCH 1/8] OP-3283 - implemented proper usage of {layer} in subset template for legacy creator {layer} placeholder could be used in project_settings/global/tools/creator/subset_name_profiles to drive lower/upper cases when layer is used in subset name (eg. when multiple subsets are created at once). Warning {layer} means keep layer name as it is, not lowercasing! --- .../plugins/create/create_legacy_image.py | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index 9736471a267..142cddfd52a 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -1,6 +1,11 @@ from Qt import QtWidgets from openpype.pipeline import create from openpype.hosts.photoshop import api as photoshop +from openpype.pipeline import legacy_io +from openpype.client import get_asset_by_name +from openpype.settings import get_project_settings +from openpype.lib import prepare_template_data +from openpype.lib.profiles_filtering import filter_profiles class CreateImage(create.LegacyCreator): @@ -82,7 +87,18 @@ def process(self): subset_name = creator_subset_name if len(groups) > 1: - subset_name += group.name.title().replace(" ", "") + subset_template = self._get_subset_template(self.family) + if not subset_template or 'layer' not in subset_template.lower(): + subset_name += group.name.title().replace(" ", "") + else: + fill_pairs = { + "variant": self.data["variant"], + "family": self.family, + "task": legacy_io.Session["AVALON_TASK"], + "layer": group.name + } + + subset_name = subset_template.format(**prepare_template_data(fill_pairs)) if group.long_name: for directory in group.long_name[::-1]: @@ -98,3 +114,34 @@ def process(self): # reusing existing group, need to rename afterwards if not create_group: stub.rename_layer(group.id, stub.PUBLISH_ICON + group.name) + + @classmethod + def get_dynamic_data( + cls, variant, task_name, asset_id, project_name, host_name + ): + return {"layer": ""} + + def _get_subset_template(self, family): + project_name = legacy_io.Session["AVALON_PROJECT"] + asset_name = legacy_io.Session["AVALON_ASSET"] + task_name = legacy_io.Session["AVALON_TASK"] + + asset_doc = get_asset_by_name( + project_name, asset_name, fields=["data.tasks"] + ) + asset_tasks = asset_doc.get("data", {}).get("tasks") or {} + task_info = asset_tasks.get(task_name) or {} + task_type = task_info.get("type") + + tools_settings = get_project_settings(project_name)["global"]["tools"] + profiles = tools_settings["creator"]["subset_name_profiles"] + filtering_criteria = { + "families": family, + "hosts": "photoshop", + "tasks": task_name, + "task_types": task_type + } + + matching_profile = filter_profiles(profiles, filtering_criteria) + if matching_profile: + return matching_profile["template"] From 8c95aab796ec3cc284851b2d1c3170ead24a22b7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 28 Jul 2022 12:41:49 +0200 Subject: [PATCH 2/8] OP-3283 - extracted logic to plugin to reuse --- openpype/hosts/photoshop/api/plugin.py | 53 +++++++++++++++++++ .../plugins/create/create_legacy_image.py | 50 +++-------------- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/openpype/hosts/photoshop/api/plugin.py b/openpype/hosts/photoshop/api/plugin.py index c80e6bbd063..ecbfbf91e3f 100644 --- a/openpype/hosts/photoshop/api/plugin.py +++ b/openpype/hosts/photoshop/api/plugin.py @@ -2,6 +2,11 @@ from openpype.pipeline import LoaderPlugin from .launch_logic import stub +from openpype.pipeline import legacy_io +from openpype.client import get_asset_by_name +from openpype.settings import get_project_settings +from openpype.lib import prepare_template_data +from openpype.lib.profiles_filtering import filter_profiles def get_unique_layer_name(layers, asset_name, subset_name): @@ -33,3 +38,51 @@ class PhotoshopLoader(LoaderPlugin): @staticmethod def get_stub(): return stub() + + +def get_subset_template(family): + """Get subset template name from Settings""" + project_name = legacy_io.Session["AVALON_PROJECT"] + asset_name = legacy_io.Session["AVALON_ASSET"] + task_name = legacy_io.Session["AVALON_TASK"] + + asset_doc = get_asset_by_name( + project_name, asset_name, fields=["data.tasks"] + ) + asset_tasks = asset_doc.get("data", {}).get("tasks") or {} + task_info = asset_tasks.get(task_name) or {} + task_type = task_info.get("type") + + tools_settings = get_project_settings(project_name)["global"]["tools"] + profiles = tools_settings["creator"]["subset_name_profiles"] + filtering_criteria = { + "families": family, + "hosts": "photoshop", + "tasks": task_name, + "task_types": task_type + } + + matching_profile = filter_profiles(profiles, filtering_criteria) + if matching_profile: + return matching_profile["template"] + + +def get_subset_name_for_multiple(subset_name, subset_template, group, + family, variant): + """Update subset name with layer information to differentiate multiple + + subset_template might contain specific way how to format layer name + ({layer},{Layer} or {LAYER}). If subset_template doesn't contain placeholder + at all, fall back to original solution. + """ + if not subset_template or 'layer' not in subset_template.lower(): + subset_name += group.name.title().replace(" ", "") + else: + fill_pairs = { + "family": family, + "variant": variant, + "task": legacy_io.Session["AVALON_TASK"], + "layer": group.name + } + + return subset_template.format(**prepare_template_data(fill_pairs)) diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index 142cddfd52a..6d0587c20c9 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -1,11 +1,8 @@ from Qt import QtWidgets from openpype.pipeline import create from openpype.hosts.photoshop import api as photoshop -from openpype.pipeline import legacy_io -from openpype.client import get_asset_by_name -from openpype.settings import get_project_settings -from openpype.lib import prepare_template_data -from openpype.lib.profiles_filtering import filter_profiles + +from openpype.hosts.photoshop.api.plugin import get_subset_template, get_subset_name_for_multiple class CreateImage(create.LegacyCreator): @@ -87,18 +84,12 @@ def process(self): subset_name = creator_subset_name if len(groups) > 1: - subset_template = self._get_subset_template(self.family) - if not subset_template or 'layer' not in subset_template.lower(): - subset_name += group.name.title().replace(" ", "") - else: - fill_pairs = { - "variant": self.data["variant"], - "family": self.family, - "task": legacy_io.Session["AVALON_TASK"], - "layer": group.name - } - - subset_name = subset_template.format(**prepare_template_data(fill_pairs)) + subset_template = get_subset_template(self.family) + subset_name = get_subset_name_for_multiple(subset_name, + subset_template, + group, + self.family, + self.data["variant"]) if group.long_name: for directory in group.long_name[::-1]: @@ -120,28 +111,3 @@ def get_dynamic_data( cls, variant, task_name, asset_id, project_name, host_name ): return {"layer": ""} - - def _get_subset_template(self, family): - project_name = legacy_io.Session["AVALON_PROJECT"] - asset_name = legacy_io.Session["AVALON_ASSET"] - task_name = legacy_io.Session["AVALON_TASK"] - - asset_doc = get_asset_by_name( - project_name, asset_name, fields=["data.tasks"] - ) - asset_tasks = asset_doc.get("data", {}).get("tasks") or {} - task_info = asset_tasks.get(task_name) or {} - task_type = task_info.get("type") - - tools_settings = get_project_settings(project_name)["global"]["tools"] - profiles = tools_settings["creator"]["subset_name_profiles"] - filtering_criteria = { - "families": family, - "hosts": "photoshop", - "tasks": task_name, - "task_types": task_type - } - - matching_profile = filter_profiles(profiles, filtering_criteria) - if matching_profile: - return matching_profile["template"] From 87cf386a54917adacfd91542cd3613ac0fe4babc Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 28 Jul 2022 12:52:22 +0200 Subject: [PATCH 3/8] OP-3283 - implemented for new creator --- .../photoshop/plugins/create/create_image.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index f15068b0315..ebb268dc93e 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -5,6 +5,10 @@ CreatedInstance, legacy_io ) +from openpype.hosts.photoshop.api.plugin import ( + get_subset_template, + get_subset_name_for_multiple +) class ImageCreator(Creator): @@ -68,7 +72,12 @@ def create(self, subset_name_from_ui, data, pre_create_data): if creating_multiple_groups: # concatenate with layer name to differentiate subsets - subset_name += group.name.title().replace(" ", "") + subset_template = get_subset_template(self.family) + subset_name = get_subset_name_for_multiple(subset_name, + subset_template, + group, + self.family, + data["variant"]) if group.long_name: for directory in group.long_name[::-1]: @@ -143,3 +152,9 @@ def _handle_legacy(self, instance_data): def _clean_highlights(self, stub, item): return item.replace(stub.PUBLISH_ICON, '').replace(stub.LOADED_ICON, '') + @classmethod + def get_dynamic_data( + cls, variant, task_name, asset_id, project_name, host_name + ): + """Called by UI, empty value for layer must be provided.""" + return {"layer": ""} From a03f2b6a1a6ee24692e25710d55fd0af11eecb96 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 28 Jul 2022 12:53:20 +0200 Subject: [PATCH 4/8] OP-3283 - fixed imports --- .../hosts/photoshop/plugins/create/create_legacy_image.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index 6d0587c20c9..d1a54a407e8 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -2,7 +2,10 @@ from openpype.pipeline import create from openpype.hosts.photoshop import api as photoshop -from openpype.hosts.photoshop.api.plugin import get_subset_template, get_subset_name_for_multiple +from openpype.hosts.photoshop.api.plugin import ( + get_subset_template, + get_subset_name_for_multiple +) class CreateImage(create.LegacyCreator): From de8668dc351ff77794da22427145fdbc6fc4b679 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 29 Jul 2022 12:13:43 +0200 Subject: [PATCH 5/8] OP-3283 - fix not create separate from multiple selected --- .../photoshop/plugins/create/create_image.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index ebb268dc93e..5688fe376e9 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -42,17 +42,17 @@ def create(self, subset_name_from_ui, data, pre_create_data): top_level_selected_items = stub.get_selected_layers() if pre_create_data.get("use_selection"): only_single_item_selected = len(top_level_selected_items) == 1 - for selected_item in top_level_selected_items: - if ( - only_single_item_selected or - pre_create_data.get("create_multiple")): + if ( + only_single_item_selected or + pre_create_data.get("create_multiple")): + for selected_item in top_level_selected_items: if selected_item.group: groups_to_create.append(selected_item) else: top_layers_to_wrap.append(selected_item) - else: - group = stub.group_selected_layers(subset_name_from_ui) - groups_to_create.append(group) + else: + group = stub.group_selected_layers(subset_name_from_ui) + groups_to_create.append(group) if not groups_to_create and not top_layers_to_wrap: group = stub.create_group(subset_name_from_ui) @@ -156,5 +156,4 @@ def _clean_highlights(self, stub, item): def get_dynamic_data( cls, variant, task_name, asset_id, project_name, host_name ): - """Called by UI, empty value for layer must be provided.""" - return {"layer": ""} + return {"layer": ""} \ No newline at end of file From 831884232cf1c51a76c25470986ac3b01bc44841 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 29 Jul 2022 13:03:00 +0200 Subject: [PATCH 6/8] OP-3283 - fix without select and multiple If creator was configured to not use selection and not create multiple, it failed before. (It should create one wrapping group, eg. instance, around all. Locked background layer cannot be present!) --- openpype/hosts/photoshop/plugins/create/create_image.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index 5688fe376e9..2b6e5e64482 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -53,6 +53,13 @@ def create(self, subset_name_from_ui, data, pre_create_data): else: group = stub.group_selected_layers(subset_name_from_ui) groups_to_create.append(group) + else: + stub.select_layers(stub.get_layers()) + try: + group = stub.group_selected_layers(subset_name_from_ui) + except: + raise ValueError("Cannot group locked Bakcground layer!") + groups_to_create.append(group) if not groups_to_create and not top_layers_to_wrap: group = stub.create_group(subset_name_from_ui) From 90962d673511c60df44e34e746753208fc359a1c Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 29 Jul 2022 14:41:28 +0200 Subject: [PATCH 7/8] OP-3283 - refactored logic Easier solution found without reinventing logic. --- openpype/hosts/photoshop/api/plugin.py | 53 ------------------- .../photoshop/plugins/create/create_image.py | 25 ++++----- .../plugins/create/create_legacy_image.py | 24 ++++----- 3 files changed, 20 insertions(+), 82 deletions(-) diff --git a/openpype/hosts/photoshop/api/plugin.py b/openpype/hosts/photoshop/api/plugin.py index ecbfbf91e3f..c80e6bbd063 100644 --- a/openpype/hosts/photoshop/api/plugin.py +++ b/openpype/hosts/photoshop/api/plugin.py @@ -2,11 +2,6 @@ from openpype.pipeline import LoaderPlugin from .launch_logic import stub -from openpype.pipeline import legacy_io -from openpype.client import get_asset_by_name -from openpype.settings import get_project_settings -from openpype.lib import prepare_template_data -from openpype.lib.profiles_filtering import filter_profiles def get_unique_layer_name(layers, asset_name, subset_name): @@ -38,51 +33,3 @@ class PhotoshopLoader(LoaderPlugin): @staticmethod def get_stub(): return stub() - - -def get_subset_template(family): - """Get subset template name from Settings""" - project_name = legacy_io.Session["AVALON_PROJECT"] - asset_name = legacy_io.Session["AVALON_ASSET"] - task_name = legacy_io.Session["AVALON_TASK"] - - asset_doc = get_asset_by_name( - project_name, asset_name, fields=["data.tasks"] - ) - asset_tasks = asset_doc.get("data", {}).get("tasks") or {} - task_info = asset_tasks.get(task_name) or {} - task_type = task_info.get("type") - - tools_settings = get_project_settings(project_name)["global"]["tools"] - profiles = tools_settings["creator"]["subset_name_profiles"] - filtering_criteria = { - "families": family, - "hosts": "photoshop", - "tasks": task_name, - "task_types": task_type - } - - matching_profile = filter_profiles(profiles, filtering_criteria) - if matching_profile: - return matching_profile["template"] - - -def get_subset_name_for_multiple(subset_name, subset_template, group, - family, variant): - """Update subset name with layer information to differentiate multiple - - subset_template might contain specific way how to format layer name - ({layer},{Layer} or {LAYER}). If subset_template doesn't contain placeholder - at all, fall back to original solution. - """ - if not subset_template or 'layer' not in subset_template.lower(): - subset_name += group.name.title().replace(" ", "") - else: - fill_pairs = { - "family": family, - "variant": variant, - "task": legacy_io.Session["AVALON_TASK"], - "layer": group.name - } - - return subset_template.format(**prepare_template_data(fill_pairs)) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index 2b6e5e64482..44a74de6500 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -5,10 +5,7 @@ CreatedInstance, legacy_io ) -from openpype.hosts.photoshop.api.plugin import ( - get_subset_template, - get_subset_name_for_multiple -) +from openpype.lib import prepare_template_data class ImageCreator(Creator): @@ -71,6 +68,7 @@ def create(self, subset_name_from_ui, data, pre_create_data): group = stub.group_selected_layers(layer.name) groups_to_create.append(group) + layer_name = '' creating_multiple_groups = len(groups_to_create) > 1 for group in groups_to_create: subset_name = subset_name_from_ui # reset to name from creator UI @@ -78,13 +76,12 @@ def create(self, subset_name_from_ui, data, pre_create_data): created_group_name = self._clean_highlights(stub, group.name) if creating_multiple_groups: - # concatenate with layer name to differentiate subsets - subset_template = get_subset_template(self.family) - subset_name = get_subset_name_for_multiple(subset_name, - subset_template, - group, - self.family, - data["variant"]) + layer_name = group.name + if "{layer}" not in subset_name.lower(): + subset_name += "{Layer}" + + layer_fill = prepare_template_data({"layer": layer_name}) + subset_name = subset_name.format(**layer_fill) if group.long_name: for directory in group.long_name[::-1]: @@ -160,7 +157,5 @@ def _clean_highlights(self, stub, item): return item.replace(stub.PUBLISH_ICON, '').replace(stub.LOADED_ICON, '') @classmethod - def get_dynamic_data( - cls, variant, task_name, asset_id, project_name, host_name - ): - return {"layer": ""} \ No newline at end of file + def get_dynamic_data(cls, *args, **kwargs): + return {"layer": "{layer}"} diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index d1a54a407e8..e465c30abd0 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -2,10 +2,7 @@ from openpype.pipeline import create from openpype.hosts.photoshop import api as photoshop -from openpype.hosts.photoshop.api.plugin import ( - get_subset_template, - get_subset_name_for_multiple -) +from openpype.lib import prepare_template_data class CreateImage(create.LegacyCreator): @@ -80,6 +77,7 @@ def process(self): groups.append(group) creator_subset_name = self.data["subset"] + layer_name = '' for group in groups: long_names = [] group.name = group.name.replace(stub.PUBLISH_ICON, ''). \ @@ -87,12 +85,12 @@ def process(self): subset_name = creator_subset_name if len(groups) > 1: - subset_template = get_subset_template(self.family) - subset_name = get_subset_name_for_multiple(subset_name, - subset_template, - group, - self.family, - self.data["variant"]) + layer_name = group.name + if "{layer}" not in subset_name.lower(): + subset_name += "{Layer}" + + layer_fill = prepare_template_data({"layer": layer_name}) + subset_name = subset_name.format(**layer_fill) if group.long_name: for directory in group.long_name[::-1]: @@ -110,7 +108,5 @@ def process(self): stub.rename_layer(group.id, stub.PUBLISH_ICON + group.name) @classmethod - def get_dynamic_data( - cls, variant, task_name, asset_id, project_name, host_name - ): - return {"layer": ""} + def get_dynamic_data(cls, *args, **kwargs): + return {"layer": "{layer}"} From 4ac9ed6886ee455640e93c31fac510270ce571bd Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 29 Jul 2022 16:24:16 +0200 Subject: [PATCH 8/8] OP-3283 - fix invalid characters in subset name Removal of invalid characters must be done in Create phase to persist. --- openpype/hosts/photoshop/plugins/create/create_image.py | 9 ++++++++- .../photoshop/plugins/create/create_legacy_image.py | 9 ++++++++- .../hosts/photoshop/plugins/publish/validate_naming.py | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index 44a74de6500..2cfbfa8778c 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -1,3 +1,5 @@ +import re + from openpype.hosts.photoshop import api from openpype.lib import BoolDef from openpype.pipeline import ( @@ -6,6 +8,7 @@ legacy_io ) from openpype.lib import prepare_template_data +from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS class ImageCreator(Creator): @@ -76,7 +79,11 @@ def create(self, subset_name_from_ui, data, pre_create_data): created_group_name = self._clean_highlights(stub, group.name) if creating_multiple_groups: - layer_name = group.name + layer_name = re.sub( + "[^{}]+".format(SUBSET_NAME_ALLOWED_SYMBOLS), + "", + group.name + ) if "{layer}" not in subset_name.lower(): subset_name += "{Layer}" diff --git a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py index e465c30abd0..2792a775e06 100644 --- a/openpype/hosts/photoshop/plugins/create/create_legacy_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_legacy_image.py @@ -1,8 +1,11 @@ +import re + from Qt import QtWidgets from openpype.pipeline import create from openpype.hosts.photoshop import api as photoshop from openpype.lib import prepare_template_data +from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS class CreateImage(create.LegacyCreator): @@ -85,7 +88,11 @@ def process(self): subset_name = creator_subset_name if len(groups) > 1: - layer_name = group.name + layer_name = re.sub( + "[^{}]+".format(SUBSET_NAME_ALLOWED_SYMBOLS), + "", + group.name + ) if "{layer}" not in subset_name.lower(): subset_name += "{Layer}" diff --git a/openpype/hosts/photoshop/plugins/publish/validate_naming.py b/openpype/hosts/photoshop/plugins/publish/validate_naming.py index b53f4e8198f..8106d6ff163 100644 --- a/openpype/hosts/photoshop/plugins/publish/validate_naming.py +++ b/openpype/hosts/photoshop/plugins/publish/validate_naming.py @@ -4,6 +4,7 @@ import openpype.api from openpype.pipeline import PublishXmlValidationError from openpype.hosts.photoshop import api as photoshop +from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS class ValidateNamingRepair(pyblish.api.Action): @@ -50,6 +51,13 @@ def process(self, context, plugin): subset_name = re.sub(invalid_chars, replace_char, instance.data["subset"]) + # format from Tool Creator + subset_name = re.sub( + "[^{}]+".format(SUBSET_NAME_ALLOWED_SYMBOLS), + "", + subset_name + ) + layer_meta["subset"] = subset_name stub.imprint(instance_id, layer_meta)