tools use version entity

This commit is contained in:
Jakub Trllo 2024-03-06 11:01:26 +01:00
parent 41b0c51171
commit e812e8e963
6 changed files with 161 additions and 164 deletions

View file

@ -7,10 +7,7 @@ import uuid
import ayon_api
from ayon_core.client import (
get_versions,
get_representations,
)
from ayon_core.client import get_representations
from ayon_core.pipeline.load import (
discover_loader_plugins,
ProductLoaderPlugin,
@ -34,12 +31,12 @@ class LoaderActionsModel:
This is probably only part of models that requires to use codebase from
'ayon_core.client' because of backwards compatibility with loaders logic
which are expecting mongo documents.
which are expecting entities.
TODOs:
Deprecate 'qargparse' usage in loaders and implement conversion
of 'ActionItem' to data (and 'from_data').
Use controller to get entities (documents) -> possible only when
Use controller to get entities -> possible only when
loaders are able to handle AYON vs. OpenPype logic.
Add missing site sync logic, and if possible remove it from loaders.
Implement loader actions to replace load plugins.
@ -367,39 +364,6 @@ class LoaderActionsModel:
return action_item.order, action_item.label
def _get_version_docs(self, project_name, version_ids):
"""Get version documents for given version ids.
This function also handles hero versions and copies data from
source version to it.
Todos:
Remove this function when this is completely rewritten to
use AYON calls.
"""
version_docs = list(get_versions(
project_name, version_ids=version_ids, hero=True
))
hero_versions_by_src_id = collections.defaultdict(list)
src_hero_version = set()
for version_doc in version_docs:
if version_doc["type"] != "hero":
continue
version_id = ""
src_hero_version.add(version_id)
hero_versions_by_src_id[version_id].append(version_doc)
src_versions = []
if src_hero_version:
src_versions = get_versions(project_name, version_ids=version_ids)
for src_version in src_versions:
src_version_id = src_version["_id"]
for hero_version in hero_versions_by_src_id[src_version_id]:
hero_version["data"] = copy.deepcopy(src_version["data"])
return version_docs
def _contexts_for_versions(self, project_name, version_ids):
"""Get contexts for given version ids.
@ -408,7 +372,7 @@ class LoaderActionsModel:
given versions.
This method is very similar to '_contexts_for_representations' but the
queries of documents are called in a different order.
queries of entities are called in a different order.
Args:
project_name (str): Project name.
@ -425,16 +389,18 @@ class LoaderActionsModel:
if not project_name and not version_ids:
return version_context_by_id, repre_context_by_id
version_docs = self._get_version_docs(project_name, version_ids)
version_docs_by_id = {}
version_docs_by_product_id = collections.defaultdict(list)
for version_doc in version_docs:
version_id = version_doc["_id"]
product_id = version_doc["parent"]
version_docs_by_id[version_id] = version_doc
version_docs_by_product_id[product_id].append(version_doc)
version_entities = ayon_api.get_versions(
project_name, version_ids=version_ids
)
version_entities_by_id = {}
version_entities_by_product_id = collections.defaultdict(list)
for version_entity in version_entities:
version_id = version_entity["id"]
product_id = version_entity["productId"]
version_entities_by_id[version_id] = version_entity
version_entities_by_product_id[product_id].append(version_entity)
_product_ids = set(version_docs_by_product_id.keys())
_product_ids = set(version_entities_by_product_id.keys())
_product_entities = ayon_api.get_products(
project_name, product_ids=_product_ids
)
@ -448,9 +414,9 @@ class LoaderActionsModel:
project_entity = ayon_api.get_project(project_name)
for version_doc in version_docs:
version_id = version_doc["_id"]
product_id = version_doc["parent"]
for version_entity in version_entities_by_id:
version_id = version_entity["id"]
product_id = version_entity["productId"]
product_entity = product_entities_by_id[product_id]
folder_id = product_entity["folderId"]
folder_entity = folder_entities_by_id[folder_id]
@ -458,15 +424,15 @@ class LoaderActionsModel:
"project": project_entity,
"folder": folder_entity,
"product": product_entity,
"version": version_doc,
"version": version_entity,
}
repre_docs = get_representations(
project_name, version_ids=version_ids)
for repre_doc in repre_docs:
version_id = repre_doc["parent"]
version_doc = version_docs_by_id[version_id]
product_id = version_doc["parent"]
version_entity = version_entities_by_id[version_id]
product_id = version_entity["productId"]
product_entity = product_entities_by_id[product_id]
folder_id = product_entity["folderId"]
folder_entity = folder_entities_by_id[folder_id]
@ -475,7 +441,7 @@ class LoaderActionsModel:
"project": project_entity,
"folder": folder_entity,
"product": product_entity,
"version": version_doc,
"version": version_entity,
"representation": repre_doc,
}
@ -489,7 +455,7 @@ class LoaderActionsModel:
given versions.
This method is very similar to '_contexts_for_versions' but the
queries of documents are called in a different order.
queries of entities are called in a different order.
Args:
project_name (str): Project name.
@ -509,12 +475,14 @@ class LoaderActionsModel:
project_name, representation_ids=repre_ids
))
version_ids = {r["parent"] for r in repre_docs}
version_docs = self._get_version_docs(project_name, version_ids)
version_docs_by_id = {
v["_id"]: v for v in version_docs
version_entities = ayon_api.get_versions(
project_name, version_ids=version_ids
)
version_entities_by_id = {
v["id"]: v for v in version_entities
}
product_ids = {v["parent"] for v in version_docs_by_id.values()}
product_ids = {v["productId"] for v in version_entities_by_id.values()}
product_entities = ayon_api.get_products(
project_name, product_ids=product_ids
)
@ -543,8 +511,8 @@ class LoaderActionsModel:
for repre_doc in repre_docs:
version_id = repre_doc["parent"]
version_doc = version_docs_by_id[version_id]
product_id = version_doc["parent"]
version_entity = version_entities_by_id[version_id]
product_id = version_entity["productId"]
product_entity = product_entities_by_id[product_id]
folder_id = product_entity["folderId"]
folder_entity = folder_entities_by_id[folder_id]
@ -553,7 +521,7 @@ class LoaderActionsModel:
"project": project_entity,
"folder": folder_entity,
"product": product_entity,
"version": version_doc,
"version": version_entity,
"representation": repre_doc,
}
return product_context_by_id, repre_context_by_id
@ -667,8 +635,10 @@ class LoaderActionsModel:
project_entity = ayon_api.get_project(project_name)
version_docs = self._get_version_docs(project_name, version_ids)
product_ids = {v["parent"] for v in version_docs}
version_entities = list(ayon_api.get_versions(
project_name, version_ids=version_ids
))
product_ids = {v["productId"] for v in version_entities}
product_entities = ayon_api.get_products(
project_name, product_ids=product_ids
)
@ -679,8 +649,8 @@ class LoaderActionsModel:
)
folder_entities_by_id = {f["id"]: f for f in folder_entities}
product_contexts = []
for version_doc in version_docs:
product_id = version_doc["parent"]
for version_entity in version_entities:
product_id = version_entity["productId"]
product_entity = product_entities_by_id[product_id]
folder_id = product_entity["folderId"]
folder_entity = folder_entities_by_id[folder_id]
@ -688,7 +658,7 @@ class LoaderActionsModel:
"project": project_entity,
"folder": folder_entity,
"product": product_entity,
"version": version_doc,
"version": version_entity,
})
return self._load_products_by_loader(
@ -706,7 +676,7 @@ class LoaderActionsModel:
This triggers 'load' method of 'LoaderPlugin' for given representation
ids. For that are prepared contexts for each representation, with
all parent documents.
all parent entities.
Args:
loader (LoaderPlugin): Loader plugin to use.
@ -720,9 +690,13 @@ class LoaderActionsModel:
project_name, representation_ids=representation_ids
))
version_ids = {r["parent"] for r in repre_docs}
version_docs = self._get_version_docs(project_name, version_ids)
version_docs_by_id = {v["_id"]: v for v in version_docs}
product_ids = {v["parent"] for v in version_docs_by_id.values()}
version_entities = ayon_api.get_versions(
project_name, version_ids=version_ids
)
version_entities_by_id = {v["id"]: v for v in version_entities}
product_ids = {
v["productId"] for v in version_entities_by_id.values()
}
product_entities = ayon_api.get_products(
project_name, product_ids=product_ids
)
@ -735,8 +709,8 @@ class LoaderActionsModel:
repre_contexts = []
for repre_doc in repre_docs:
version_id = repre_doc["parent"]
version_doc = version_docs_by_id[version_id]
product_id = version_doc["parent"]
version_entity = version_entities_by_id[version_id]
product_id = version_entity["productId"]
product_entity = product_entities_by_id[product_id]
folder_id = product_entity["folderId"]
folder_entity = folder_entities_by_id[folder_id]
@ -744,7 +718,7 @@ class LoaderActionsModel:
"project": project_entity,
"folder": folder_entity,
"product": product_entity,
"version": version_doc,
"version": version_entity,
"representation": repre_doc,
})
@ -758,18 +732,17 @@ class LoaderActionsModel:
Args:
loader (LoaderPlugin): Loader plugin to use.
repre_contexts (list[dict]): Full info about selected
representations, containing repre, version, product, folder and
project documents.
representations, containing repre, version, product, folder
and project entities.
options (dict): Data from options.
"""
error_info = []
for repre_context in repre_contexts:
version_doc = repre_context["version"]
if version_doc["type"] == "hero_version":
version_name = "Hero"
else:
version_name = version_doc.get("name")
version_entity = repre_context["version"]
version = version_entity["version"]
if version < 0:
version = "Hero"
try:
load_with_repre_context(
loader,
@ -784,7 +757,7 @@ class LoaderActionsModel:
None,
repre_context["representation"]["name"],
repre_context["product"]["name"],
version_name
version
))
except Exception as exc:
@ -800,7 +773,7 @@ class LoaderActionsModel:
formatted_traceback,
repre_context["representation"]["name"],
repre_context["product"]["name"],
version_name
version
))
return error_info

View file

@ -1,8 +1,10 @@
import collections
from ayon_core.lib import Logger
from ayon_core.client.entities import get_representations
from ayon_core.client import get_linked_representation_id
from ayon_core.client import (
get_representations,
get_linked_representation_id,
)
from ayon_core.addon import AddonsManager
from ayon_core.tools.ayon_utils.models import NestedCacheItem
from ayon_core.tools.loader.abstract import ActionItem

View file

@ -50,9 +50,7 @@ class VersionComboBox(QtWidgets.QComboBox):
item = self._items_by_id.get(version_id)
if item is None:
label = format_version(
abs(version_item.version), version_item.is_hero
)
label = format_version(version_item.version)
item = QtGui.QStandardItem(label)
item.setData(version_id, QtCore.Qt.UserRole)
self._items_by_id[version_id] = item
@ -85,7 +83,7 @@ class VersionDelegate(QtWidgets.QStyledItemDelegate):
def displayText(self, value, locale):
if not isinstance(value, numbers.Integral):
return "N/A"
return format_version(abs(value), value < 0)
return format_version(value)
def paint(self, painter, option, index):
fg_color = index.data(QtCore.Qt.ForegroundRole)

View file

@ -2,10 +2,7 @@ import threading
import ayon_api
from ayon_core.client import (
get_version_by_id,
get_representations,
)
from ayon_core.client import get_representations
from ayon_core.settings import get_project_settings
from ayon_core.lib import prepare_template_data
from ayon_core.lib.events import QueuedEventSystem
@ -35,7 +32,7 @@ class PushToContextController:
self._src_folder_entity = None
self._src_folder_task_entities = {}
self._src_product_entity = None
self._src_version_doc = None
self._src_version_entity = None
self._src_label = None
self._submission_enabled = False
@ -75,13 +72,15 @@ class PushToContextController:
folder_entity = None
task_entities = {}
product_entity = None
version_doc = None
version_entity = None
if project_name and version_id:
version_doc = get_version_by_id(project_name, version_id)
version_entity = ayon_api.get_version_by_id(
project_name, version_id
)
if version_doc:
if version_entity:
product_entity = ayon_api.get_product_by_id(
project_name, version_doc["parent"]
project_name, version_entity["productId"]
)
if product_entity:
@ -100,14 +99,14 @@ class PushToContextController:
self._src_folder_entity = folder_entity
self._src_folder_task_entities = task_entities
self._src_product_entity = product_entity
self._src_version_doc = version_doc
self._src_version_entity = version_entity
if folder_entity:
self._user_values.set_new_folder_name(folder_entity["name"])
variant = self._get_src_variant()
if variant:
self._user_values.set_variant(variant)
comment = version_doc["data"].get("comment")
comment = version_entity["attrib"].get("comment")
if comment:
self._user_values.set_comment(comment)
@ -218,12 +217,12 @@ class PushToContextController:
folder_path = folder_entity["path"]
product_entity = self._src_product_entity
version_doc = self._src_version_doc
version_entity = self._src_version_entity
return "Source: {}{}/{}/v{:0>3}".format(
self._src_project_name,
folder_path,
product_entity["name"],
version_doc["name"]
version_entity["version"]
)
def _get_task_info_from_repre_docs(self, task_entities, repre_docs):
@ -256,10 +255,10 @@ class PushToContextController:
def _get_src_variant(self):
project_name = self._src_project_name
version_doc = self._src_version_doc
version_entity = self._src_version_entity
task_entities = self._src_folder_task_entities
repre_docs = get_representations(
project_name, version_ids=[version_doc["_id"]]
project_name, version_ids=[version_entity["id"]]
)
task_name, task_type = self._get_task_info_from_repre_docs(
task_entities, repre_docs

View file

@ -1,7 +1,6 @@
import os
import re
import copy
import socket
import itertools
import datetime
import sys
@ -10,24 +9,15 @@ import uuid
import ayon_api
from ayon_core.client import (
get_version_by_id,
get_last_version_by_subset_id,
get_version_by_name,
get_representations,
)
from ayon_core.client import get_representations
from ayon_core.client.operations import (
OperationsSession,
new_version_doc,
new_representation_doc,
prepare_version_update_data,
prepare_representation_update_data,
)
from ayon_core.addon import AddonsManager
from ayon_core.lib import (
StringTemplate,
get_ayon_username,
get_formatted_current_time,
source_hash,
)
@ -445,7 +435,7 @@ class ProjectPushItemProcess:
self._src_folder_entity = None
self._src_product_entity = None
self._src_version_doc = None
self._src_version_entity = None
self._src_repre_items = None
self._project_entity = None
@ -453,7 +443,7 @@ class ProjectPushItemProcess:
self._folder_entity = None
self._task_info = None
self._product_entity = None
self._version_doc = None
self._version_entity = None
self._product_type = None
self._product_name = None
@ -570,16 +560,20 @@ class ProjectPushItemProcess:
self._log_debug(f"Project '{src_project_name}' found")
version_doc = get_version_by_id(src_project_name, src_version_id)
if not version_doc:
version_entity = ayon_api.get_version_by_id(
src_project_name, src_version_id
)
if not version_entity:
self._status.set_failed((
f"Source version with id \"{src_version_id}\""
f" was not found in project \"{src_project_name}\""
))
raise PushToProjectError(self._status.fail_reason)
product_id = version_doc["parent"]
product_entity = ayon_api.get_product_by_id(src_project_name, product_id)
product_id = version_entity["productId"]
product_entity = ayon_api.get_product_by_id(
src_project_name, product_id
)
if not product_entity:
self._status.set_failed((
f"Could find product with id \"{product_id}\""
@ -621,7 +615,7 @@ class ProjectPushItemProcess:
self._src_folder_entity = folder_entity
self._src_product_entity = product_entity
self._src_version_doc = version_doc
self._src_version_entity = version_entity
self._src_repre_items = repre_items
def _fill_destination_project(self):
@ -882,27 +876,42 @@ class ProjectPushItemProcess:
project_name = self._item.dst_project_name
version = self._item.dst_version
src_version_doc = self._src_version_doc
src_version_entity = self._src_version_entity
product_entity = self._product_entity
product_id = product_entity["id"]
src_data = src_version_doc["data"]
product_type = product_entity["productType"]
src_attrib = src_version_entity["attrib"]
dst_attrib = {}
for key in {
"productType",
"productTypes",
"families",
"fps",
"pixelAspect",
"clipIn",
"clipOut",
"frameStart",
"frameEnd",
"handleStart",
"handleEnd",
"resolutionWidth",
"resolutionHeight",
"colorSpace",
"source",
"comment",
"description",
"intent",
}:
if key in src_attrib:
dst_attrib[key] = src_attrib[key]
version_data = {
"families": [product_type],
"fps": src_data.get("fps"),
"source": src_data.get("source"),
"machine": socket.gethostname(),
"comment": self._item.comment or "",
"author": get_ayon_username(),
"time": get_formatted_current_time(),
}
if version is None:
last_version_doc = get_last_version_by_subset_id(
last_version_entity = ayon_api.get_last_version_by_product_id(
project_name, product_id
)
if last_version_doc:
version = int(last_version_doc["name"]) + 1
if last_version_entity:
version = int(last_version_entity["version"]) + 1
else:
version = get_versioning_start(
project_name,
@ -913,34 +922,50 @@ class ProjectPushItemProcess:
product_name=product_entity["name"]
)
existing_version_doc = get_version_by_name(
existing_version_entity = ayon_api.get_version_by_name(
project_name, version, product_id
)
# Update existing version
if existing_version_doc:
version_doc = new_version_doc(
version, product_id, version_data, existing_version_doc["_id"]
if existing_version_entity:
ayon_api.patch(
"projects/{}/versions/{}".format(
project_name, existing_version_entity["id"]
),
**{"attrib": dst_attrib}
)
update_data = prepare_version_update_data(
existing_version_doc, version_doc
version_entity = ayon_api.get_version_by_id(
project_name, existing_version_entity["id"]
)
if update_data:
self._operations.update_entity(
project_name,
"version",
existing_version_doc["_id"],
update_data
)
self._version_doc = version_doc
# TODO use operations
# self._operations.update_entity(
# project_name,
# "version",
# existing_version_entity["id"],
# update_data
# )
self._version_entity = version_entity
return
version_doc = new_version_doc(
version, product_id, version_data
response = ayon_api.post(
"projects/{}/versions/{}".format(
project_name, existing_version_entity["id"]
),
**{
"version": version,
"productId": product_id,
"attrib": dst_attrib,
}
)
self._operations.create_entity(project_name, "version", version_doc)
version_entity = ayon_api.get_version_by_id(
project_name, response.data["id"]
)
# TODO use operations
# self._operations.create_entity(
# project_name, "version", version_entity
# )
self._version_doc = version_doc
self._version_entity = version_entity
def _integrate_representations(self):
try:
@ -951,8 +976,8 @@ class ProjectPushItemProcess:
raise
def _real_integrate_representations(self):
version_doc = self._version_doc
version_id = version_doc["_id"]
version_entity = self._version_entity
version_id = version_entity["id"]
existing_repres = get_representations(
self._item.dst_project_name,
version_ids=[version_id]
@ -976,7 +1001,7 @@ class ProjectPushItemProcess:
"name": self._product_name,
"type": self._product_type,
},
"version": version_doc["name"]
"version": version_entity["version"]
})
path_template = anatomy.templates[template_name]["path"].replace(

View file

@ -120,12 +120,12 @@ def paint_image_with_color(image, color):
return pixmap
def format_version(value, hero_version=False):
def format_version(value):
"""Formats integer to displayable version name"""
label = "v{0:03d}".format(value)
if not hero_version:
return label
return "[{}]".format(label)
label = "v{0:03d}".format(abs(value))
if value < 0:
return "[{}]".format(label)
return label
@contextlib.contextmanager