modified workfile utils to use folder and task entity

This commit is contained in:
Jakub Trllo 2024-03-04 15:09:47 +01:00
parent 02eef200a1
commit e25856eb03
3 changed files with 254 additions and 193 deletions

View file

@ -13,12 +13,12 @@ import re
import collections
import json
import ayon_api
from ayon_core.client import (
get_asset_by_name,
get_subsets,
get_last_versions,
get_representations,
get_linked_assets,
)
from ayon_core.settings import get_project_settings
from ayon_core.lib import (
@ -76,21 +76,21 @@ class BuildWorkfile:
def build_workfile(self):
"""Prepares and load containers into workfile.
Loads latest versions of current and linked assets to workfile by logic
stored in Workfile profiles from presets. Profiles are set by host,
filtered by current task name and used by families.
Loads latest versions of current and linked folders to workfile by
logic stored in Workfile profiles from presets. Profiles are set
by host, filtered by current task name and used by families.
Each product type can specify representation names and loaders for
representations and first available and successful loaded
representation is returned as container.
At the end you'll get list of loaded containers per each asset.
At the end you'll get list of loaded containers per each folder.
loaded_containers [{
"asset_doc": <AssetEntity1>,
"folder_entity": <FolderEntity1>,
"containers": [<Container1>, <Container2>, ...]
}, {
"asset_doc": <AssetEntity2>,
"folder_entity": <FolderEntity2>,
"containers": [<Container3>, ...]
}, {
...
@ -100,22 +100,21 @@ class BuildWorkfile:
List[Dict[str, Any]]: Loaded containers during build.
"""
from ayon_core.pipeline.context_tools import (
get_current_project_name,
get_current_folder_path,
get_current_task_name,
)
from ayon_core.pipeline.context_tools import get_current_context
loaded_containers = []
# Get current asset name and entity
project_name = get_current_project_name()
current_folder_path = get_current_folder_path()
current_asset_doc = get_asset_by_name(
# Get current folder and task entities
context = get_current_context()
project_name = context["project_name"]
current_folder_path = context["folder_path"]
current_task_name = context["task_name"]
current_folder_entity = ayon_api.get_folder_by_path(
project_name, current_folder_path
)
# Skip if asset was not found
if not current_asset_doc:
# Skip if folder was not found
if not current_folder_entity:
print("Folder entity `{}` was not found".format(
current_folder_path
))
@ -138,12 +137,9 @@ class BuildWorkfile:
self.log.warning("There are no registered loaders.")
return loaded_containers
# Get current task name
current_task_name = get_current_task_name()
# Load workfile presets for task
self.build_presets = self.get_build_presets(
current_task_name, current_asset_doc
current_task_name, current_folder_entity["id"]
)
# Skip if there are any presets for task
@ -180,45 +176,53 @@ class BuildWorkfile:
"loading preset for it's linked folders."
).format(current_task_name))
# Prepare assets to process by workfile presets
asset_docs = []
# Prepare folders to process by workfile presets
folder_entities = []
current_folder_id = None
if current_context_profiles:
# Add current asset entity if preset has current context set
asset_docs.append(current_asset_doc)
current_folder_id = current_asset_doc["_id"]
# Add current folder entity if preset has current context set
folder_entities.append(current_folder_entity)
current_folder_id = current_folder_entity["_id"]
if link_context_profiles:
# Find and append linked assets if preset has set linked mapping
link_assets = get_linked_assets(project_name, current_asset_doc)
if link_assets:
asset_docs.extend(link_assets)
# Find and append linked folders if preset has set linked mapping
linked_folder_entities = self._get_linked_folder_entities(
project_name, current_folder_entity["id"]
)
if linked_folder_entities:
folder_entities.extend(linked_folder_entities)
# Skip if there are no assets. This can happen if only linked mapping
# is set and there are no links for his asset.
if not asset_docs:
# Skip if there are no folders. This can happen if only linked mapping
# is set and there are no links for his folder.
if not folder_entities:
self.log.warning(
"Asset does not have linked assets. Nothing to process."
"Folder does not have linked folders. Nothing to process."
)
return loaded_containers
# Prepare entities from database for assets
prepared_entities = self._collect_last_version_repres(asset_docs)
# Prepare entities from database for folders
prepared_entities = self._collect_last_version_repres(
folder_entities
)
# Load containers by prepared entities and presets
# - Current asset containers
# - Current folder containers
if current_folder_id and current_folder_id in prepared_entities:
current_context_data = prepared_entities.pop(current_folder_id)
loaded_data = self.load_containers_by_asset_data(
current_context_data, current_context_profiles, loaders_by_name
loaded_data = self.load_containers_by_folder_data(
current_context_data,
current_context_profiles,
loaders_by_name
)
if loaded_data:
loaded_containers.append(loaded_data)
# - Linked assets container
for linked_asset_data in prepared_entities.values():
loaded_data = self.load_containers_by_asset_data(
linked_asset_data, link_context_profiles, loaders_by_name
for linked_folder_data in prepared_entities.values():
loaded_data = self.load_containers_by_folder_data(
linked_folder_data,
link_context_profiles,
loaders_by_name
)
if loaded_data:
loaded_containers.append(loaded_data)
@ -226,7 +230,7 @@ class BuildWorkfile:
# Return list of loaded containers
return loaded_containers
def get_build_presets(self, task_name, asset_doc):
def get_build_presets(self, task_name, folder_id):
""" Returns presets to build workfile for task name.
Presets are loaded for current project received by
@ -235,6 +239,7 @@ class BuildWorkfile:
Args:
task_name (str): Task name used for filtering build presets.
folder_id (str): Folder id.
Returns:
Dict[str, Any]: preset per entered task name
@ -245,10 +250,9 @@ class BuildWorkfile:
get_current_project_name,
)
project_name = get_current_project_name()
host_name = get_current_host_name()
project_settings = get_project_settings(
get_current_project_name()
)
project_settings = get_project_settings(project_name)
host_settings = project_settings.get(host_name) or {}
# Get presets for host
@ -261,13 +265,15 @@ class BuildWorkfile:
if not builder_profiles:
return None
task_type = (
asset_doc
.get("data", {})
.get("tasks", {})
.get(task_name, {})
.get("type")
task_entity = ayon_api.get_task_by_name(
project_name,
folder_id,
task_name,
)
task_type = None
if task_entity:
task_type = task_entity["taskType"]
filter_data = {
"task_types": task_type,
"tasks": task_name
@ -349,6 +355,31 @@ class BuildWorkfile:
return valid_profiles
def _get_linked_folder_entities(self, project_name, folder_id):
"""Get linked folder entities for entered folder.
Args:
project_name (str): Project name.
folder_id (str): Folder id.
Returns:
list[dict[str, Any]]: Linked folder entities.
"""
links = ayon_api.get_folder_links(
project_name, folder_id, link_direction="in"
)
linked_folder_ids = {
link["entityId"]
for link in links
if link["entityType"] == "folder"
}
if not linked_folder_ids:
return []
return list(ayon_api.get_folders(
project_name, folder_ids=linked_folder_ids
))
def _prepare_profile_for_products(self, subset_docs, profiles):
"""Select profile for each product by it's data.
@ -405,28 +436,28 @@ class BuildWorkfile:
break
return profiles_by_product_id
def load_containers_by_asset_data(
self, asset_doc_data, build_profiles, loaders_by_name
def load_containers_by_folder_data(
self, linked_folder_data, build_profiles, loaders_by_name
):
"""Load containers for entered asset entity by Build profiles.
"""Load containers for entered folder entity by Build profiles.
Args:
asset_doc_data (Dict[str, Any]): Prepared data with products,
last versions and representations for specific asset.
linked_folder_data (Dict[str, Any]): Prepared data with products,
last versions and representations for specific folder.
build_profiles (Dict[str, Any]): Build profiles.
loaders_by_name (Dict[str, LoaderPlugin]): Available loaders
per name.
Returns:
Dict[str, Any]: Output contains asset document
Dict[str, Any]: Output contains folder entity
and loaded containers.
"""
# Make sure all data are not empty
if not asset_doc_data or not build_profiles or not loaders_by_name:
if not linked_folder_data or not build_profiles or not loaders_by_name:
return
asset_doc = asset_doc_data["asset_doc"]
folder_entity = linked_folder_data["folder_entity"]
valid_profiles = self._filter_build_profiles(
build_profiles, loaders_by_name
@ -442,7 +473,7 @@ class BuildWorkfile:
products_by_id = {}
version_by_product_id = {}
repres_by_version_id = {}
for product_id, in_data in asset_doc_data["subsets"].items():
for product_id, in_data in linked_folder_data["subsets"].items():
subset_doc = in_data["subset_doc"]
products_by_id[subset_doc["_id"]] = subset_doc
@ -454,8 +485,8 @@ class BuildWorkfile:
)
if not products_by_id:
self.log.warning("There are not products for folder {0}".format(
asset_doc["name"]
self.log.warning("There are not products for folder {}".format(
folder_entity["path"]
))
return
@ -480,7 +511,7 @@ class BuildWorkfile:
# DEBUG message
msg = "Valid representations for Folder: `{}`".format(
asset_doc["name"]
folder_entity["path"]
)
for product_id, repres in valid_repres_by_product_id.items():
subset_doc = products_by_id[product_id]
@ -498,7 +529,7 @@ class BuildWorkfile:
)
return {
"asset_doc": asset_doc,
"folder_entity": folder_entity,
"containers": containers
}
@ -628,11 +659,11 @@ class BuildWorkfile:
return loaded_containers
def _collect_last_version_repres(self, asset_docs):
"""Collect products, versions and representations for asset_entities.
def _collect_last_version_repres(self, folder_entities):
"""Collect products, versions and representations for folder_entities.
Args:
asset_docs (List[Dict[str, Any]]): Asset entities for which
folder_entities (List[Dict[str, Any]]): Folder entities for which
want to find data.
Returns:
@ -641,11 +672,11 @@ class BuildWorkfile:
Example output:
```
{
{Asset ID}: {
"asset_doc": <AssetEntity>,
<folder id>: {
"folder_entity": <dict[str, Any]>,
"subsets": {
{Subset ID}: {
"subset_doc": <SubsetEntity>,
<product id>: {
"subset_doc": <dict[str, Any]>,
"version": {
"version_doc": <VersionEntity>,
"repres": [
@ -665,17 +696,17 @@ class BuildWorkfile:
from ayon_core.pipeline.context_tools import get_current_project_name
output = {}
if not asset_docs:
if not folder_entities:
return output
asset_docs_by_ids = {
asset_doc["_id"]: asset_doc
for asset_doc in asset_docs
folder_entities_by_id = {
folder_entity["id"]: folder_entity
for folder_entity in folder_entities
}
project_name = get_current_project_name()
subset_docs = list(get_subsets(
project_name, asset_ids=asset_docs_by_ids.keys()
project_name, asset_ids=folder_entities_by_id.keys()
))
subset_docs_by_id = {
subset_doc["_id"]: subset_doc
@ -701,11 +732,11 @@ class BuildWorkfile:
subset_doc = subset_docs_by_id[product_id]
folder_id = subset_doc["parent"]
asset_doc = asset_docs_by_ids[folder_id]
folder_entity = folder_entities_by_id[folder_id]
if folder_id not in output:
output[folder_id] = {
"asset_doc": asset_doc,
"folder_entity": folder_entity,
"subsets": {}
}

View file

@ -5,7 +5,6 @@ import platform
import ayon_api
from ayon_core.client import get_asset_by_name
from ayon_core.settings import get_project_settings
from ayon_core.lib import (
filter_profiles,
@ -17,7 +16,11 @@ from ayon_core.pipeline.template_data import get_template_data
def get_workfile_template_key_from_context(
asset_name, task_name, host_name, project_name, project_settings=None
project_name,
folder_path,
task_name,
host_name,
project_settings=None
):
"""Helper function to get template key for workfile template.
@ -25,41 +28,39 @@ def get_workfile_template_key_from_context(
context".
Args:
asset_name(str): Name of asset document.
task_name(str): Task name for which is template key retrieved.
Must be available on asset document under `data.tasks`.
host_name(str): Name of host implementation for which is workfile
used.
project_name(str): Project name where asset and task is.
project_settings(Dict[str, Any]): Project settings for passed
project_name (str): Project name.
folder_path (str): Folder path.
task_name (str): Task name.
host_name (str): Host name.
project_settings (Dict[str, Any]): Project settings for passed
'project_name'. Not required at all but makes function faster.
"""
asset_doc = get_asset_by_name(
project_name, asset_name, fields=["data.tasks"]
folder_entity = ayon_api.get_folder_by_path(
project_name, folder_path, fields={"id"}
)
asset_tasks = asset_doc.get("data", {}).get("tasks") or {}
task_info = asset_tasks.get(task_name) or {}
task_type = task_info.get("type")
task_entity = ayon_api.get_task_by_name(
project_name, folder_entity["id"], task_name
)
task_type = task_entity.get("type")
return get_workfile_template_key(
task_type, host_name, project_name, project_settings
project_name, task_type, host_name, project_settings
)
def get_workfile_template_key(
task_type, host_name, project_name, project_settings=None
project_name, task_type, host_name, project_settings=None
):
"""Workfile template key which should be used to get workfile template.
Function is using profiles from project settings to return right template
for passet task type and host name.
for passed task type and host name.
Args:
task_type(str): Name of task type.
host_name(str): Name of host implementation (e.g. "maya", "nuke", ...)
project_name(str): Name of project in which context should look for
settings.
project_name(str): Project name.
task_type(str): Task type.
host_name(str): Host name (e.g. "maya", "nuke", ...)
project_settings(Dict[str, Any]): Prepared project settings for
project name. Optional to make processing faster.
"""
@ -128,9 +129,9 @@ def get_workdir_with_workdir_data(
if not template_key:
template_key = get_workfile_template_key(
workdir_data["project"]["name"],
workdir_data["task"]["type"],
workdir_data["app"],
workdir_data["project"]["name"],
project_settings
)
@ -144,8 +145,8 @@ def get_workdir_with_workdir_data(
def get_workdir(
project_entity,
asset_doc,
task_name,
folder_entity,
task_entity,
host_name,
anatomy=None,
template_key=None,
@ -155,8 +156,8 @@ def get_workdir(
Args:
project_entity (Dict[str, Any]): Project entity.
asset_doc (Dict[str, Any]): Mongo document of asset from MongoDB.
task_name (str): Task name for which are workdir data preapred.
folder_entity (Dict[str, Any]): Folder entity.
task_entity (dict[str, Any]): Task entity.
host_name (str): Host which is used to workdir. This is required
because workdir template may contain `{app}` key. In `Session`
is stored under `AYON_HOST_NAME` key.
@ -180,7 +181,10 @@ def get_workdir(
)
workdir_data = get_template_data(
project_entity, asset_doc, task_name, host_name
project_entity,
folder_entity,
task_entity,
host_name,
)
# Output is TemplateResult object which contain useful data
return get_workdir_with_workdir_data(
@ -341,8 +345,8 @@ def get_last_workfile(
def get_custom_workfile_template(
project_entity,
asset_doc,
task_name,
folder_entity,
task_entity,
host_name,
anatomy=None,
project_settings=None
@ -360,13 +364,13 @@ def get_custom_workfile_template(
points to a file which is copied as
first workfile
It is expected that passed argument are already queried documents of
project and asset as parents of processing task name.
It is expected that passed argument are already queried entities of
project and folder as parents of processing task name.
Args:
project_entity (Dict[str, Any]): Project entity.
asset_doc (Dict[str, Any]): Asset document from MongoDB.
task_name (str): Name of task for which templates are filtered.
folder_entity (Dict[str, Any]): Folder entity.
task_entity (Dict[str, Any]): Task entity.
host_name (str): Name of host.
anatomy (Anatomy): Optionally passed anatomy object for passed project
name.
@ -415,9 +419,9 @@ def get_custom_workfile_template(
if anatomy is None:
anatomy = Anatomy(project_name)
# get project, asset, task anatomy context data
# get project, folder, task anatomy context data
anatomy_context_data = get_template_data(
project_entity, asset_doc, task_name, host_name
project_entity, folder_entity, task_entity, host_name
)
# add root dict
anatomy_context_data["root"] = anatomy.roots
@ -448,7 +452,7 @@ def get_custom_workfile_template(
def get_custom_workfile_template_by_string_context(
project_name,
asset_name,
folder_path,
task_name,
host_name,
anatomy=None,
@ -456,13 +460,13 @@ def get_custom_workfile_template_by_string_context(
):
"""Filter and fill workfile template profiles by passed context.
Passed context are string representations of project, asset and task.
Function will query documents of project and asset to be able use
Passed context are string representations of project, folder and task.
Function will query documents of project and folder to be able to use
`get_custom_workfile_template` for rest of logic.
Args:
project_name (str): Project name.
asset_name (str): Asset name.
folder_path (str): Folder path.
task_name (str): Task name.
host_name (str): Name of host.
anatomy (Anatomy): Optionally prepared anatomy object for passed
@ -476,12 +480,15 @@ def get_custom_workfile_template_by_string_context(
"""
project_entity = ayon_api.get_project(project_name)
asset_doc = get_asset_by_name(project_name, asset_name)
folder_entity = ayon_api.get_folder_by_path(project_name, folder_path)
task_entity = ayon_api.get_task_by_name(
project_name, folder_entity["id"], task_name
)
return get_custom_workfile_template(
project_entity,
asset_doc,
task_name,
folder_entity,
task_entity,
host_name,
anatomy,
project_settings

View file

@ -18,12 +18,17 @@ import copy
from abc import ABCMeta, abstractmethod
import six
from ayon_api import get_products, get_last_versions
from ayon_api import (
get_folders,
get_folder_by_path,
get_folder_links,
get_task_by_name,
get_products,
get_last_versions,
)
from ayon_api.graphql_queries import folders_graphql_query
from ayon_core.client import (
get_asset_by_name,
get_linked_assets,
get_representations,
get_ayon_server_api_connection,
)
@ -48,6 +53,8 @@ from ayon_core.pipeline.create import (
CreateContext,
)
_NOT_SET = object()
class TemplateNotFound(Exception):
"""Exception raised when template does not exist."""
@ -117,9 +124,9 @@ class AbstractTemplateBuilder(object):
self._project_settings = None
self._current_asset_doc = None
self._linked_asset_docs = None
self._task_type = None
self._current_folder_entity = _NOT_SET
self._current_task_entity = _NOT_SET
self._linked_folder_entities = _NOT_SET
@property
def project_name(self):
@ -155,33 +162,39 @@ class AbstractTemplateBuilder(object):
return self._project_settings
@property
def current_asset_doc(self):
if self._current_asset_doc is None:
self._current_asset_doc = get_asset_by_name(
def current_folder_entity(self):
if self._current_folder_entity is _NOT_SET:
self._current_folder_entity = get_folder_by_path(
self.project_name, self.current_folder_path
)
return self._current_asset_doc
return self._current_folder_entity
@property
def linked_asset_docs(self):
if self._linked_asset_docs is None:
self._linked_asset_docs = get_linked_assets(
self.project_name, self.current_asset_doc
)
return self._linked_asset_docs
def linked_folder_entities(self):
if self._linked_folder_entities is _NOT_SET:
self._linked_folder_entities = self._get_linked_folder_entities()
return self._linked_folder_entities
@property
def current_task_entity(self):
if self._current_task_entity is _NOT_SET:
task_entity = None
folder_entity = self.current_folder_entity
if folder_entity:
task_entity = get_task_by_name(
self.project_name,
folder_entity["id"],
self.current_task_name
)
self._current_task_entity = task_entity
return self._current_task_entity
@property
def current_task_type(self):
asset_doc = self.current_asset_doc
if not asset_doc:
return None
return (
asset_doc
.get("data", {})
.get("tasks", {})
.get(self.current_task_name, {})
.get("type")
)
task_entity = self.current_task_entity
if task_entity:
return task_entity["taskType"]
return None
@property
def create_context(self):
@ -242,9 +255,9 @@ class AbstractTemplateBuilder(object):
self._loaders_by_name = None
self._creators_by_name = None
self._current_asset_doc = None
self._linked_asset_docs = None
self._task_type = None
self._current_folder_entity = _NOT_SET
self._current_task_entity = _NOT_SET
self._linked_folder_entities = _NOT_SET
self._project_settings = None
@ -256,6 +269,22 @@ class AbstractTemplateBuilder(object):
self._loaders_by_name = get_loaders_by_name()
return self._loaders_by_name
def _get_linked_folder_entities(self):
project_name = self.project_name
folder_entity = self.current_folder_entity
if not folder_entity:
return []
links = get_folder_links(
project_name, folder_entity["id"], link_direction="in"
)
linked_folder_ids = {
link["entityId"]
for link in links
if link["entityType"] == "folder"
}
return list(get_folders(project_name, folder_ids=linked_folder_ids))
def _collect_legacy_creators(self):
creators_by_name = {}
for creator in discover_legacy_creator_plugins():
@ -305,8 +334,8 @@ class AbstractTemplateBuilder(object):
different key or if the key is not already used for something else.
Key should be self explanatory to content.
- wrong: 'asset'
- good: 'asset_name'
- wrong: 'folder'
- good: 'folder_name'
Args:
key (str): Key under which is key stored.
@ -351,8 +380,8 @@ class AbstractTemplateBuilder(object):
different key or if the key is not already used for something else.
Key should be self explanatory to content.
- wrong: 'asset'
- good: 'asset_name'
- wrong: 'folder'
- good: 'folder_path'
Args:
key (str): Key under which is key stored.
@ -371,8 +400,8 @@ class AbstractTemplateBuilder(object):
different key or if the key is not already used for something else.
Key should be self explanatory to content.
- wrong: 'asset'
- good: 'asset_name'
- wrong: 'folder'
- good: 'folder_path'
Args:
key (str): Key under which is key stored.
@ -1021,8 +1050,8 @@ class PlaceholderPlugin(object):
Using shared data from builder but stored under plugin identifier.
Key should be self explanatory to content.
- wrong: 'asset'
- good: 'asset_name'
- wrong: 'folder'
- good: 'folder_path'
Args:
key (str): Key under which is key stored.
@ -1061,8 +1090,8 @@ class PlaceholderPlugin(object):
Using shared data from builder but stored under plugin identifier.
Key should be self explanatory to content.
- wrong: 'asset'
- good: 'asset_name'
- wrong: 'folder'
- good: 'folder_path'
Shared populate data are cleaned up during populate while loop.
@ -1323,7 +1352,7 @@ class PlaceholderLoadMixin(object):
items=loader_items,
tooltip=(
"Loader"
"\nDefines what OpenPype loader will be used to"
"\nDefines what AYON loader will be used to"
" load assets."
"\nUseable loader depends on current host's loader list."
"\nField is case sensitive."
@ -1480,7 +1509,7 @@ class PlaceholderLoadMixin(object):
return []
project_name = self.builder.project_name
current_asset_doc = self.builder.current_asset_doc
current_folder_entity = self.builder.current_folder_entity
folder_path_regex = placeholder.data["folder_path"]
product_name_regex_value = placeholder.data["product_name"]
@ -1492,7 +1521,7 @@ class PlaceholderLoadMixin(object):
builder_type = placeholder.data["builder_type"]
folder_ids = []
if builder_type == "context_folder":
folder_ids = [current_asset_doc["_id"]]
folder_ids = [current_folder_entity["_id"]]
elif builder_type == "all_folders":
folder_ids = list(self._query_by_folder_regex(
@ -1547,17 +1576,18 @@ class PlaceholderLoadMixin(object):
"""Reduce representations to last verison."""
mapping = {}
# TODO use representation context with entities
for repre_doc in representations:
repre_context = repre_doc["context"]
asset_name = repre_context["asset"]
folder_name = repre_context["asset"]
product_name = repre_context["subset"]
version = repre_context.get("version", -1)
if asset_name not in mapping:
mapping[asset_name] = {}
if folder_name not in mapping:
mapping[folder_name] = {}
product_mapping = mapping[asset_name]
product_mapping = mapping[folder_name]
if product_name not in product_mapping:
product_mapping[product_name] = collections.defaultdict(list)
@ -1788,31 +1818,24 @@ class PlaceholderCreateMixin(object):
# create product name
context = self._builder.get_current_context()
project_name = context["project_name"]
asset_name = context["folder_path"]
folder_path = context["folder_path"]
task_name = context["task_name"]
host_name = self.builder.host_name
if legacy_create:
asset_doc = get_asset_by_name(
project_name, asset_name, fields=["_id"]
)
assert asset_doc, "No current asset found in Session"
product_name = creator_plugin.get_product_name(
project_name,
asset_doc["_id"],
task_name,
create_variant,
)
folder_entity = get_folder_by_path(project_name, folder_path)
if not folder_entity:
raise ValueError("Current context does not have set folder")
task_entity = get_task_by_name(
project_name, folder_entity["id"], task_name
)
else:
asset_doc = get_asset_by_name(project_name, asset_name)
assert asset_doc, "No current asset found in Session"
product_name = creator_plugin.get_product_name(
project_name,
asset_doc,
task_name,
create_variant,
self.builder.host_name
)
product_name = creator_plugin.get_product_name(
project_name,
folder_entity,
task_entity,
create_variant,
host_name
)
creator_data = {
"creator_name": creator_name,
@ -1828,13 +1851,13 @@ class PlaceholderCreateMixin(object):
if legacy_create:
creator_instance = creator_plugin(
product_name,
asset_name
folder_path
).process()
else:
creator_instance = self.builder.create_context.create(
creator_plugin.identifier,
create_variant,
asset_doc,
folder_entity,
task_name=task_name,
pre_create_data=pre_create_data
)