mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
modified workfile utils to use folder and task entity
This commit is contained in:
parent
02eef200a1
commit
e25856eb03
3 changed files with 254 additions and 193 deletions
|
|
@ -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": {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue