diff --git a/openpype/client/mongo/entities.py b/openpype/client/mongo/entities.py
index adbdd7a47c..260fde4594 100644
--- a/openpype/client/mongo/entities.py
+++ b/openpype/client/mongo/entities.py
@@ -1468,7 +1468,9 @@ def get_thumbnails(project_name, thumbnail_ids, fields=None):
return conn.find(query_filter, _prepare_fields(fields))
-def get_thumbnail(project_name, thumbnail_id, fields=None):
+def get_thumbnail(
+ project_name, thumbnail_id, entity_type, entity_id, fields=None
+):
"""Receive thumbnail entity data.
Args:
diff --git a/openpype/client/server/constants.py b/openpype/client/server/constants.py
index 7ff990dc60..1d3f94c702 100644
--- a/openpype/client/server/constants.py
+++ b/openpype/client/server/constants.py
@@ -1,13 +1,3 @@
-# --- Project ---
-DEFAULT_PROJECT_FIELDS = {
- "active",
- "name",
- "code",
- "config",
- "data",
- "createdAt",
-}
-
# --- Folders ---
DEFAULT_FOLDER_FIELDS = {
"id",
@@ -19,47 +9,6 @@ DEFAULT_FOLDER_FIELDS = {
"thumbnailId"
}
-# --- Tasks ---
-DEFAULT_TASK_FIELDS = {
- "id",
- "name",
- "taskType",
- "assignees",
-}
-
-# --- Subsets ---
-DEFAULT_SUBSET_FIELDS = {
- "id",
- "name",
- "active",
- "family",
- "folderId",
-}
-
-# --- Versions ---
-DEFAULT_VERSION_FIELDS = {
- "id",
- "name",
- "version",
- "active",
- "subsetId",
- "taskId",
- "author",
- "thumbnailId",
- "createdAt",
- "updatedAt",
-}
-
-# --- Representations ---
-DEFAULT_REPRESENTATION_FIELDS = {
- "id",
- "name",
- "context",
- "createdAt",
- "active",
- "versionId",
-}
-
REPRESENTATION_FILES_FIELDS = {
"files.name",
"files.hash",
@@ -67,17 +16,3 @@ REPRESENTATION_FILES_FIELDS = {
"files.path",
"files.size",
}
-
-DEFAULT_WORKFILE_INFO_FIELDS = {
- "active",
- "createdAt",
- "createdBy",
- "id",
- "name",
- "path",
- "projectName",
- "taskId",
- "thumbnailId",
- "updatedAt",
- "updatedBy",
-}
diff --git a/openpype/client/server/conversion_utils.py b/openpype/client/server/conversion_utils.py
index 54b89275fe..b5bd755470 100644
--- a/openpype/client/server/conversion_utils.py
+++ b/openpype/client/server/conversion_utils.py
@@ -56,7 +56,7 @@ SUBSET_FIELDS_MAPPING_V3_V4 = {
VERSION_FIELDS_MAPPING_V3_V4 = {
"_id": {"id"},
"name": {"version"},
- "parent": {"subsetId"}
+ "parent": {"productId"}
}
# --- Representation entity ---
@@ -130,10 +130,21 @@ def _get_default_template_name(templates):
return default_template
+def _template_replacements_to_v3(template):
+ return (
+ template
+ .replace("{folder[name]}", "{asset}")
+ .replace("{product[name]}", "{subset}")
+ .replace("{product[type]}", "{family}")
+ )
+
+
def _convert_template_item(template):
- template["folder"] = template.pop("directory")
+ folder = _template_replacements_to_v3(template.pop("directory"))
+ template["folder"] = folder
+ template["file"] = _template_replacements_to_v3(template["file"])
template["path"] = "/".join(
- (template["folder"], template["file"])
+ (folder, template["file"])
)
@@ -384,7 +395,7 @@ def subset_fields_v3_to_v4(fields, con):
if not fields:
return None
- subset_attributes = con.get_attributes_for_type("subset")
+ product_attributes = con.get_attributes_for_type("product")
output = set()
for field in fields:
@@ -395,11 +406,11 @@ def subset_fields_v3_to_v4(fields, con):
output |= SUBSET_FIELDS_MAPPING_V3_V4[field]
elif field == "data":
- output.add("family")
+ output.add("productType")
output.add("active")
output |= {
"attrib.{}".format(attr)
- for attr in subset_attributes
+ for attr in product_attributes
}
elif field.startswith("data"):
@@ -407,9 +418,9 @@ def subset_fields_v3_to_v4(fields, con):
field_parts.pop(0)
data_key = ".".join(field_parts)
if data_key in ("family", "families"):
- output.add("family")
+ output.add("productType")
- elif data_key in subset_attributes:
+ elif data_key in product_attributes:
output.add("attrib.{}".format(data_key))
else:
@@ -443,9 +454,11 @@ def convert_v4_subset_to_v3(subset):
if "attrib" in subset:
attrib = subset["attrib"]
+ if "productGroup" in attrib:
+ attrib["subsetGroup"] = attrib.pop("productGroup")
output_data.update(attrib)
- family = subset.get("family")
+ family = subset.get("productType")
if family:
output_data["family"] = family
output_data["families"] = [family]
@@ -537,8 +550,8 @@ def convert_v4_version_to_v3(version):
"type": "hero_version",
"schema": CURRENT_HERO_VERSION_SCHEMA,
}
- if "subsetId" in version:
- output["parent"] = version["subsetId"]
+ if "productId" in version:
+ output["parent"] = version["productId"]
if "data" in version:
output["data"] = version["data"]
@@ -550,8 +563,8 @@ def convert_v4_version_to_v3(version):
"name": version_num,
"schema": CURRENT_VERSION_SCHEMA
}
- if "subsetId" in version:
- output["parent"] = version["subsetId"]
+ if "productId" in version:
+ output["parent"] = version["productId"]
output_data = version.get("data") or {}
if "attrib" in version:
@@ -647,6 +660,16 @@ def convert_v4_representation_to_v3(representation):
context = representation["context"]
if isinstance(context, six.string_types):
context = json.loads(context)
+
+ if "folder" in context:
+ _c_folder = context.pop("folder")
+ context["asset"] = _c_folder["name"]
+
+ if "product" in context:
+ _c_product = context.pop("product")
+ context["family"] = _c_product["type"]
+ context["subset"] = _c_product["name"]
+
output["context"] = context
if "files" in representation:
@@ -686,6 +709,14 @@ def convert_v4_representation_to_v3(representation):
if key in representation:
output_data[data_key] = representation[key]
+ if "template" in output_data:
+ output_data["template"] = (
+ output_data["template"]
+ .replace("{folder[name]}", "{asset}")
+ .replace("{product[name]}", "{subset}")
+ .replace("{product[type]}", "{family}")
+ )
+
output["data"] = output_data
return output
@@ -714,7 +745,7 @@ def workfile_info_fields_v3_to_v4(fields):
def convert_v4_workfile_info_to_v3(workfile_info, task):
output = {
- "type": "representation",
+ "type": "workfile",
"schema": CURRENT_WORKFILE_INFO_SCHEMA,
}
if "id" in workfile_info:
@@ -790,44 +821,46 @@ def convert_create_task_to_v4(task, project, con):
def convert_create_subset_to_v4(subset, con):
- subset_attributes = con.get_attributes_for_type("subset")
+ product_attributes = con.get_attributes_for_type("product")
subset_data = subset["data"]
- family = subset_data.get("family")
- if not family:
- family = subset_data["families"][0]
+ product_type = subset_data.get("family")
+ if not product_type:
+ product_type = subset_data["families"][0]
- converted_subset = {
+ converted_product = {
"name": subset["name"],
- "family": family,
+ "productType": product_type,
"folderId": subset["parent"],
}
entity_id = subset.get("_id")
if entity_id:
- converted_subset["id"] = entity_id
+ converted_product["id"] = entity_id
attribs = {}
data = {}
+ if "subsetGroup" in subset_data:
+ subset_data["productGroup"] = subset_data.pop("subsetGroup")
for key, value in subset_data.items():
- if key not in subset_attributes:
+ if key not in product_attributes:
data[key] = value
elif value is not None:
attribs[key] = value
if attribs:
- converted_subset["attrib"] = attribs
+ converted_product["attrib"] = attribs
if data:
- converted_subset["data"] = data
+ converted_product["data"] = data
- return converted_subset
+ return converted_product
def convert_create_version_to_v4(version, con):
version_attributes = con.get_attributes_for_type("version")
converted_version = {
"version": version["name"],
- "subsetId": version["parent"],
+ "productId": version["parent"],
}
entity_id = version.get("_id")
if entity_id:
@@ -870,7 +903,7 @@ def convert_create_hero_version_to_v4(hero_version, project_name, con):
version_attributes = con.get_attributes_for_type("version")
converted_version = {
"version": hero_version["version"],
- "subsetId": hero_version["parent"],
+ "productId": hero_version["parent"],
}
entity_id = hero_version.get("_id")
if entity_id:
@@ -923,12 +956,28 @@ def convert_create_representation_to_v4(representation, con):
new_files.append(new_file_item)
converted_representation["files"] = new_files
+
+ context = representation["context"]
+ context["folder"] = {
+ "name": context.pop("asset", None)
+ }
+ context["product"] = {
+ "type": context.pop("family", None),
+ "name": context.pop("subset", None),
+ }
+
attribs = {}
data = {
- "context": representation["context"],
+ "context": context,
}
representation_data = representation["data"]
+ representation_data["template"] = (
+ representation_data["template"]
+ .replace("{asset}", "{folder[name]}")
+ .replace("{subset}", "{product[name]}")
+ .replace("{family}", "{product[type]}")
+ )
for key, value in representation_data.items():
if key not in representation_attributes:
@@ -1073,7 +1122,7 @@ def convert_update_folder_to_v4(project_name, asset_id, update_data, con):
def convert_update_subset_to_v4(project_name, subset_id, update_data, con):
new_update_data = {}
- subset_attributes = con.get_attributes_for_type("subset")
+ product_attributes = con.get_attributes_for_type("product")
full_update_data = _from_flat_dict(update_data)
data = full_update_data.get("data")
new_data = {}
@@ -1081,15 +1130,17 @@ def convert_update_subset_to_v4(project_name, subset_id, update_data, con):
if data:
if "family" in data:
family = data.pop("family")
- new_update_data["family"] = family
+ new_update_data["productType"] = family
if "families" in data:
families = data.pop("families")
- if "family" not in new_update_data:
- new_update_data["family"] = families[0]
+ if "productType" not in new_update_data:
+ new_update_data["productType"] = families[0]
+ if "subsetGroup" in data:
+ data["productGroup"] = data.pop("subsetGroup")
for key, value in data.items():
- if key in subset_attributes:
+ if key in product_attributes:
if value is REMOVED_VALUE:
value = None
attribs[key] = value
@@ -1159,7 +1210,7 @@ def convert_update_version_to_v4(project_name, version_id, update_data, con):
new_update_data["active"] = False
if "parent" in update_data:
- new_update_data["subsetId"] = update_data["parent"]
+ new_update_data["productId"] = update_data["parent"]
flat_data = _to_flat_dict(new_update_data)
if new_data:
@@ -1209,6 +1260,14 @@ def convert_update_representation_to_v4(
else:
new_data[key] = value
+ if "template" in attribs:
+ attribs["template"] = (
+ attribs["template"]
+ .replace("{asset}", "{folder[name]}")
+ .replace("{family}", "{product[type]}")
+ .replace("{subset}", "{product[name]}")
+ )
+
if "name" in update_data:
new_update_data["name"] = update_data["name"]
@@ -1223,7 +1282,16 @@ def convert_update_representation_to_v4(
new_update_data["versionId"] = update_data["parent"]
if "context" in update_data:
- new_data["context"] = update_data["context"]
+ context = update_data["context"]
+ if "asset" in context:
+ context["folder"] = {"name": context.pop("asset")}
+
+ if "family" in context or "subset" in context:
+ context["product"] = {
+ "name": context.pop("subset"),
+ "type": context.pop("family"),
+ }
+ new_data["context"] = context
if "files" in update_data:
new_files = update_data["files"]
diff --git a/openpype/client/server/entities.py b/openpype/client/server/entities.py
index 2a2662b327..fee503297b 100644
--- a/openpype/client/server/entities.py
+++ b/openpype/client/server/entities.py
@@ -79,7 +79,7 @@ def _get_subsets(
if archived:
active = False
- for subset in con.get_subsets(
+ for subset in con.get_products(
project_name,
subset_ids,
subset_names,
@@ -105,11 +105,11 @@ def _get_versions(
fields = version_fields_v3_to_v4(fields, con)
- # Make sure 'subsetId' and 'version' are available when hero versions
+ # Make sure 'productId' and 'version' are available when hero versions
# are queried
if fields and hero:
fields = set(fields)
- fields |= {"subsetId", "version"}
+ fields |= {"productId", "version"}
queried_versions = con.get_versions(
project_name,
@@ -135,22 +135,22 @@ def _get_versions(
versions_nums = set()
for hero_version in hero_versions:
versions_nums.add(abs(hero_version["version"]))
- subset_ids.add(hero_version["subsetId"])
+ subset_ids.add(hero_version["productId"])
hero_eq_versions = con.get_versions(
project_name,
- subset_ids=subset_ids,
+ product_ids=subset_ids,
versions=versions_nums,
hero=False,
- fields=["id", "version", "subsetId"]
+ fields=["id", "version", "productId"]
)
hero_eq_by_subset_id = collections.defaultdict(list)
for version in hero_eq_versions:
- hero_eq_by_subset_id[version["subsetId"]].append(version)
+ hero_eq_by_subset_id[version["productId"]].append(version)
for hero_version in hero_versions:
abs_version = abs(hero_version["version"])
- subset_id = hero_version["subsetId"]
+ subset_id = hero_version["productId"]
version_id = None
for version in hero_eq_by_subset_id.get(subset_id, []):
if version["version"] == abs_version:
@@ -235,7 +235,7 @@ def get_archived_assets(
def get_asset_ids_with_subsets(project_name, asset_ids=None):
con = get_server_api_connection()
- return con.get_asset_ids_with_subsets(project_name, asset_ids)
+ return con.get_folder_ids_with_products(project_name, asset_ids)
def get_subset_by_id(project_name, subset_id, fields=None):
@@ -281,7 +281,7 @@ def get_subsets(
def get_subset_families(project_name, subset_ids=None):
con = get_server_api_connection()
- return con.get_subset_families(project_name, subset_ids)
+ return con.get_product_type_names(project_name, subset_ids)
def get_version_by_id(project_name, version_id, fields=None):
@@ -618,6 +618,14 @@ def get_thumbnail(
def get_thumbnails(project_name, thumbnail_contexts, fields=None):
+ """Get thumbnail entities.
+
+ Warning:
+ This function is not OpenPype compatible. There is none usage of this
+ function in codebase so there is nothing to convert. The previous
+ implementation cannot be AYON compatible without entity types.
+ """
+
thumbnail_items = set()
for thumbnail_context in thumbnail_contexts:
thumbnail_id, entity_type, entity_id = thumbnail_context
diff --git a/openpype/client/server/openpype_comp.py b/openpype/client/server/openpype_comp.py
index df3ffcc0d3..a123fe3167 100644
--- a/openpype/client/server/openpype_comp.py
+++ b/openpype/client/server/openpype_comp.py
@@ -11,7 +11,7 @@ def folders_tasks_graphql_query(fields):
parent_folder_ids_var = query.add_variable("parentFolderIds", "[String!]")
folder_paths_var = query.add_variable("folderPaths", "[String!]")
folder_names_var = query.add_variable("folderNames", "[String!]")
- has_subsets_var = query.add_variable("folderHasSubsets", "Boolean!")
+ has_products_var = query.add_variable("folderHasProducts", "Boolean!")
project_field = query.add_field("project")
project_field.set_filter("name", project_name_var)
@@ -21,7 +21,7 @@ def folders_tasks_graphql_query(fields):
folders_field.set_filter("parentIds", parent_folder_ids_var)
folders_field.set_filter("names", folder_names_var)
folders_field.set_filter("paths", folder_paths_var)
- folders_field.set_filter("hasSubsets", has_subsets_var)
+ folders_field.set_filter("hasProducts", has_products_var)
fields = set(fields)
fields.discard("tasks")
diff --git a/openpype/client/server/operations.py b/openpype/client/server/operations.py
index e5254ee7b7..eeb55784e1 100644
--- a/openpype/client/server/operations.py
+++ b/openpype/client/server/operations.py
@@ -375,7 +375,18 @@ def prepare_representation_update_data(old_doc, new_doc, replace=True):
Dict[str, Any]: Changes between old and new document.
"""
- return _prepare_update_data(old_doc, new_doc, replace)
+ changes = _prepare_update_data(old_doc, new_doc, replace)
+ context = changes.get("data", {}).get("context")
+ # Make sure that both 'family' and 'subset' are in changes if
+ # one of them changed (they'll both become 'product').
+ if (
+ context
+ and ("family" in context or "subset" in context)
+ ):
+ context["family"] = new_doc["data"]["context"]["family"]
+ context["subset"] = new_doc["data"]["context"]["subset"]
+
+ return changes
def prepare_workfile_info_update_data(old_doc, new_doc, replace=True):
@@ -445,6 +456,7 @@ class ServerCreateOperation(CreateOperation):
elif entity_type == "subset":
new_data = convert_create_subset_to_v4(data, self.con)
+ entity_type = "product"
elif entity_type == "version":
new_data = convert_create_version_to_v4(data, self.con)
@@ -551,6 +563,7 @@ class ServerUpdateOperation(UpdateOperation):
new_update_data = convert_update_subset_to_v4(
project_name, entity_id, update_data, self.con
)
+ entity_type = "product"
elif entity_type == "version":
new_update_data = convert_update_version_to_v4(
@@ -636,9 +649,12 @@ class ServerDeleteOperation(DeleteOperation):
if entity_type == "asset":
entity_type == "folder"
- if entity_type == "hero_version":
+ elif entity_type == "hero_version":
entity_type = "version"
+ elif entity_type == "subset":
+ entity_type = "product"
+
super(ServerDeleteOperation, self).__init__(
project_name, entity_type, entity_id
)
diff --git a/openpype/plugins/publish/integrate_inputlinks.py b/openpype/plugins/publish/integrate_inputlinks.py
index c639bbf994..3baa462a81 100644
--- a/openpype/plugins/publish/integrate_inputlinks.py
+++ b/openpype/plugins/publish/integrate_inputlinks.py
@@ -36,10 +36,6 @@ class IntegrateInputLinks(pyblish.api.ContextPlugin):
"""
- if AYON_SERVER_ENABLED:
- self.log.info("Skipping, in AYON mode")
- return
-
workfile = None
publishing = []
@@ -139,3 +135,7 @@ class IntegrateInputLinks(pyblish.api.ContextPlugin):
{"_id": version_doc["_id"]},
{"$set": {"data.inputLinks": input_links}}
)
+
+
+if AYON_SERVER_ENABLED:
+ del IntegrateInputLinks
diff --git a/openpype/plugins/publish/integrate_inputlinks_ayon.py b/openpype/plugins/publish/integrate_inputlinks_ayon.py
index 8ab5c923c4..180524cd08 100644
--- a/openpype/plugins/publish/integrate_inputlinks_ayon.py
+++ b/openpype/plugins/publish/integrate_inputlinks_ayon.py
@@ -32,10 +32,6 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
specific publish plugin.
"""
- if not AYON_SERVER_ENABLED:
- self.log.info("Skipping, not in AYON mode")
- return
-
workfile_instance, other_instances = self.split_instances(context)
# Variable where links are stored in submethods
@@ -158,3 +154,7 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
output_id,
"version"
)
+
+
+if not AYON_SERVER_ENABLED:
+ del IntegrateInputLinksAYON
diff --git a/openpype/settings/ayon_settings.py b/openpype/settings/ayon_settings.py
index ae5f5ead4d..46ad77c7ca 100644
--- a/openpype/settings/ayon_settings.py
+++ b/openpype/settings/ayon_settings.py
@@ -351,18 +351,25 @@ def _convert_flame_project_settings(ayon_settings, output):
ayon_flame = ayon_settings["flame"]
ayon_publish_flame = ayon_flame["publish"]
+ # Plugin 'ExtractSubsetResources' renamed to 'ExtractProductResources'
+ if "ExtractSubsetResources" in ayon_publish_flame:
+ ayon_product_resources = ayon_publish_flame["ExtractSubsetResources"]
+ else:
+ ayon_product_resources = (
+ ayon_publish_flame.pop("ExtractProductResources"))
+ ayon_publish_flame["ExtractSubsetResources"] = ayon_product_resources
+
# 'ExtractSubsetResources' changed model of 'export_presets_mapping'
# - some keys were moved under 'other_parameters'
- ayon_subset_resources = ayon_publish_flame["ExtractSubsetResources"]
new_subset_resources = {}
- for item in ayon_subset_resources.pop("export_presets_mapping"):
+ for item in ayon_product_resources.pop("export_presets_mapping"):
name = item.pop("name")
if "other_parameters" in item:
other_parameters = item.pop("other_parameters")
item.update(other_parameters)
new_subset_resources[name] = item
- ayon_subset_resources["export_presets_mapping"] = new_subset_resources
+ ayon_product_resources["export_presets_mapping"] = new_subset_resources
# 'imageio' changed model
# - missing subkey 'project' which is in root of 'imageio' model
@@ -375,6 +382,21 @@ def _convert_flame_project_settings(ayon_settings, output):
"profilesMapping": profile_mapping
}
+ ayon_load_flame = ayon_flame["load"]
+ for plugin_name in ("LoadClip", "LoadClipBatch"):
+ plugin_settings = ayon_load_flame[plugin_name]
+ plugin_settings["families"] = plugin_settings.pop("product_types")
+ plugin_settings["clip_name_template"] = (
+ plugin_settings["clip_name_template"]
+ .replace("{folder[name]}", "{asset}")
+ .replace("{product[name]}", "{subset}")
+ )
+ plugin_settings["layer_rename_template"] = (
+ plugin_settings["layer_rename_template"]
+ .replace("{folder[name]}", "{asset}")
+ .replace("{product[name]}", "{subset}")
+ )
+
output["flame"] = ayon_flame
@@ -409,6 +431,15 @@ def _convert_fusion_project_settings(ayon_settings, output):
_convert_host_imageio(ayon_imageio_fusion)
+ ayon_create_saver = ayon_fusion["create"]["CreateSaver"]
+ ayon_create_saver["temp_rendering_path_template"] = (
+ ayon_create_saver["temp_rendering_path_template"]
+ .replace("{product[name]}", "{subset}")
+ .replace("{product[type]}", "{family}")
+ .replace("{folder[name]}", "{asset}")
+ .replace("{task[name]}", "{task}")
+ )
+
output["fusion"] = ayon_fusion
@@ -477,6 +508,11 @@ def _convert_maya_project_settings(ayon_settings, output):
SUFFIX_NAMING_TABLE
)
+ validate_frame_range = ayon_publish["ValidateFrameRange"]
+ if "exclude_product_types" in validate_frame_range:
+ validate_frame_range["exclude_families"] = (
+ validate_frame_range.pop("exclude_product_types"))
+
# Extract playblast capture settings
validate_rendern_settings = ayon_publish["ValidateRenderSettings"]
for key in (
@@ -537,12 +573,31 @@ def _convert_maya_project_settings(ayon_settings, output):
for item in renderer_settings["additional_options"]
]
+ # Workfile build
+ ayon_workfile_build = ayon_maya["workfile_build"]
+ for item in ayon_workfile_build["profiles"]:
+ for key in ("current_context", "linked_assets"):
+ for subitem in item[key]:
+ if "families" in subitem:
+ break
+ subitem["families"] = subitem.pop("product_types")
+ subitem["subset_name_filters"] = subitem.pop(
+ "product_name_filters")
+
_convert_host_imageio(ayon_maya)
- load_colors = ayon_maya["load"]["colors"]
+ ayon_maya_load = ayon_maya["load"]
+ load_colors = ayon_maya_load["colors"]
for key, color in tuple(load_colors.items()):
load_colors[key] = _convert_color(color)
+ reference_loader = ayon_maya_load["reference_loader"]
+ reference_loader["namespace"] = (
+ reference_loader["namespace"]
+ .replace("{folder[name]}", "{asset_name}")
+ .replace("{product[name]}", "{subset}")
+ )
+
output["maya"] = ayon_maya
@@ -630,13 +685,21 @@ def _convert_nuke_project_settings(ayon_settings, output):
"CreateWriteImage",
"CreateWriteRender",
):
+ create_plugin_settings = ayon_create[creator_name]
+ create_plugin_settings["temp_rendering_path_template"] = (
+ create_plugin_settings["temp_rendering_path_template"]
+ .replace("{product[name]}", "{subset}")
+ .replace("{product[type]}", "{family}")
+ .replace("{task[name]}", "{task}")
+ .replace("{folder[name]}", "{asset}")
+ )
new_prenodes = {}
- for prenode in ayon_create[creator_name]["prenodes"]:
+ for prenode in create_plugin_settings["prenodes"]:
name = prenode.pop("name")
prenode["knobs"] = _convert_nuke_knobs(prenode["knobs"])
new_prenodes[name] = prenode
- ayon_create[creator_name]["prenodes"] = new_prenodes
+ create_plugin_settings["prenodes"] = new_prenodes
# --- Publish ---
ayon_publish = ayon_nuke["publish"]
@@ -651,6 +714,11 @@ def _convert_nuke_project_settings(ayon_settings, output):
new_review_data_outputs = {}
for item in ayon_publish["ExtractReviewDataMov"]["outputs"]:
+ item_filter = item["filter"]
+ if "product_names" in item_filter:
+ item_filter["subsets"] = item_filter.pop("product_names")
+ item_filter["families"] = item_filter.pop("product_types")
+
item["reformat_node_config"] = _convert_nuke_knobs(
item["reformat_node_config"])
@@ -659,9 +727,14 @@ def _convert_nuke_project_settings(ayon_settings, output):
name = item.pop("name")
new_review_data_outputs[name] = item
-
ayon_publish["ExtractReviewDataMov"]["outputs"] = new_review_data_outputs
+ collect_instance_data = ayon_publish["CollectInstanceData"]
+ if "sync_workfile_version_on_product_types" in collect_instance_data:
+ collect_instance_data["sync_workfile_version_on_families"] = (
+ collect_instance_data.pop(
+ "sync_workfile_version_on_product_types"))
+
# TODO 'ExtractThumbnail' does not have ideal schema in v3
new_thumbnail_nodes = {}
for item in ayon_publish["ExtractThumbnail"]["nodes"]:
@@ -707,6 +780,17 @@ def _convert_hiero_project_settings(ayon_settings, output):
new_gui_filters[key] = subvalue
ayon_hiero["filters"] = new_gui_filters
+ ayon_load_clip = ayon_hiero["load"]["LoadClip"]
+ if "product_types" in ayon_load_clip:
+ ayon_load_clip["families"] = ayon_load_clip.pop("product_types")
+
+ ayon_load_clip = ayon_hiero["load"]["LoadClip"]
+ ayon_load_clip["clip_name_template"] = (
+ ayon_load_clip["clip_name_template"]
+ .replace("{folder[name]}", "{asset}")
+ .replace("{product[name]}", "{subset}")
+ )
+
output["hiero"] = ayon_hiero
@@ -717,7 +801,14 @@ def _convert_photoshop_project_settings(ayon_settings, output):
ayon_photoshop = ayon_settings["photoshop"]
_convert_host_imageio(ayon_photoshop)
- collect_review = ayon_photoshop["publish"]["CollectReview"]
+ ayon_publish_photoshop = ayon_photoshop["publish"]
+
+ ayon_colorcoded = ayon_publish_photoshop["CollectColorCodedInstances"]
+ if "flatten_product_type_template" in ayon_colorcoded:
+ ayon_colorcoded["flatten_subset_template"] = (
+ ayon_colorcoded.pop("flatten_product_type_template"))
+
+ collect_review = ayon_publish_photoshop["CollectReview"]
if "active" in collect_review:
collect_review["publish"] = collect_review.pop("active")
@@ -762,6 +853,14 @@ def _convert_tvpaint_project_settings(ayon_settings, output):
extract_sequence_setting["review_bg"]
)
+ # TODO remove when removed from OpenPype schema
+ # this is unused setting
+ ayon_tvpaint["publish"]["ExtractSequence"]["families_to_review"] = [
+ "review",
+ "renderlayer",
+ "renderscene"
+ ]
+
output["tvpaint"] = ayon_tvpaint
@@ -776,6 +875,13 @@ def _convert_traypublisher_project_settings(ayon_settings, output):
ayon_editorial_simple = (
ayon_traypublisher["editorial_creators"]["editorial_simple"]
)
+ # Subset -> Product type conversion
+ if "product_type_presets" in ayon_editorial_simple:
+ family_presets = ayon_editorial_simple.pop("product_type_presets")
+ for item in family_presets:
+ item["family"] = item.pop("product_type")
+ ayon_editorial_simple["family_presets"] = family_presets
+
if "shot_metadata_creator" in ayon_editorial_simple:
shot_metadata_creator = ayon_editorial_simple.pop(
"shot_metadata_creator"
@@ -798,6 +904,13 @@ def _convert_traypublisher_project_settings(ayon_settings, output):
for item in ayon_editorial_simple["shot_hierarchy"]["parents"]:
item["type"] = item.pop("parent_type")
+ # Simple creators
+ ayon_simple_creators = ayon_traypublisher["simple_creators"]
+ for item in ayon_simple_creators:
+ if "product_type" not in item:
+ break
+ item["family"] = item.pop("product_type")
+
shot_add_tasks = ayon_editorial_simple["shot_add_tasks"]
if isinstance(shot_add_tasks, dict):
shot_add_tasks = []
@@ -886,6 +999,13 @@ def _convert_kitsu_project_settings(ayon_settings, output):
ayon_kitsu_settings = ayon_settings["kitsu"]
ayon_kitsu_settings.pop("server")
+
+ integrate_note = ayon_kitsu_settings["publish"]["IntegrateKitsuNote"]
+ status_change_conditions = integrate_note["status_change_conditions"]
+ if "product_type_requirements" in status_change_conditions:
+ status_change_conditions["family_requirements"] = (
+ status_change_conditions.pop("product_type_requirements"))
+
output["kitsu"] = ayon_kitsu_settings
@@ -946,12 +1066,25 @@ def _convert_global_project_settings(ayon_settings, output, default_settings):
# Publish conversion
ayon_publish = ayon_core["publish"]
+
+ ayon_collect_audio = ayon_publish["CollectAudio"]
+ if "audio_product_name" in ayon_collect_audio:
+ ayon_collect_audio["audio_subset_name"] = (
+ ayon_collect_audio.pop("audio_product_name"))
+
for profile in ayon_publish["ExtractReview"]["profiles"]:
+ if "product_types" in profile:
+ profile["families"] = profile.pop("product_types")
new_outputs = {}
for output_def in profile.pop("outputs"):
name = output_def.pop("name")
new_outputs[name] = output_def
+ output_def_filter = output_def["filter"]
+ if "product_names" in output_def_filter:
+ output_def_filter["subsets"] = (
+ output_def_filter.pop("product_names"))
+
for color_key in ("overscan_color", "bg_color"):
output_def[color_key] = _convert_color(output_def[color_key])
@@ -967,6 +1100,7 @@ def _convert_global_project_settings(ayon_settings, output, default_settings):
profile["outputs"] = new_outputs
+ # Extract Burnin plugin
extract_burnin = ayon_publish["ExtractBurnin"]
extract_burnin_options = extract_burnin["options"]
for color_key in ("font_color", "bg_color"):
@@ -976,16 +1110,56 @@ def _convert_global_project_settings(ayon_settings, output, default_settings):
for profile in extract_burnin["profiles"]:
extract_burnin_defs = profile["burnins"]
+ if "product_names" in profile:
+ profile["subsets"] = profile.pop("product_names")
+ profile["families"] = profile.pop("product_types")
+
+ for burnin_def in extract_burnin_defs:
+ for key in (
+ "TOP_LEFT",
+ "TOP_CENTERED",
+ "TOP_RIGHT",
+ "BOTTOM_LEFT",
+ "BOTTOM_CENTERED",
+ "BOTTOM_RIGHT",
+ ):
+ burnin_def[key] = (
+ burnin_def[key]
+ .replace("{product[name]}", "{subset}")
+ .replace("{Product[name]}", "{Subset}")
+ .replace("{PRODUCT[NAME]}", "{SUBSET}")
+ .replace("{product[type]}", "{family}")
+ .replace("{Product[type]}", "{Family}")
+ .replace("{PRODUCT[TYPE]}", "{FAMILY}")
+ .replace("{folder[name]}", "{asset}")
+ .replace("{Folder[name]}", "{Asset}")
+ .replace("{FOLDER[NAME]}", "{ASSET}")
+ )
profile["burnins"] = {
extract_burnin_def.pop("name"): extract_burnin_def
for extract_burnin_def in extract_burnin_defs
}
+ ayon_integrate_hero = ayon_publish["IntegrateHeroVersion"]
+ for profile in ayon_integrate_hero["template_name_profiles"]:
+ if "product_types" not in profile:
+ break
+ profile["families"] = profile.pop("product_types")
+
+ if "IntegrateProductGroup" in ayon_publish:
+ subset_group = ayon_publish.pop("IntegrateProductGroup")
+ subset_group_profiles = subset_group.pop("product_grouping_profiles")
+ for profile in subset_group_profiles:
+ profile["families"] = profile.pop("product_types")
+ subset_group["subset_grouping_profiles"] = subset_group_profiles
+ ayon_publish["IntegrateSubsetGroup"] = subset_group
+
+ # Cleanup plugin
ayon_cleanup = ayon_publish["CleanUp"]
if "patterns" in ayon_cleanup:
ayon_cleanup["paterns"] = ayon_cleanup.pop("patterns")
- # Project root settings
+ # Project root settings - json string to dict
ayon_core["project_environments"] = json.loads(
ayon_core["project_environments"]
)
@@ -996,18 +1170,55 @@ def _convert_global_project_settings(ayon_settings, output, default_settings):
# Tools settings
ayon_tools = ayon_core["tools"]
ayon_create_tool = ayon_tools["creator"]
+ if "product_name_profiles" in ayon_create_tool:
+ product_name_profiles = ayon_create_tool.pop("product_name_profiles")
+ for profile in product_name_profiles:
+ profile["families"] = profile.pop("product_types")
+ ayon_create_tool["subset_name_profiles"] = product_name_profiles
+
+ for profile in ayon_create_tool["subset_name_profiles"]:
+ template = profile["template"]
+ profile["template"] = (
+ template
+ .replace("{task[name]}", "{task}")
+ .replace("{Task[name]}", "{Task}")
+ .replace("{TASK[NAME]}", "{TASK}")
+ .replace("{product[type]}", "{family}")
+ .replace("{Product[type]}", "{Family}")
+ .replace("{PRODUCT[TYPE]}", "{FAMILY}")
+ .replace("{folder[name]}", "{asset}")
+ .replace("{Folder[name]}", "{Asset}")
+ .replace("{FOLDER[NAME]}", "{ASSET}")
+ )
+
+ product_smart_select_key = "families_smart_select"
+ if "product_types_smart_select" in ayon_create_tool:
+ product_smart_select_key = "product_types_smart_select"
+
new_smart_select_families = {
item["name"]: item["task_names"]
- for item in ayon_create_tool["families_smart_select"]
+ for item in ayon_create_tool.pop(product_smart_select_key)
}
ayon_create_tool["families_smart_select"] = new_smart_select_families
ayon_loader_tool = ayon_tools["loader"]
- for profile in ayon_loader_tool["family_filter_profiles"]:
- if "template_publish_families" in profile:
- profile["filter_families"] = (
- profile.pop("template_publish_families")
- )
+ if "product_type_filter_profiles" in ayon_loader_tool:
+ product_type_filter_profiles = (
+ ayon_loader_tool.pop("product_type_filter_profiles"))
+ for profile in product_type_filter_profiles:
+ profile["filter_families"] = profile.pop("filter_product_types")
+
+ ayon_loader_tool["family_filter_profiles"] = (
+ product_type_filter_profiles)
+
+ ayon_publish_tool = ayon_tools["publish"]
+ for profile in ayon_publish_tool["hero_template_name_profiles"]:
+ if "product_types" in profile:
+ profile["families"] = profile.pop("product_types")
+
+ for profile in ayon_publish_tool["template_name_profiles"]:
+ if "product_types" in profile:
+ profile["families"] = profile.pop("product_types")
ayon_core["sync_server"] = (
default_settings["global"]["sync_server"]
diff --git a/openpype/settings/defaults/project_settings/global.json b/openpype/settings/defaults/project_settings/global.json
index 36e00858ed..b6eb2f52f1 100644
--- a/openpype/settings/defaults/project_settings/global.json
+++ b/openpype/settings/defaults/project_settings/global.json
@@ -53,7 +53,8 @@
},
"ValidateEditorialAssetName": {
"enabled": true,
- "optional": false
+ "optional": false,
+ "active": true
},
"ValidateVersion": {
"enabled": true,
@@ -300,71 +301,6 @@
}
]
},
- "IntegrateAssetNew": {
- "subset_grouping_profiles": [
- {
- "families": [],
- "hosts": [],
- "task_types": [],
- "tasks": [],
- "template": ""
- }
- ],
- "template_name_profiles": [
- {
- "families": [],
- "hosts": [],
- "task_types": [],
- "tasks": [],
- "template_name": "publish"
- },
- {
- "families": [
- "review",
- "render",
- "prerender"
- ],
- "hosts": [],
- "task_types": [],
- "tasks": [],
- "template_name": "render"
- },
- {
- "families": [
- "simpleUnrealTexture"
- ],
- "hosts": [
- "standalonepublisher"
- ],
- "task_types": [],
- "tasks": [],
- "template_name": "simpleUnrealTexture"
- },
- {
- "families": [
- "staticMesh",
- "skeletalMesh"
- ],
- "hosts": [
- "maya"
- ],
- "task_types": [],
- "tasks": [],
- "template_name": "maya2unreal"
- },
- {
- "families": [
- "online"
- ],
- "hosts": [
- "traypublisher"
- ],
- "task_types": [],
- "tasks": [],
- "template_name": "online"
- }
- ]
- },
"IntegrateHeroVersion": {
"enabled": true,
"optional": true,
diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json
index 1f4f468656..fdbd6d5d0f 100644
--- a/openpype/settings/defaults/project_settings/tvpaint.json
+++ b/openpype/settings/defaults/project_settings/tvpaint.json
@@ -60,11 +60,6 @@
255,
255,
255
- ],
- "families_to_review": [
- "review",
- "renderlayer",
- "renderscene"
]
},
"ValidateProjectSettings": {
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
index 45fc13bdde..e9255f426e 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
@@ -273,18 +273,6 @@
"key": "review_bg",
"label": "Review BG color",
"use_alpha": false
- },
- {
- "type": "enum",
- "key": "families_to_review",
- "label": "Families to review",
- "multiselection": true,
- "enum_items": [
- {"review": "review"},
- {"renderpass": "renderPass"},
- {"renderlayer": "renderLayer"},
- {"renderscene": "renderScene"}
- ]
}
]
},
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
index 81a13d9c57..c7e91fd22d 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json
@@ -118,6 +118,11 @@
"type": "boolean",
"key": "optional",
"label": "Optional"
+ },
+ {
+ "type": "boolean",
+ "key": "active",
+ "label": "Active"
}
]
},
@@ -888,111 +893,6 @@
}
]
},
- {
- "type": "dict",
- "collapsible": true,
- "key": "IntegrateAssetNew",
- "label": "IntegrateAsset (Legacy)",
- "is_group": true,
- "children": [
- {
- "type": "label",
- "label": "NOTE: Subset grouping profiles settings were moved to Integrate Subset Group. Please move values there."
- },
- {
- "type": "list",
- "key": "subset_grouping_profiles",
- "label": "Subset grouping profiles (DEPRECATED)",
- "use_label_wrap": true,
- "object_type": {
- "type": "dict",
- "children": [
- {
- "key": "families",
- "label": "Families",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "hosts-enum",
- "key": "hosts",
- "label": "Hosts",
- "multiselection": true
- },
- {
- "key": "task_types",
- "label": "Task types",
- "type": "task-types-enum"
- },
- {
- "key": "tasks",
- "label": "Task names",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "separator"
- },
- {
- "type": "text",
- "key": "template",
- "label": "Template"
- }
- ]
- }
- },
- {
- "type": "label",
- "label": "NOTE: Publish template profiles settings were moved to Tools/Publish/Template name profiles. Please move values there."
- },
- {
- "type": "list",
- "key": "template_name_profiles",
- "label": "Template name profiles (DEPRECATED)",
- "use_label_wrap": true,
- "object_type": {
- "type": "dict",
- "children": [
- {
- "type": "label",
- "label": ""
- },
- {
- "key": "families",
- "label": "Families",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "hosts-enum",
- "key": "hosts",
- "label": "Hosts",
- "multiselection": true
- },
- {
- "key": "task_types",
- "label": "Task types",
- "type": "task-types-enum"
- },
- {
- "key": "tasks",
- "label": "Task names",
- "type": "list",
- "object_type": "text"
- },
- {
- "type": "separator"
- },
- {
- "type": "text",
- "key": "template_name",
- "label": "Template name"
- }
- ]
- }
- }
- ]
- },
{
"type": "dict",
"collapsible": true,
diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json
index 85ec482e73..23fc7c9351 100644
--- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json
+++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json
@@ -320,10 +320,6 @@
"key": "publish",
"label": "Publish",
"children": [
- {
- "type": "label",
- "label": "NOTE: For backwards compatibility can be value empty and in that case are used values from IntegrateAssetNew. This will change in future so please move all values here as soon as possible."
- },
{
"type": "list",
"key": "template_name_profiles",
diff --git a/openpype/tools/creator/widgets.py b/openpype/tools/creator/widgets.py
index 74f75811ff..0ebbd905e5 100644
--- a/openpype/tools/creator/widgets.py
+++ b/openpype/tools/creator/widgets.py
@@ -5,6 +5,7 @@ from qtpy import QtWidgets, QtCore, QtGui
import qtawesome
+from openpype import AYON_SERVER_ENABLED
from openpype.pipeline.create import SUBSET_NAME_ALLOWED_SYMBOLS
from openpype.tools.utils import ErrorMessageBox
@@ -42,10 +43,13 @@ class CreateErrorMessageBox(ErrorMessageBox):
def _get_report_data(self):
report_message = (
- "Failed to create Subset: \"{subset}\" Family: \"{family}\""
+ "Failed to create {subset_label}: \"{subset}\""
+ " {family_label}: \"{family}\""
" in Asset: \"{asset}\""
"\n\nError: {message}"
).format(
+ subset_label="Product" if AYON_SERVER_ENABLED else "Subset",
+ family_label="Type" if AYON_SERVER_ENABLED else "Family",
subset=self._subset_name,
family=self._family,
asset=self._asset_name,
@@ -57,9 +61,13 @@ class CreateErrorMessageBox(ErrorMessageBox):
def _create_content(self, content_layout):
item_name_template = (
- "Family: {}
"
- "Subset: {}
"
- "Asset: {}
"
+ "{}: {{}}
"
+ "{}: {{}}
"
+ "{}: {{}}
"
+ ).format(
+ "Product type" if AYON_SERVER_ENABLED else "Family",
+ "Product name" if AYON_SERVER_ENABLED else "Subset",
+ "Folder" if AYON_SERVER_ENABLED else "Asset"
)
exc_msg_template = "{}"
@@ -151,15 +159,21 @@ class VariantLineEdit(QtWidgets.QLineEdit):
def as_empty(self):
self._set_border("empty")
- self.report.emit("Empty subset name ..")
+ self.report.emit("Empty {} name ..".format(
+ "product" if AYON_SERVER_ENABLED else "subset"
+ ))
def as_exists(self):
self._set_border("exists")
- self.report.emit("Existing subset, appending next version.")
+ self.report.emit("Existing {}, appending next version.".format(
+ "product" if AYON_SERVER_ENABLED else "subset"
+ ))
def as_new(self):
self._set_border("new")
- self.report.emit("New subset, creating first version.")
+ self.report.emit("New {}, creating first version.".format(
+ "product" if AYON_SERVER_ENABLED else "subset"
+ ))
def _set_border(self, status):
qcolor, style = self.colors[status]
diff --git a/openpype/tools/loader/app.py b/openpype/tools/loader/app.py
index 302fe6c366..b305233247 100644
--- a/openpype/tools/loader/app.py
+++ b/openpype/tools/loader/app.py
@@ -223,7 +223,7 @@ class LoaderWindow(QtWidgets.QDialog):
lib.schedule(self._refresh, 50, channel="mongo")
def on_assetschanged(self, *args):
- self.echo("Fetching asset..")
+ self.echo("Fetching hierarchy..")
lib.schedule(self._assetschanged, 50, channel="mongo")
def on_subsetschanged(self, *args):
diff --git a/openpype/tools/loader/model.py b/openpype/tools/loader/model.py
index 1ec695b915..5115f39a69 100644
--- a/openpype/tools/loader/model.py
+++ b/openpype/tools/loader/model.py
@@ -7,6 +7,7 @@ from uuid import uuid4
from qtpy import QtCore, QtGui
import qtawesome
+from openpype import AYON_SERVER_ENABLED
from openpype.client import (
get_assets,
get_subsets,
@@ -143,9 +144,9 @@ class SubsetsModel(BaseRepresentationModel, TreeModel):
]
column_labels_mapping = {
- "subset": "Subset",
- "asset": "Asset",
- "family": "Family",
+ "subset": "Product" if AYON_SERVER_ENABLED else "Subset",
+ "asset": "Folder" if AYON_SERVER_ENABLED else "Asset",
+ "family": "Product type" if AYON_SERVER_ENABLED else "Family",
"version": "Version",
"time": "Time",
"author": "Author",
diff --git a/openpype/tools/publisher/widgets/assets_widget.py b/openpype/tools/publisher/widgets/assets_widget.py
index a750d8d540..c536f93c9b 100644
--- a/openpype/tools/publisher/widgets/assets_widget.py
+++ b/openpype/tools/publisher/widgets/assets_widget.py
@@ -2,6 +2,7 @@ import collections
from qtpy import QtWidgets, QtCore, QtGui
+from openpype import AYON_SERVER_ENABLED
from openpype.tools.utils import (
PlaceholderLineEdit,
RecursiveSortFilterProxyModel,
@@ -187,7 +188,8 @@ class AssetsDialog(QtWidgets.QDialog):
proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
filter_input = PlaceholderLineEdit(self)
- filter_input.setPlaceholderText("Filter assets..")
+ filter_input.setPlaceholderText("Filter {}..".format(
+ "folders" if AYON_SERVER_ENABLED else "assets"))
asset_view = AssetDialogView(self)
asset_view.setModel(proxy_model)
diff --git a/openpype/tools/publisher/widgets/create_widget.py b/openpype/tools/publisher/widgets/create_widget.py
index b7605b1188..1940d16eb8 100644
--- a/openpype/tools/publisher/widgets/create_widget.py
+++ b/openpype/tools/publisher/widgets/create_widget.py
@@ -2,6 +2,7 @@ import re
from qtpy import QtWidgets, QtCore, QtGui
+from openpype import AYON_SERVER_ENABLED
from openpype.pipeline.create import (
SUBSET_NAME_ALLOWED_SYMBOLS,
PRE_CREATE_THUMBNAIL_KEY,
@@ -203,7 +204,9 @@ class CreateWidget(QtWidgets.QWidget):
variant_subset_layout.setHorizontalSpacing(INPUTS_LAYOUT_HSPACING)
variant_subset_layout.setVerticalSpacing(INPUTS_LAYOUT_VSPACING)
variant_subset_layout.addRow("Variant", variant_widget)
- variant_subset_layout.addRow("Subset", subset_name_input)
+ variant_subset_layout.addRow(
+ "Product" if AYON_SERVER_ENABLED else "Subset",
+ subset_name_input)
creator_basics_layout = QtWidgets.QVBoxLayout(creator_basics_widget)
creator_basics_layout.setContentsMargins(0, 0, 0, 0)
diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py
index 0b13f26d57..1bbe73381f 100644
--- a/openpype/tools/publisher/widgets/widgets.py
+++ b/openpype/tools/publisher/widgets/widgets.py
@@ -9,6 +9,7 @@ import collections
from qtpy import QtWidgets, QtCore, QtGui
import qtawesome
+from openpype import AYON_SERVER_ENABLED
from openpype.lib.attribute_definitions import UnknownDef
from openpype.tools.attribute_defs import create_widget_for_attr_def
from openpype.tools import resources
@@ -1116,10 +1117,16 @@ class GlobalAttrsWidget(QtWidgets.QWidget):
main_layout.setHorizontalSpacing(INPUTS_LAYOUT_HSPACING)
main_layout.setVerticalSpacing(INPUTS_LAYOUT_VSPACING)
main_layout.addRow("Variant", variant_input)
- main_layout.addRow("Asset", asset_value_widget)
+ main_layout.addRow(
+ "Folder" if AYON_SERVER_ENABLED else "Asset",
+ asset_value_widget)
main_layout.addRow("Task", task_value_widget)
- main_layout.addRow("Family", family_value_widget)
- main_layout.addRow("Subset", subset_value_widget)
+ main_layout.addRow(
+ "Product type" if AYON_SERVER_ENABLED else "Family",
+ family_value_widget)
+ main_layout.addRow(
+ "Product name" if AYON_SERVER_ENABLED else "Subset",
+ subset_value_widget)
main_layout.addRow(btns_layout)
variant_input.value_changed.connect(self._on_variant_change)
diff --git a/openpype/tools/standalonepublish/widgets/widget_asset.py b/openpype/tools/standalonepublish/widgets/widget_asset.py
index 5da25a0c3e..669366dd1d 100644
--- a/openpype/tools/standalonepublish/widgets/widget_asset.py
+++ b/openpype/tools/standalonepublish/widgets/widget_asset.py
@@ -2,6 +2,7 @@ import contextlib
from qtpy import QtWidgets, QtCore
import qtawesome
+from openpype import AYON_SERVER_ENABLED
from openpype.client import (
get_projects,
get_project,
@@ -181,7 +182,8 @@ class AssetWidget(QtWidgets.QWidget):
filter = PlaceholderLineEdit()
filter.textChanged.connect(proxy.setFilterFixedString)
- filter.setPlaceholderText("Filter assets..")
+ filter.setPlaceholderText("Filter {}..".format(
+ "folders" if AYON_SERVER_ENABLED else "assets"))
header.addWidget(filter)
header.addWidget(refresh)
diff --git a/openpype/tools/utils/assets_widget.py b/openpype/tools/utils/assets_widget.py
index ffbdd995d6..a45d762c73 100644
--- a/openpype/tools/utils/assets_widget.py
+++ b/openpype/tools/utils/assets_widget.py
@@ -5,6 +5,7 @@ import qtpy
from qtpy import QtWidgets, QtCore, QtGui
import qtawesome
+from openpype import AYON_SERVER_ENABLED
from openpype.client import (
get_project,
get_assets,
@@ -607,7 +608,8 @@ class AssetsWidget(QtWidgets.QWidget):
refresh_btn.setToolTip("Refresh items")
filter_input = PlaceholderLineEdit(header_widget)
- filter_input.setPlaceholderText("Filter assets..")
+ filter_input.setPlaceholderText("Filter {}..".format(
+ "folders" if AYON_SERVER_ENABLED else "assets"))
# Header
header_layout = QtWidgets.QHBoxLayout(header_widget)
diff --git a/openpype/vendor/python/common/ayon_api/__init__.py b/openpype/vendor/python/common/ayon_api/__init__.py
index ee6672dd38..b1790d1fb6 100644
--- a/openpype/vendor/python/common/ayon_api/__init__.py
+++ b/openpype/vendor/python/common/ayon_api/__init__.py
@@ -99,22 +99,24 @@ from ._api import (
get_tasks,
- get_folder_ids_with_subsets,
- get_subset_by_id,
- get_subset_by_name,
- get_subsets,
- get_subset_families,
+ get_folder_ids_with_products,
+ get_product_by_id,
+ get_product_by_name,
+ get_products,
+ get_product_types,
+ get_project_product_types,
+ get_product_type_names,
get_version_by_id,
get_version_by_name,
version_is_latest,
get_versions,
- get_hero_version_by_subset_id,
+ get_hero_version_by_product_id,
get_hero_version_by_id,
get_hero_versions,
get_last_versions,
- get_last_version_by_subset_id,
- get_last_version_by_subset_name,
+ get_last_version_by_product_id,
+ get_last_version_by_product_name,
get_representation_by_id,
get_representation_by_name,
get_representations,
@@ -122,6 +124,10 @@ from ._api import (
get_representation_parents,
get_repre_ids_by_context_filters,
+ get_workfiles_info,
+ get_workfile_info,
+ get_workfile_info_by_id,
+
get_thumbnail,
get_folder_thumbnail,
get_version_thumbnail,
@@ -143,8 +149,8 @@ from ._api import (
get_folders_links,
get_task_links,
get_tasks_links,
- get_subset_links,
- get_subsets_links,
+ get_product_links,
+ get_products_links,
get_version_links,
get_versions_links,
get_representations_links,
@@ -251,22 +257,24 @@ __all__ = (
"get_tasks",
- "get_folder_ids_with_subsets",
- "get_subset_by_id",
- "get_subset_by_name",
- "get_subsets",
- "get_subset_families",
+ "get_folder_ids_with_products",
+ "get_product_by_id",
+ "get_product_by_name",
+ "get_products",
+ "get_product_types",
+ "get_project_product_types",
+ "get_product_type_names",
"get_version_by_id",
"get_version_by_name",
"version_is_latest",
"get_versions",
- "get_hero_version_by_subset_id",
+ "get_hero_version_by_product_id",
"get_hero_version_by_id",
"get_hero_versions",
"get_last_versions",
- "get_last_version_by_subset_id",
- "get_last_version_by_subset_name",
+ "get_last_version_by_product_id",
+ "get_last_version_by_product_name",
"get_representation_by_id",
"get_representation_by_name",
"get_representations",
@@ -274,6 +282,10 @@ __all__ = (
"get_representation_parents",
"get_repre_ids_by_context_filters",
+ "get_workfiles_info",
+ "get_workfile_info",
+ "get_workfile_info_by_id",
+
"get_thumbnail",
"get_folder_thumbnail",
"get_version_thumbnail",
@@ -295,8 +307,8 @@ __all__ = (
"get_folders_links",
"get_task_links",
"get_tasks_links",
- "get_subset_links",
- "get_subsets_links",
+ "get_product_links",
+ "get_products_links",
"get_version_links",
"get_versions_links",
"get_representations_links",
diff --git a/openpype/vendor/python/common/ayon_api/_api.py b/openpype/vendor/python/common/ayon_api/_api.py
index ed730841ae..f351cd8102 100644
--- a/openpype/vendor/python/common/ayon_api/_api.py
+++ b/openpype/vendor/python/common/ayon_api/_api.py
@@ -656,29 +656,39 @@ def get_folder_by_name(*args, **kwargs):
return con.get_folder_by_name(*args, **kwargs)
-def get_folder_ids_with_subsets(*args, **kwargs):
+def get_folder_ids_with_products(*args, **kwargs):
con = get_server_api_connection()
- return con.get_folder_ids_with_subsets(*args, **kwargs)
+ return con.get_folder_ids_with_products(*args, **kwargs)
-def get_subsets(*args, **kwargs):
+def get_product_types(*args, **kwargs):
con = get_server_api_connection()
- return con.get_subsets(*args, **kwargs)
+ return con.get_product_types(*args, **kwargs)
-def get_subset_by_id(*args, **kwargs):
+def get_project_product_types(*args, **kwargs):
con = get_server_api_connection()
- return con.get_subset_by_id(*args, **kwargs)
+ return con.get_project_product_types(*args, **kwargs)
-def get_subset_by_name(*args, **kwargs):
+def get_product_type_names(*args, **kwargs):
con = get_server_api_connection()
- return con.get_subset_by_name(*args, **kwargs)
+ return con.get_product_type_names(*args, **kwargs)
-def get_subset_families(*args, **kwargs):
+def get_products(*args, **kwargs):
con = get_server_api_connection()
- return con.get_subset_families(*args, **kwargs)
+ return con.get_products(*args, **kwargs)
+
+
+def get_product_by_id(*args, **kwargs):
+ con = get_server_api_connection()
+ return con.get_product_by_id(*args, **kwargs)
+
+
+def get_product_by_name(*args, **kwargs):
+ con = get_server_api_connection()
+ return con.get_product_by_name(*args, **kwargs)
def get_versions(*args, **kwargs):
@@ -701,9 +711,9 @@ def get_hero_version_by_id(*args, **kwargs):
return con.get_hero_version_by_id(*args, **kwargs)
-def get_hero_version_by_subset_id(*args, **kwargs):
+def get_hero_version_by_product_id(*args, **kwargs):
con = get_server_api_connection()
- return con.get_hero_version_by_subset_id(*args, **kwargs)
+ return con.get_hero_version_by_product_id(*args, **kwargs)
def get_hero_versions(*args, **kwargs):
@@ -716,14 +726,14 @@ def get_last_versions(*args, **kwargs):
return con.get_last_versions(*args, **kwargs)
-def get_last_version_by_subset_id(*args, **kwargs):
+def get_last_version_by_product_id(*args, **kwargs):
con = get_server_api_connection()
- return con.get_last_version_by_subset_id(*args, **kwargs)
+ return con.get_last_version_by_product_id(*args, **kwargs)
-def get_last_version_by_subset_name(*args, **kwargs):
+def get_last_version_by_product_name(*args, **kwargs):
con = get_server_api_connection()
- return con.get_last_version_by_subset_name(*args, **kwargs)
+ return con.get_last_version_by_product_name(*args, **kwargs)
def version_is_latest(*args, **kwargs):
@@ -761,6 +771,21 @@ def get_repre_ids_by_context_filters(*args, **kwargs):
return con.get_repre_ids_by_context_filters(*args, **kwargs)
+def get_workfiles_info(*args, **kwargs):
+ con = get_server_api_connection()
+ return con.get_workfiles_info(*args, **kwargs)
+
+
+def get_workfile_info(*args, **kwargs):
+ con = get_server_api_connection()
+ return con.get_workfile_info(*args, **kwargs)
+
+
+def get_workfile_info_by_id(*args, **kwargs):
+ con = get_server_api_connection()
+ return con.get_workfile_info_by_id(*args, **kwargs)
+
+
def create_project(
project_name,
project_code,
@@ -954,31 +979,31 @@ def get_task_links(
)
-def get_subsets_links(
+def get_products_links(
project_name,
- subset_ids=None,
+ product_ids=None,
link_types=None,
link_direction=None
):
con = get_server_api_connection()
- return con.get_subsets_links(
+ return con.get_products_links(
project_name,
- subset_ids,
+ product_ids,
link_types,
link_direction
)
-def get_subset_links(
+def get_product_links(
project_name,
- subset_id,
+ product_id,
link_types=None,
link_direction=None
):
con = get_server_api_connection()
- return con.get_subset_links(
+ return con.get_product_links(
project_name,
- subset_id,
+ product_id,
link_types,
link_direction
)
diff --git a/openpype/vendor/python/common/ayon_api/constants.py b/openpype/vendor/python/common/ayon_api/constants.py
index 03451756a0..e2b05a5cae 100644
--- a/openpype/vendor/python/common/ayon_api/constants.py
+++ b/openpype/vendor/python/common/ayon_api/constants.py
@@ -4,6 +4,13 @@ SERVER_API_ENV_KEY = "AYON_API_KEY"
# Backwards compatibility
SERVER_TOKEN_ENV_KEY = SERVER_API_ENV_KEY
+# --- Product types ---
+DEFAULT_PRODUCT_TYPE_FIELDS = {
+ "name",
+ "icon",
+ "color",
+}
+
# --- Project ---
DEFAULT_PROJECT_FIELDS = {
"active",
@@ -36,13 +43,13 @@ DEFAULT_TASK_FIELDS = {
"assignees",
}
-# --- Subsets ---
-DEFAULT_SUBSET_FIELDS = {
+# --- Products ---
+DEFAULT_PRODUCT_FIELDS = {
"id",
"name",
"folderId",
"active",
- "family",
+ "productType",
}
# --- Versions ---
@@ -50,7 +57,7 @@ DEFAULT_VERSION_FIELDS = {
"id",
"name",
"version",
- "subsetId",
+ "productId",
"taskId",
"active",
"author",
diff --git a/openpype/vendor/python/common/ayon_api/entity_hub.py b/openpype/vendor/python/common/ayon_api/entity_hub.py
index c6baceeb31..d71ce18839 100644
--- a/openpype/vendor/python/common/ayon_api/entity_hub.py
+++ b/openpype/vendor/python/common/ayon_api/entity_hub.py
@@ -558,7 +558,7 @@ class EntityHub(object):
folder_fields = set(
self._connection.get_default_fields_for_type("folder")
)
- folder_fields.add("hasSubsets")
+ folder_fields.add("hasProducts")
if self._allow_data_changes:
folder_fields.add("data")
return folder_fields
@@ -602,7 +602,7 @@ class EntityHub(object):
for folder in folders_by_parent_id[parent_id]:
folder_entity = self.add_folder(folder)
children_ids.add(folder_entity.id)
- folder_entity.has_published_content = folder["hasSubsets"]
+ folder_entity.has_published_content = folder["hasProducts"]
hierarchy_queue.append((folder_entity.id, folder_entity))
for task in tasks_by_parent_id[parent_id]:
@@ -1564,7 +1564,7 @@ class FolderEntity(BaseEntity):
self._orig_folder_type = folder_type
self._orig_label = label
- # Know if folder has any subsets
+ # Know if folder has any products
# - is used to know if folder allows hierarchy changes
self._has_published_content = False
self._path = path
diff --git a/openpype/vendor/python/common/ayon_api/graphql_queries.py b/openpype/vendor/python/common/ayon_api/graphql_queries.py
index 1fc653cf68..4af8c53e4e 100644
--- a/openpype/vendor/python/common/ayon_api/graphql_queries.py
+++ b/openpype/vendor/python/common/ayon_api/graphql_queries.py
@@ -123,6 +123,51 @@ def projects_graphql_query(fields):
return query
+def product_types_query(fields):
+ query = GraphQlQuery("ProductTypes")
+ product_types_field = query.add_field("productTypes")
+
+ nested_fields = fields_to_dict(fields)
+
+ query_queue = collections.deque()
+ for key, value in nested_fields.items():
+ query_queue.append((key, value, product_types_field))
+
+ while query_queue:
+ item = query_queue.popleft()
+ key, value, parent = item
+ field = parent.add_field(key)
+ if value is FIELD_VALUE:
+ continue
+
+ for k, v in value.items():
+ query_queue.append((k, v, field))
+ return query
+
+def project_product_types_query(fields):
+ query = GraphQlQuery("ProjectProductTypes")
+ project_query = query.add_field("project")
+ project_name_var = query.add_variable("projectName", "String!")
+ project_query.set_filter("name", project_name_var)
+ product_types_field = project_query.add_field("productTypes")
+ nested_fields = fields_to_dict(fields)
+
+ query_queue = collections.deque()
+ for key, value in nested_fields.items():
+ query_queue.append((key, value, product_types_field))
+
+ while query_queue:
+ item = query_queue.popleft()
+ key, value, parent = item
+ field = parent.add_field(key)
+ if value is FIELD_VALUE:
+ continue
+
+ for k, v in value.items():
+ query_queue.append((k, v, field))
+ return query
+
+
def folders_graphql_query(fields):
query = GraphQlQuery("FoldersQuery")
project_name_var = query.add_variable("projectName", "String!")
@@ -130,7 +175,7 @@ def folders_graphql_query(fields):
parent_folder_ids_var = query.add_variable("parentFolderIds", "[String!]")
folder_paths_var = query.add_variable("folderPaths", "[String!]")
folder_names_var = query.add_variable("folderNames", "[String!]")
- has_subsets_var = query.add_variable("folderHasSubsets", "Boolean!")
+ has_products_var = query.add_variable("folderHasProducts", "Boolean!")
project_field = query.add_field("project")
project_field.set_filter("name", project_name_var)
@@ -140,7 +185,7 @@ def folders_graphql_query(fields):
folders_field.set_filter("parentIds", parent_folder_ids_var)
folders_field.set_filter("names", folder_names_var)
folders_field.set_filter("paths", folder_paths_var)
- folders_field.set_filter("hasSubsets", has_subsets_var)
+ folders_field.set_filter("hasProducts", has_products_var)
nested_fields = fields_to_dict(fields)
add_links_fields(folders_field, nested_fields)
@@ -198,28 +243,28 @@ def tasks_graphql_query(fields):
return query
-def subsets_graphql_query(fields):
- query = GraphQlQuery("SubsetsQuery")
+def products_graphql_query(fields):
+ query = GraphQlQuery("ProductsQuery")
project_name_var = query.add_variable("projectName", "String!")
folder_ids_var = query.add_variable("folderIds", "[String!]")
- subset_ids_var = query.add_variable("subsetIds", "[String!]")
- subset_names_var = query.add_variable("subsetNames", "[String!]")
+ product_ids_var = query.add_variable("productIds", "[String!]")
+ product_names_var = query.add_variable("productNames", "[String!]")
project_field = query.add_field("project")
project_field.set_filter("name", project_name_var)
- subsets_field = project_field.add_field_with_edges("subsets")
- subsets_field.set_filter("ids", subset_ids_var)
- subsets_field.set_filter("names", subset_names_var)
- subsets_field.set_filter("folderIds", folder_ids_var)
+ products_field = project_field.add_field_with_edges("products")
+ products_field.set_filter("ids", product_ids_var)
+ products_field.set_filter("names", product_names_var)
+ products_field.set_filter("folderIds", folder_ids_var)
nested_fields = fields_to_dict(set(fields))
- add_links_fields(subsets_field, nested_fields)
+ add_links_fields(products_field, nested_fields)
query_queue = collections.deque()
for key, value in nested_fields.items():
- query_queue.append((key, value, subsets_field))
+ query_queue.append((key, value, products_field))
while query_queue:
item = query_queue.popleft()
@@ -237,7 +282,7 @@ def versions_graphql_query(fields):
query = GraphQlQuery("VersionsQuery")
project_name_var = query.add_variable("projectName", "String!")
- subset_ids_var = query.add_variable("subsetIds", "[String!]")
+ product_ids_var = query.add_variable("productIds", "[String!]")
version_ids_var = query.add_variable("versionIds", "[String!]")
versions_var = query.add_variable("versions", "[Int!]")
hero_only_var = query.add_variable("heroOnly", "Boolean")
@@ -249,20 +294,20 @@ def versions_graphql_query(fields):
project_field = query.add_field("project")
project_field.set_filter("name", project_name_var)
- subsets_field = project_field.add_field_with_edges("versions")
- subsets_field.set_filter("ids", version_ids_var)
- subsets_field.set_filter("subsetIds", subset_ids_var)
- subsets_field.set_filter("versions", versions_var)
- subsets_field.set_filter("heroOnly", hero_only_var)
- subsets_field.set_filter("latestOnly", latest_only_var)
- subsets_field.set_filter("heroOrLatestOnly", hero_or_latest_only_var)
+ products_field = project_field.add_field_with_edges("versions")
+ products_field.set_filter("ids", version_ids_var)
+ products_field.set_filter("productIds", product_ids_var)
+ products_field.set_filter("versions", versions_var)
+ products_field.set_filter("heroOnly", hero_only_var)
+ products_field.set_filter("latestOnly", latest_only_var)
+ products_field.set_filter("heroOrLatestOnly", hero_or_latest_only_var)
nested_fields = fields_to_dict(set(fields))
- add_links_fields(subsets_field, nested_fields)
+ add_links_fields(products_field, nested_fields)
query_queue = collections.deque()
for key, value in nested_fields.items():
- query_queue.append((key, value, subsets_field))
+ query_queue.append((key, value, products_field))
while query_queue:
item = query_queue.popleft()
@@ -312,7 +357,7 @@ def representations_graphql_query(fields):
def representations_parents_qraphql_query(
- version_fields, subset_fields, folder_fields
+ version_fields, product_fields, folder_fields
):
query = GraphQlQuery("RepresentationsParentsQuery")
@@ -331,11 +376,11 @@ def representations_parents_qraphql_query(
for key, value in fields_to_dict(version_fields).items():
fields_queue.append((key, value, version_field))
- subset_field = version_field.add_field("subset")
- for key, value in fields_to_dict(subset_fields).items():
- fields_queue.append((key, value, subset_field))
+ product_field = version_field.add_field("product")
+ for key, value in fields_to_dict(product_fields).items():
+ fields_queue.append((key, value, product_field))
- folder_field = subset_field.add_field("folder")
+ folder_field = product_field.add_field("folder")
for key, value in fields_to_dict(folder_fields).items():
fields_queue.append((key, value, folder_field))
diff --git a/openpype/vendor/python/common/ayon_api/operations.py b/openpype/vendor/python/common/ayon_api/operations.py
index b5689de7c0..7cf610a566 100644
--- a/openpype/vendor/python/common/ayon_api/operations.py
+++ b/openpype/vendor/python/common/ayon_api/operations.py
@@ -31,12 +31,14 @@ def new_folder_entity(
Args:
name (str): Is considered as unique identifier of folder in project.
- parent_id (str): Id of parent folder.
- attribs (Dict[str, Any]): Explicitly set attributes of folder.
- data (Dict[str, Any]): Custom folder data. Empty dictionary is used
- if not passed.
- thumbnail_id (str): Id of thumbnail related to folder.
- entity_id (str): Predefined id of entity. New id is
+ folder_type (str): Type of folder.
+ parent_id (Optional[str]]): Id of parent folder.
+ attribs (Optional[Dict[str, Any]]): Explicitly set attributes
+ of folder.
+ data (Optional[Dict[str, Any]]): Custom folder data. Empty dictionary
+ is used if not passed.
+ thumbnail_id (Optional[str]): Id of thumbnail related to folder.
+ entity_id (Optional[str]): Predefined id of entity. New id is
created if not passed.
Returns:
@@ -64,23 +66,32 @@ def new_folder_entity(
}
-def new_subset_entity(
- name, family, folder_id, attribs=None, data=None, entity_id=None
+def new_product_entity(
+ name,
+ product_type,
+ folder_id,
+ status=None,
+ attribs=None,
+ data=None,
+ entity_id=None
):
- """Create skeleton data of subset entity.
+ """Create skeleton data of product entity.
Args:
- name (str): Is considered as unique identifier of subset under folder.
- family (str): Subset's family.
+ name (str): Is considered as unique identifier of
+ product under folder.
+ product_type (str): Product type.
folder_id (str): Id of parent folder.
- attribs (Dict[str, Any]): Explicitly set attributes of subset.
- data (Dict[str, Any]): Subset entity data. Empty dictionary is used
- if not passed. Value of 'family' is used to fill 'family'.
- entity_id (str): Predefined id of entity. New id is
+ status (Optional[str]): Product status.
+ attribs (Optional[Dict[str, Any]]): Explicitly set attributes
+ of product.
+ data (Optional[Dict[str, Any]]): product entity data. Empty dictionary
+ is used if not passed.
+ entity_id (Optional[str]): Predefined id of entity. New id is
created if not passed.
Returns:
- Dict[str, Any]: Skeleton of subset entity.
+ Dict[str, Any]: Skeleton of product entity.
"""
if attribs is None:
@@ -89,19 +100,22 @@ def new_subset_entity(
if data is None:
data = {}
- return {
+ output = {
"id": _create_or_convert_to_id(entity_id),
"name": name,
- "family": family,
+ "productType": product_type,
"attrib": attribs,
"data": data,
- "folderId": _create_or_convert_to_id(folder_id)
+ "folderId": _create_or_convert_to_id(folder_id),
}
+ if status:
+ output["status"] = status
+ return output
def new_version_entity(
version,
- subset_id,
+ product_id,
task_id=None,
thumbnail_id=None,
author=None,
@@ -113,14 +127,15 @@ def new_version_entity(
Args:
version (int): Is considered as unique identifier of version
- under subset.
- subset_id (str): Id of parent subset.
- task_id (str): Id of task under which subset was created.
- thumbnail_id (str): Thumbnail related to version.
- author (str): Name of version author.
- attribs (Dict[str, Any]): Explicitly set attributes of version.
- data (Dict[str, Any]): Version entity custom data.
- entity_id (str): Predefined id of entity. New id is
+ under product.
+ product_id (str): Id of parent product.
+ task_id (Optional[str]]): Id of task under which product was created.
+ thumbnail_id (Optional[str]]): Thumbnail related to version.
+ author (Optional[str]]): Name of version author.
+ attribs (Optional[Dict[str, Any]]): Explicitly set attributes
+ of version.
+ data (Optional[Dict[str, Any]]): Version entity custom data.
+ entity_id (Optional[str]): Predefined id of entity. New id is
created if not passed.
Returns:
@@ -139,7 +154,7 @@ def new_version_entity(
output = {
"id": _create_or_convert_to_id(entity_id),
"version": int(version),
- "subsetId": _create_or_convert_to_id(subset_id),
+ "productId": _create_or_convert_to_id(product_id),
"attrib": attribs,
"data": data
}
@@ -154,7 +169,7 @@ def new_version_entity(
def new_hero_version_entity(
version,
- subset_id,
+ product_id,
task_id=None,
thumbnail_id=None,
author=None,
@@ -166,14 +181,15 @@ def new_hero_version_entity(
Args:
version (int): Is considered as unique identifier of version
- under subset. Should be same as standard version if there is any.
- subset_id (str): Id of parent subset.
- task_id (str): Id of task under which subset was created.
- thumbnail_id (str): Thumbnail related to version.
- author (str): Name of version author.
- attribs (Dict[str, Any]): Explicitly set attributes of version.
- data (Dict[str, Any]): Version entity data.
- entity_id (str): Predefined id of entity. New id is
+ under product. Should be same as standard version if there is any.
+ product_id (str): Id of parent product.
+ task_id (Optional[str]): Id of task under which product was created.
+ thumbnail_id (Optional[str]): Thumbnail related to version.
+ author (Optional[str]): Name of version author.
+ attribs (Optional[Dict[str, Any]]): Explicitly set attributes
+ of version.
+ data (Optional[Dict[str, Any]]): Version entity data.
+ entity_id (Optional[str]): Predefined id of entity. New id is
created if not passed.
Returns:
@@ -189,7 +205,7 @@ def new_hero_version_entity(
output = {
"id": _create_or_convert_to_id(entity_id),
"version": -abs(int(version)),
- "subsetId": subset_id,
+ "productId": product_id,
"attrib": attribs,
"data": data
}
@@ -211,9 +227,10 @@ def new_representation_entity(
name (str): Representation name considered as unique identifier
of representation under version.
version_id (str): Id of parent version.
- attribs (Dict[str, Any]): Explicitly set attributes of representation.
- data (Dict[str, Any]): Representation entity data.
- entity_id (str): Predefined id of entity. New id is created
+ attribs (Optional[Dict[str, Any]]): Explicitly set attributes
+ of representation.
+ data (Optional[Dict[str, Any]]): Representation entity data.
+ entity_id (Optional[str]): Predefined id of entity. New id is created
if not passed.
Returns:
@@ -247,8 +264,8 @@ def new_workfile_info_doc(
folder_id (str): Id of folder under which workfile live.
task_name (str): Task under which was workfile created.
files (List[str]): List of rootless filepaths related to workfile.
- data (Dict[str, Any]): Additional metadata.
- entity_id (str): Predefined id of entity. New id is created
+ data (Optional[Dict[str, Any]]): Additional metadata.
+ entity_id (Optional[str]): Predefined id of entity. New id is created
if not passed.
Returns:
diff --git a/openpype/vendor/python/common/ayon_api/server_api.py b/openpype/vendor/python/common/ayon_api/server_api.py
index 675f5ea4be..253d590658 100644
--- a/openpype/vendor/python/common/ayon_api/server_api.py
+++ b/openpype/vendor/python/common/ayon_api/server_api.py
@@ -17,10 +17,11 @@ import requests
from requests.exceptions import JSONDecodeError as RequestsJSONDecodeError
from .constants import (
+ DEFAULT_PRODUCT_TYPE_FIELDS,
DEFAULT_PROJECT_FIELDS,
DEFAULT_FOLDER_FIELDS,
DEFAULT_TASK_FIELDS,
- DEFAULT_SUBSET_FIELDS,
+ DEFAULT_PRODUCT_FIELDS,
DEFAULT_VERSION_FIELDS,
DEFAULT_REPRESENTATION_FIELDS,
REPRESENTATION_FILES_FIELDS,
@@ -32,9 +33,11 @@ from .graphql import GraphQlQuery, INTROSPECTION_QUERY
from .graphql_queries import (
project_graphql_query,
projects_graphql_query,
+ project_product_types_query,
+ product_types_query,
folders_graphql_query,
tasks_graphql_query,
- subsets_graphql_query,
+ products_graphql_query,
versions_graphql_query,
representations_graphql_query,
representations_parents_qraphql_query,
@@ -293,12 +296,12 @@ class ServerAPI(object):
Args:
base_url (str): Example: http://localhost:5000
- token (str): Access token (api key) to server.
- site_id (str): Unique name of site. Should be the same when
+ token (Optional[str]): Access token (api key) to server.
+ site_id (Optional[str]): Unique name of site. Should be the same when
connection is created from the same machine under same user.
- client_version (str): Version of client application (used in
+ client_version (Optional[str]): Version of client application (used in
desktop client application).
- default_settings_variant (Union[str, None]): Settings variant used by
+ default_settings_variant (Optional[str]): Settings variant used by
default if a method for settings won't get any (by default is
'production').
"""
@@ -317,7 +320,7 @@ class ServerAPI(object):
base_url = base_url.rstrip("/")
self._base_url = base_url
self._rest_url = "{}/api".format(base_url)
- self._graphl_url = "{}/graphql".format(base_url)
+ self._graphql_url = "{}/graphql".format(base_url)
self._log = None
self._access_token = token
self._site_id = site_id
@@ -472,7 +475,7 @@ class ServerAPI(object):
'as_user' context manager is not entered.
Args:
- username (Union[str, None]): Username to work as when service.
+ username (Optional[str]): Username to work as when service.
Raises:
ValueError: When connection is not yet authenticated or api key
@@ -888,13 +891,14 @@ class ServerAPI(object):
Not all event happen on a project.
Args:
- topics (Iterable[str]): Name of topics.
- project_names (Iterable[str]): Project on which event happened.
- states (Iterable[str]): Filtering by states.
- users (Iterable[str]): Filtering by users who created/triggered
- an event.
- include_logs (bool): Query also log events.
- fields (Union[Iterable[str], None]): Fields that should be received
+ topics (Optional[Iterable[str]]): Name of topics.
+ project_names (Optional[Iterable[str]]): Project on which
+ event happened.
+ states (Optional[Iterable[str]]): Filtering by states.
+ users (Optional[Iterable[str]]): Filtering by users
+ who created/triggered an event.
+ include_logs (Optional[bool]): Query also log events.
+ fields (Optional[Iterable[str]]): Fields that should be received
for each event.
Returns:
@@ -951,17 +955,18 @@ class ServerAPI(object):
summary=None,
payload=None
):
- kwargs = {}
- for key, value in (
- ("sender", sender),
- ("projectName", project_name),
- ("status", status),
- ("description", description),
- ("summary", summary),
- ("payload", payload),
- ):
- if value is not None:
- kwargs[key] = value
+ kwargs = {
+ key: value
+ for key, value in (
+ ("sender", sender),
+ ("project", project_name),
+ ("status", status),
+ ("description", description),
+ ("summary", summary),
+ ("payload", payload),
+ )
+ if value is not None
+ }
response = self.patch(
"events/{}".format(event_id),
**kwargs
@@ -990,15 +995,16 @@ class ServerAPI(object):
hash (Optional[str]): Event hash.
project_name (Optional[str]): Project name.
username (Optional[str]): Username which triggered event.
- dependencies (Optional[list[str]]): List of event id deprendencies.
+ dependencies (Optional[list[str]]): List of event id dependencies.
description (Optional[str]): Description of event.
summary (Optional[dict[str, Any]]): Summary of event that can be used
for simple filtering on listeners.
payload (Optional[dict[str, Any]]): Full payload of event data with
all details.
- finished (bool): Mark event as finished on dispatch.
- store (bool): Store event in event queue for possible future processing
- otherwise is event send only to active listeners.
+ finished (Optional[bool]): Mark event as finished on dispatch.
+ store (Optional[bool]): Store event in event queue for possible
+ future processing otherwise is event send only
+ to active listeners.
"""
if summary is None:
@@ -1053,14 +1059,14 @@ class ServerAPI(object):
Use-case:
- Service 1 is creating events with topic 'my.leech'
- Service 2 process 'my.leech' and uses target topic 'my.process'
- - this service can run on 1..n machines
+ - this service can run on 1-n machines
- all events must be processed in a sequence by their creation
time and only one event can be processed at a time
- in this case 'sequential' should be set to 'True' so only
one machine is actually processing events, but if one goes
down there are other that can take place
- Service 3 process 'my.leech' and uses target topic 'my.discover'
- - this service can run on 1..n machines
+ - this service can run on 1-n machines
- order of events is not important
- 'sequential' should be 'False'
@@ -1068,8 +1074,10 @@ class ServerAPI(object):
source_topic (str): Source topic to enroll.
target_topic (str): Topic of dependent event.
sender (str): Identifier of sender (e.g. service name or username).
- description (str): Human readable text shown in target event.
- sequential (bool): The source topic must be processed in sequence.
+ description (Optional[str]): Human readable text shown
+ in target event.
+ sequential (Optional[bool]): The source topic must be processed
+ in sequence.
Returns:
Union[None, dict[str, Any]]: None if there is no event matching
@@ -1114,7 +1122,9 @@ class ServerAPI(object):
f_stream.write(chunk)
progress.add_transferred_chunk(len(chunk))
- def download_file(self, endpoint, filepath, chunk_size=None, progress=None):
+ def download_file(
+ self, endpoint, filepath, chunk_size=None, progress=None
+ ):
"""Download file from AYON server.
Endpoint can be full url (must start with 'base_url' of api object).
@@ -1126,9 +1136,10 @@ class ServerAPI(object):
Args:
endpoint (str): Endpoint or URL to file that should be downloaded.
filepath (str): Path where file will be downloaded.
- chunk_size (int): Size of chunks that are received in single loop.
- progress (TransferProgress): Object that gives ability to track
- download progress.
+ chunk_size (Optional[int]): Size of chunks that are received
+ in single loop.
+ progress (Optional[TransferProgress]): Object that gives ability
+ to track download progress.
"""
if not chunk_size:
@@ -1186,8 +1197,8 @@ class ServerAPI(object):
Args:
endpoint (str): Endpoint or url where file will be uploaded.
filepath (str): Source filepath.
- progress (TransferProgress): Object that gives ability to track
- upload progress.
+ progress (Optional[TransferProgress]): Object that gives ability
+ to track upload progress.
"""
if endpoint.startswith(self._base_url):
@@ -1232,7 +1243,7 @@ class ServerAPI(object):
Args:
query (str): GraphQl query string.
- variables (Union[None, dict[str, Any]): Variables that can be
+ variables (Optional[dict[str, Any]): Variables that can be
used in query.
Returns:
@@ -1242,7 +1253,7 @@ class ServerAPI(object):
data = {"query": query, "variables": variables or {}}
response = self._do_rest_request(
RequestTypes.post,
- self._graphl_url,
+ self._graphql_url,
json=data
)
response.raise_for_status()
@@ -1271,7 +1282,7 @@ class ServerAPI(object):
"""Get components schema.
Name of components does not match entity type names e.g. 'project' is
- under 'ProjectModel'. We should find out some mapping. Also there
+ under 'ProjectModel'. We should find out some mapping. Also, there
are properties which don't have information about reference to object
e.g. 'config' has just object definition without reference schema.
@@ -1432,8 +1443,8 @@ class ServerAPI(object):
for attr in attributes
}
- if entity_type == "subset":
- return DEFAULT_SUBSET_FIELDS | {
+ if entity_type == "product":
+ return DEFAULT_PRODUCT_FIELDS | {
"attrib.{}".format(attr)
for attr in attributes
}
@@ -1454,14 +1465,17 @@ class ServerAPI(object):
}
)
+ if entity_type == "productType":
+ return DEFAULT_PRODUCT_TYPE_FIELDS
+
raise ValueError("Unknown entity type \"{}\"".format(entity_type))
def get_addons_info(self, details=True):
"""Get information about addons available on server.
Args:
- details (bool): Detailed data with information how to get client
- code.
+ details (Optional[bool]): Detailed data with information how
+ to get client code.
"""
endpoint = "addons"
@@ -1520,11 +1534,11 @@ class ServerAPI(object):
addon_version (str): Addon version.
filename (str): Filename in private folder on server.
destination_dir (str): Where the file should be downloaded.
- destination_filename (str): Name of destination filename. Source
- filename is used if not passed.
- chunk_size (int): Download chunk size.
- progress (TransferProgress): Object that gives ability to track
- download progress.
+ destination_filename (Optional[str]): Name of destination
+ filename. Source filename is used if not passed.
+ chunk_size (Optional[int]): Download chunk size.
+ progress (Optional[TransferProgress]): Object that gives ability
+ to track download progress.
Returns:
str: Filepath to downloaded file.
@@ -1586,7 +1600,7 @@ class ServerAPI(object):
python_modules=None,
sources=None
):
- """Update or create dependency package infor by it's identifiers.
+ """Update or create dependency package for identifiers.
The endpoint can be used to create or update dependency package.
@@ -1595,15 +1609,17 @@ class ServerAPI(object):
platform_name (Literal["windows", "linux", "darwin"]): Platform for
which is dependency package targeted.
size (int): Size of dependency package in bytes.
- checksum (str): Checksum of archive file where dependecies are.
- checksum_algorithm (str): Algorithm used to calculate checksum.
- By default, is used 'md5' (defined by server).
- supported_addons (Dict[str, str]): Name of addons for which was the
- package created ('{"": "", ...}').
- python_modules (Dict[str, str]): Python modules in dependencies
- package ('{"": "", ...}').
- sources (List[Dict[str, Any]]): Information about sources where
- dependency package is available.
+ checksum (str): Checksum of archive file where dependencies are.
+ checksum_algorithm (Optional[str]): Algorithm used to calculate
+ checksum. By default, is used 'md5' (defined by server).
+ supported_addons (Optional[Dict[str, str]]): Name of addons for
+ which was the package created.
+ '{"": "", ...}'
+ python_modules (Optional[Dict[str, str]]): Python modules in
+ dependencies package.
+ '{"": "", ...}'
+ sources (Optional[List[Dict[str, Any]]]): Information about
+ sources where dependency package is available.
"""
kwargs = {
@@ -1625,7 +1641,7 @@ class ServerAPI(object):
checksum=checksum,
**kwargs
)
- if response.status not in (200, 201):
+ if response.status not in (200, 201, 204):
raise ServerError("Failed to create/update dependency")
return response.data
@@ -1647,11 +1663,12 @@ class ServerAPI(object):
package_name (str): Name of package to download.
dst_directory (str): Where the file should be downloaded.
filename (str): Name of destination filename.
- platform_name (str): Name of platform for which the dependency
- package is targetter. Default value is current platform.
- chunk_size (int): Download chunk size.
- progress (TransferProgress): Object that gives ability to track
- download progress.
+ platform_name (Optional[str]): Name of platform for which the
+ dependency package is targeted. Default value is
+ current platform.
+ chunk_size (Optional[int]): Download chunk size.
+ progress (Optional[TransferProgress]): Object that gives ability
+ to track download progress.
Returns:
str: Filepath to downloaded file.
@@ -1676,7 +1693,8 @@ class ServerAPI(object):
Args:
filepath (str): Path to a package file.
package_name (str): Name of package. Must be unique.
- platform_name (str): For which platform is the package targeted.
+ platform_name (Optional[str]): For which platform is the
+ package targeted.
progress (Optional[TransferProgress]): Object to keep track about
upload state.
"""
@@ -1695,8 +1713,8 @@ class ServerAPI(object):
Args:
package_name (str): Name of package to remove.
- platform_name (Optional[str]): Which platform of the package should
- be removed. Current platform is used if not passed.
+ platform_name (Optional[str]): Which platform of the package
+ should be removed. Current platform is used if not passed.
"""
if platform_name is None:
@@ -1741,7 +1759,7 @@ class ServerAPI(object):
if preset name is set to 'None'.
Args:
- Union[str, None]: Preset name.
+ preset_name (Optional[str]): Preset name.
Returns:
dict[str, Any]: Anatomy preset values.
@@ -1807,7 +1825,7 @@ class ServerAPI(object):
Args:
addon_name (str): Name of addon.
addon_version (str): Version of addon.
- project_name (Union[str, None]): Schema for specific project or
+ project_name (Optional[str]): Schema for specific project or
default studio schemas.
Returns:
@@ -1855,8 +1873,8 @@ class ServerAPI(object):
Args:
addon_name (str): Name of addon.
addon_version (str): Version of addon.
- variant (str): Name of settings variant. By default, is used
- 'default_settings_variant' passed on init.
+ variant (Optional[str]): Name of settings variant. By default,
+ is used 'default_settings_variant' passed on init.
Returns:
dict[str, Any]: Addon settings.
@@ -1898,13 +1916,14 @@ class ServerAPI(object):
addon_version (str): Version of addon.
project_name (str): Name of project for which the settings are
received.
- variant (str): Name of settings variant. By default, is used
- 'production'.
- site_id (str): Name of site which is used for site overrides. Is
- filled with connection 'site_id' attribute if not passed.
- use_site (bool): To force disable option of using site overrides
- set to 'False'. In that case won't be applied any site
- overrides.
+ variant (Optional[str]): Name of settings variant. By default,
+ is used 'production'.
+ site_id (Optional[str]): Name of site which is used for site
+ overrides. Is filled with connection 'site_id' attribute
+ if not passed.
+ use_site (Optional[bool]): To force disable option of using site
+ overrides set to 'False'. In that case won't be applied
+ any site overrides.
Returns:
dict[str, Any]: Addon settings.
@@ -1951,15 +1970,17 @@ class ServerAPI(object):
Args:
addon_name (str): Name of addon.
addon_version (str): Version of addon.
- project_name (str): Name of project for which the settings are
- received. A studio settings values are received if is 'None'.
- variant (str): Name of settings variant. By default, is used
- 'production'.
- site_id (str): Name of site which is used for site overrides. Is
- filled with connection 'site_id' attribute if not passed.
- use_site (bool): To force disable option of using site overrides
- set to 'False'. In that case won't be applied any site
- overrides.
+ project_name (Optional[str]): Name of project for which the
+ settings are received. A studio settings values are received
+ if is 'None'.
+ variant (Optional[str]): Name of settings variant. By default,
+ is used 'production'.
+ site_id (Optional[str]): Name of site which is used for site
+ overrides. Is filled with connection 'site_id' attribute
+ if not passed.
+ use_site (Optional[bool]): To force disable option of using
+ site overrides set to 'False'. In that case won't be applied
+ any site overrides.
Returns:
dict[str, Any]: Addon settings.
@@ -1983,8 +2004,8 @@ class ServerAPI(object):
Args:
addon_name (str): Name of addon.
addon_version (str): Version of addon.
- site_id (str): Name of site for which should be settings returned.
- using 'site_id' attribute if not passed.
+ site_id (Optional[str]): Name of site for which should be settings
+ returned. using 'site_id' attribute if not passed.
Returns:
dict[str, Any]: Site settings.
@@ -2007,8 +2028,8 @@ class ServerAPI(object):
"""All addons settings in one bulk.
Args:
- variant (Literal[production, staging]): Variant of settings. By
- default, is used 'production'.
+ variant (Optional[Literal[production, staging]]): Variant of
+ settings. By default, is used 'production'.
only_values (Optional[bool]): Output will contain only settings
values without metadata about addons.
@@ -2105,9 +2126,9 @@ class ServerAPI(object):
By default, is used 'production'.
site_id (Optional[str]): Id of site for which want to receive
site overrides.
- use_site (bool): To force disable option of using site overrides
- set to 'False'. In that case won't be applied any site
- overrides.
+ use_site (Optional[bool]): To force disable option of using site
+ overrides set to 'False'. In that case won't be applied
+ any site overrides.
only_values (Optional[bool]): Only settings values will be
returned. By default, is set to 'True'.
"""
@@ -2147,10 +2168,10 @@ class ServerAPI(object):
User must be logged in.
Args:
- active (Union[bool, None]): Filter active/inactive projects. Both
+ active (Optional[bool]): Filter active/inactive projects. Both
+ are returned if 'None' is passed.
+ library (Optional[bool]): Filter standard/library projects. Both
are returned if 'None' is passed.
- library (bool): Filter standard/library projects. Both are
- returned if 'None' is passed.
Returns:
Generator[Dict[str, Any]]: Available projects.
@@ -2166,7 +2187,7 @@ class ServerAPI(object):
Args:
project_name (str): Name of project where entity is.
- entity_type (Literal["folder", "task", "subset", "version"]): The
+ entity_type (Literal["folder", "task", "product", "version"]): The
entity type which should be received.
entity_id (str): Id of entity.
@@ -2191,8 +2212,8 @@ class ServerAPI(object):
def get_rest_task(self, project_name, task_id):
return self.get_rest_entity_by_id(project_name, "task", task_id)
- def get_rest_subset(self, project_name, subset_id):
- return self.get_rest_entity_by_id(project_name, "subset", subset_id)
+ def get_rest_product(self, project_name, product_id):
+ return self.get_rest_entity_by_id(project_name, "product", product_id)
def get_rest_version(self, project_name, version_id):
return self.get_rest_entity_by_id(project_name, "version", version_id)
@@ -2208,10 +2229,10 @@ class ServerAPI(object):
User must be logged in.
Args:
- active (Union[bool, None[): Filter active/inactive projects. Both
+ active (Optional[bool]): Filter active/inactive projects. Both
+ are returned if 'None' is passed.
+ library (Optional[bool]): Filter standard/library projects. Both
are returned if 'None' is passed.
- library (bool): Filter standard/library projects. Both are
- returned if 'None' is passed.
Returns:
List[str]: List of available project names.
@@ -2222,7 +2243,7 @@ class ServerAPI(object):
query_keys["active"] = "true" if active else "false"
if library is not None:
- query_keys["library"] = "true" if active else "false"
+ query_keys["library"] = "true" if library else "false"
query = ""
if query_keys:
query = "?{}".format(",".join([
@@ -2245,14 +2266,14 @@ class ServerAPI(object):
"""Get projects.
Args:
- active (Union[bool, None]): Filter active or inactive projects.
+ active (Optional[bool]): Filter active or inactive projects.
Filter is disabled when 'None' is passed.
- library (Union[bool, None]): Filter library projects. Filter is
+ library (Optional[bool]): Filter library projects. Filter is
disabled when 'None' is passed.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for project.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried projects.
@@ -2289,10 +2310,10 @@ class ServerAPI(object):
Args:
project_name (str): Name of project.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for project.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[Dict[str, Any], None]: Project entity data or None
@@ -2345,7 +2366,7 @@ class ServerAPI(object):
"""Query folders from server.
Todos:
- Folder name won't be unique identifier so we should add folder path
+ Folder name won't be unique identifier, so we should add folder path
filtering.
Notes:
@@ -2353,18 +2374,20 @@ class ServerAPI(object):
Args:
project_name (str): Name of project.
- folder_ids (Iterable[str]): Folder ids to filter.
- folder_paths (Iterable[str]): Folder paths used for filtering.
- folder_names (Iterable[str]): Folder names used for filtering.
- parent_ids (Iterable[str]): Ids of folder parents. Use 'None'
- if folder is direct child of project.
- active (Union[bool, None]): Filter active/inactive folders.
+ folder_ids (Optional[Iterable[str]]): Folder ids to filter.
+ folder_paths (Optional[Iterable[str]]): Folder paths used
+ for filtering.
+ folder_names (Optional[Iterable[str]]): Folder names used
+ for filtering.
+ parent_ids (Optional[Iterable[str]]): Ids of folder parents.
+ Use 'None' if folder is direct child of project.
+ active (Optional[bool]): Filter active/inactive folders.
Both are returned if is set to None.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
folder. All possible folder fields are returned
if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[dict[str, Any]]: Queried folder entities.
@@ -2459,10 +2482,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
folder_id (str): Folder id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Folder entity data or None if was not found.
@@ -2494,10 +2517,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
folder_path (str): Folder path.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Folder entity data or None if was not found.
@@ -2531,10 +2554,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
folder_name (str): Folder name.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Folder entity data or None if was not found.
@@ -2551,21 +2574,21 @@ class ServerAPI(object):
return folder
return None
- def get_folder_ids_with_subsets(self, project_name, folder_ids=None):
- """Find folders which have at least one subset.
+ def get_folder_ids_with_products(self, project_name, folder_ids=None):
+ """Find folders which have at least one product.
- Folders that have at least one subset should be immutable, so they
+ Folders that have at least one product should be immutable, so they
should not change path -> change of name or name of any parent
is not possible.
Args:
project_name (str): Name of project.
- folder_ids (Union[Iterable[str], None]): Limit folder ids filtering
+ folder_ids (Optional[Iterable[str]]): Limit folder ids filtering
to a set of folders. If set to None all folders on project are
checked.
Returns:
- set[str]: Folder ids that have at least one subset.
+ set[str]: Folder ids that have at least one product.
"""
if folder_ids is not None:
@@ -2575,7 +2598,7 @@ class ServerAPI(object):
query = folders_graphql_query({"id"})
query.set_variable_value("projectName", project_name)
- query.set_variable_value("folderHasSubsets", True)
+ query.set_variable_value("folderHasProducts", True)
if folder_ids:
query.set_variable_value("folderIds", list(folder_ids))
@@ -2603,16 +2626,16 @@ class ServerAPI(object):
project_name (str): Name of project.
task_ids (Iterable[str]): Task ids to filter.
task_names (Iterable[str]): Task names used for filtering.
- task_types (Itartable[str]): Task types used for filtering.
+ task_types (Iterable[str]): Task types used for filtering.
folder_ids (Iterable[str]): Ids of task parents. Use 'None'
if folder is direct child of project.
- active (Union[bool, None]): Filter active/inactive tasks.
+ active (Optional[bool]): Filter active/inactive tasks.
Both are returned if is set to None.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
folder. All possible folder fields are returned
if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[dict[str, Any]]: Queried task entities.
@@ -2696,10 +2719,10 @@ class ServerAPI(object):
entities.
folder_id (str): Folder id.
task_name (str): Task name
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Task entity data or None if was not found.
@@ -2729,10 +2752,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
task_id (str): Task id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Task entity data or None if was not found.
@@ -2748,32 +2771,32 @@ class ServerAPI(object):
return task
return None
- def _filter_subset(
- self, project_name, subset, active, own_attributes, use_rest
+ def _filter_product(
+ self, project_name, product, active, own_attributes, use_rest
):
- if active is not None and subset["active"] is not active:
+ if active is not None and product["active"] is not active:
return None
if use_rest:
- subset = self.get_rest_subset(project_name, subset["id"])
+ product = self.get_rest_product(project_name, product["id"])
if own_attributes:
- fill_own_attribs(subset)
+ fill_own_attribs(product)
- return subset
+ return product
- def get_subsets(
+ def get_products(
self,
project_name,
- subset_ids=None,
- subset_names=None,
+ product_ids=None,
+ product_names=None,
folder_ids=None,
names_by_folder_ids=None,
active=True,
fields=None,
own_attributes=False
):
- """Query subsets from server.
+ """Query products from server.
Todos:
Separate 'name_by_folder_ids' filtering to separated method. It
@@ -2781,36 +2804,37 @@ class ServerAPI(object):
Args:
project_name (str): Name of project.
- subset_ids (Iterable[str]): Task ids to filter.
- subset_names (Iterable[str]): Task names used for filtering.
- folder_ids (Iterable[str]): Ids of task parents. Use 'None'
- if folder is direct child of project.
- names_by_folder_ids (dict[str, Iterable[str]]): Subset name
- filtering by folder id.
- active (Union[bool, None]): Filter active/inactive subsets.
+ product_ids (Optional[Iterable[str]]): Task ids to filter.
+ product_names (Optional[Iterable[str]]): Task names used for
+ filtering.
+ folder_ids (Optional[Iterable[str]]): Ids of task parents.
+ Use 'None' if folder is direct child of project.
+ names_by_folder_ids (Optional[dict[str, Iterable[str]]]): Product
+ name filtering by folder id.
+ active (Optional[bool]): Filter active/inactive products.
Both are returned if is set to None.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
folder. All possible folder fields are returned
if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
- Generator[dict[str, Any]]: Queried subset entities.
+ Generator[dict[str, Any]]: Queried product entities.
"""
if not project_name:
return
- if subset_ids is not None:
- subset_ids = set(subset_ids)
- if not subset_ids:
+ if product_ids is not None:
+ product_ids = set(product_ids)
+ if not product_ids:
return
- filter_subset_names = None
- if subset_names is not None:
- filter_subset_names = set(subset_names)
- if not filter_subset_names:
+ filter_product_names = None
+ if product_names is not None:
+ filter_product_names = set(product_names)
+ if not filter_product_names:
return
filter_folder_ids = None
@@ -2819,25 +2843,25 @@ class ServerAPI(object):
if not filter_folder_ids:
return
- # This will disable 'folder_ids' and 'subset_names' filters
+ # This will disable 'folder_ids' and 'product_names' filters
# - maybe could be enhanced in future?
if names_by_folder_ids is not None:
- filter_subset_names = set()
+ filter_product_names = set()
filter_folder_ids = set()
for folder_id, names in names_by_folder_ids.items():
if folder_id and names:
filter_folder_ids.add(folder_id)
- filter_subset_names |= set(names)
+ filter_product_names |= set(names)
- if not filter_subset_names or not filter_folder_ids:
+ if not filter_product_names or not filter_folder_ids:
return
# Convert fields and add minimum required fields
if fields:
fields = set(fields) | {"id"}
else:
- fields = self.get_default_fields_for_type("subset")
+ fields = self.get_default_fields_for_type("product")
use_rest = False
if "data" in fields:
@@ -2862,155 +2886,200 @@ class ServerAPI(object):
if filter_folder_ids:
filters["folderIds"] = list(filter_folder_ids)
- if subset_ids:
- filters["subsetIds"] = list(subset_ids)
+ if product_ids:
+ filters["productIds"] = list(product_ids)
- if filter_subset_names:
- filters["subsetNames"] = list(filter_subset_names)
+ if filter_product_names:
+ filters["productNames"] = list(filter_product_names)
- query = subsets_graphql_query(fields)
+ query = products_graphql_query(fields)
for attr, filter_value in filters.items():
query.set_variable_value(attr, filter_value)
parsed_data = query.query(self)
- subsets = parsed_data.get("project", {}).get("subsets", [])
- # Filter subsets by 'names_by_folder_ids'
+ products = parsed_data.get("project", {}).get("products", [])
+ # Filter products by 'names_by_folder_ids'
if names_by_folder_ids:
- subsets_by_folder_id = collections.defaultdict(list)
- for subset in subsets:
- filtered_subset = self._filter_subset(
- project_name, subset, active, own_attributes, use_rest
+ products_by_folder_id = collections.defaultdict(list)
+ for product in products:
+ filtered_product = self._filter_product(
+ project_name, product, active, own_attributes, use_rest
)
- if filtered_subset is not None:
- folder_id = filtered_subset["folderId"]
- subsets_by_folder_id[folder_id].append(filtered_subset)
+ if filtered_product is not None:
+ folder_id = filtered_product["folderId"]
+ products_by_folder_id[folder_id].append(filtered_product)
for folder_id, names in names_by_folder_ids.items():
- for folder_subset in subsets_by_folder_id[folder_id]:
- if folder_subset["name"] in names:
- yield folder_subset
+ for folder_product in products_by_folder_id[folder_id]:
+ if folder_product["name"] in names:
+ yield folder_product
else:
- for subset in subsets:
- filtered_subset = self._filter_subset(
- project_name, subset, active, own_attributes, use_rest
+ for product in products:
+ filtered_product = self._filter_product(
+ project_name, product, active, own_attributes, use_rest
)
- if filtered_subset is not None:
- yield filtered_subset
+ if filtered_product is not None:
+ yield filtered_product
- def get_subset_by_id(
+ def get_product_by_id(
self,
project_name,
- subset_id,
+ product_id,
fields=None,
own_attributes=False
):
- """Query subset entity by id.
+ """Query product entity by id.
Args:
project_name (str): Name of project where to look for queried
entities.
- subset_id (str): Subset id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ product_id (str): Product id.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
- Union[dict, None]: Subset entity data or None if was not found.
+ Union[dict, None]: Product entity data or None if was not found.
"""
- subsets = self.get_subsets(
+ products = self.get_products(
project_name,
- subset_ids=[subset_id],
+ product_ids=[product_id],
active=None,
fields=fields,
own_attributes=own_attributes
)
- for subset in subsets:
- return subset
+ for product in products:
+ return product
return None
- def get_subset_by_name(
+ def get_product_by_name(
self,
project_name,
- subset_name,
+ product_name,
folder_id,
fields=None,
own_attributes=False
):
- """Query subset entity by name and folder id.
+ """Query product entity by name and folder id.
Args:
project_name (str): Name of project where to look for queried
entities.
- subset_name (str): Subset name.
- folder_id (str): Folder id (Folder is a parent of subsets).
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ product_name (str): Product name.
+ folder_id (str): Folder id (Folder is a parent of products).
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
- Union[dict, None]: Subset entity data or None if was not found.
+ Union[dict, None]: Product entity data or None if was not found.
"""
- subsets = self.get_subsets(
+ products = self.get_products(
project_name,
- subset_names=[subset_name],
+ product_names=[product_name],
folder_ids=[folder_id],
active=None,
fields=fields,
own_attributes=own_attributes
)
- for subset in subsets:
- return subset
+ for product in products:
+ return product
return None
- def get_subset_families(self, project_name, subset_ids=None):
- """Families of subsets from a project.
+ def get_product_types(self, fields=None):
+ """Types of products.
+
+ This is server wide information. Product types have 'name', 'icon' and
+ 'color'.
Args:
- project_name (str): Name of project where to look for queried
- entities.
- subset_ids (Union[None, Iterable[str]]): Limit filtering to set
- of subset ids.
+ fields (Optional[Iterable[str]]): Product types fields to query.
Returns:
- set[str]: Families found on subsets.
+ list[dict[str, Any]]: Product types information.
"""
- if subset_ids is not None:
- subsets = self.get_subsets(
- project_name,
- subset_ids=subset_ids,
- fields=["family"],
- active=None,
- )
- return {
- subset["family"]
- for subset in subsets
- }
+ if not fields:
+ fields = self.get_default_fields_for_type("productType")
- query = GraphQlQuery("SubsetFamilies")
- project_name_var = query.add_variable(
- "projectName", "String!", project_name
- )
- project_query = query.add_field("project")
- project_query.set_filter("name", project_name_var)
- project_query.add_field("subsetFamilies")
+ query = product_types_query(fields)
parsed_data = query.query(self)
- return set(parsed_data.get("project", {}).get("subsetFamilies", []))
+ return parsed_data.get("productTypes", [])
+
+ def get_project_product_types(self, project_name, fields=None):
+ """Types of products available on a project.
+
+ Filter only product types available on project.
+
+ Args:
+ project_name (str): Name of project where to look for
+ product types.
+ fields (Optional[Iterable[str]]): Product types fields to query.
+
+ Returns:
+ list[dict[str, Any]]: Product types information.
+ """
+
+ if not fields:
+ fields = self.get_default_fields_for_type("productType")
+
+ query = project_product_types_query(fields)
+ query.set_variable_value("projectName", project_name)
+
+ parsed_data = query.query(self)
+
+ return parsed_data.get("project", {}).get("productTypes", [])
+
+ def get_product_type_names(self, project_name=None, product_ids=None):
+ """Product type names.
+
+ Warnings:
+ This function will be probably removed. Matters if 'products_id'
+ filter has real use-case.
+
+ Args:
+ project_name (Optional[str]): Name of project where to look for
+ queried entities.
+ product_ids (Optional[Iterable[str]]): Product ids filter. Can be
+ used only with 'project_name'.
+
+ Returns:
+ set[str]: Product type names.
+ """
+
+ if project_name and product_ids:
+ products = self.get_products(
+ project_name,
+ product_ids=product_ids,
+ fields=["productType"],
+ active=None,
+ )
+ return {
+ product["productType"]
+ for product in products
+ }
+
+ return {
+ product_info["name"]
+ for product_info in self.get_project_product_types(
+ project_name, fields=["name"]
+ )
+ }
def get_versions(
self,
project_name,
version_ids=None,
- subset_ids=None,
+ product_ids=None,
versions=None,
hero=True,
standard=True,
@@ -3023,23 +3092,24 @@ class ServerAPI(object):
Args:
project_name (str): Name of project where to look for versions.
- version_ids (Iterable[str]): Version ids used for version
- filtering.
- subset_ids (Iterable[str]): Subset ids used for version filtering.
- versions (Iterable[int]): Versions we're interested in.
- hero (bool): Receive also hero versions when set to true.
- standard (bool): Receive versions which are not hero when
+ version_ids (Optional[Iterable[str]]): Version ids used for
+ version filtering.
+ product_ids (Optional[Iterable[str]]): Product ids used for
+ version filtering.
+ versions (Optional[Iterable[int]]): Versions we're interested in.
+ hero (Optional[bool]): Receive also hero versions when set to true.
+ standard (Optional[bool]): Receive versions which are not hero when
set to true.
- latest (bool): Return only latest version of standard versions.
- This can be combined only with 'standard' attribute
+ latest (Optional[bool]): Return only latest version of standard
+ versions. This can be combined only with 'standard' attribute
set to True.
- active (Union[bool, None]): Receive active/inactive entities.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): Fields to be queried
+ fields (Optional[Iterable[str]]): Fields to be queried
for version. All possible folder fields are returned
if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried version entities.
@@ -3072,13 +3142,13 @@ class ServerAPI(object):
return
filters["versionIds"] = list(version_ids)
- if subset_ids is not None:
- subset_ids = set(subset_ids)
- if not subset_ids:
+ if product_ids is not None:
+ product_ids = set(product_ids)
+ if not product_ids:
return
- filters["subsetIds"] = list(subset_ids)
+ filters["productIds"] = list(product_ids)
- # TODO versions can't be used as fitler at this moment!
+ # TODO versions can't be used as filter at this moment!
if versions is not None:
versions = set(versions)
if not versions:
@@ -3152,10 +3222,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
version_id (str): Version id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Version entity data or None if was not found.
@@ -3177,21 +3247,21 @@ class ServerAPI(object):
self,
project_name,
version,
- subset_id,
+ product_id,
fields=None,
own_attributes=False
):
- """Query version entity by version and subset id.
+ """Query version entity by version and product id.
Args:
project_name (str): Name of project where to look for queried
entities.
version (int): Version of version entity.
- subset_id (str): Subset id. Subset is a parent of version.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ product_id (str): Product id. Product is a parent of version.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Version entity data or None if was not found.
@@ -3199,7 +3269,7 @@ class ServerAPI(object):
versions = self.get_versions(
project_name,
- subset_ids=[subset_id],
+ product_ids=[product_id],
versions=[version],
active=None,
fields=fields,
@@ -3222,10 +3292,10 @@ class ServerAPI(object):
project_name (str): Name of project where to look for queried
entities.
version_id (int): Hero version id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Version entity data or None if was not found.
@@ -3241,25 +3311,25 @@ class ServerAPI(object):
return version
return None
- def get_hero_version_by_subset_id(
+ def get_hero_version_by_product_id(
self,
project_name,
- subset_id,
+ product_id,
fields=None,
own_attributes=False
):
- """Query hero version entity by subset id.
+ """Query hero version entity by product id.
- Only one hero version is available on a subset.
+ Only one hero version is available on a product.
Args:
project_name (str): Name of project where to look for queried
entities.
- subset_id (int): Subset id.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ product_id (int): Product id.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Version entity data or None if was not found.
@@ -3267,7 +3337,7 @@ class ServerAPI(object):
versions = self.get_hero_versions(
project_name,
- subset_ids=[subset_id],
+ product_ids=[product_id],
fields=fields,
own_attributes=own_attributes
)
@@ -3278,7 +3348,7 @@ class ServerAPI(object):
def get_hero_versions(
self,
project_name,
- subset_ids=None,
+ product_ids=None,
version_ids=None,
active=True,
fields=None,
@@ -3286,19 +3356,19 @@ class ServerAPI(object):
):
"""Query hero versions by multiple filters.
- Only one hero version is available on a subset.
+ Only one hero version is available on a product.
Args:
project_name (str): Name of project where to look for queried
entities.
- subset_ids (int): Subset ids.
- version_ids (int): Version ids.
- active (Union[bool, None]): Receive active/inactive entities.
+ product_ids (Optional[Iterable[str]]): Product ids.
+ version_ids (Optional[Iterable[str]]): Version ids.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): Fields that should be returned.
+ fields (Optional[Iterable[str]]): Fields that should be returned.
All fields are returned if 'None' is passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict, None]: Version entity data or None if was not found.
@@ -3307,7 +3377,7 @@ class ServerAPI(object):
return self.get_versions(
project_name,
version_ids=version_ids,
- subset_ids=subset_ids,
+ product_ids=product_ids,
hero=True,
standard=False,
active=active,
@@ -3318,30 +3388,30 @@ class ServerAPI(object):
def get_last_versions(
self,
project_name,
- subset_ids,
+ product_ids,
active=True,
fields=None,
own_attributes=False
):
- """Query last version entities by subset ids.
+ """Query last version entities by product ids.
Args:
project_name (str): Project where to look for representation.
- subset_ids (Iterable[str]): Subset ids.
- active (Union[bool, None]): Receive active/inactive entities.
+ product_ids (Iterable[str]): Product ids.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for representations.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
- dict[str, dict[str, Any]]: Last versions by subset id.
+ dict[str, dict[str, Any]]: Last versions by product id.
"""
versions = self.get_versions(
project_name,
- subset_ids=subset_ids,
+ product_ids=product_ids,
latest=True,
active=active,
fields=fields,
@@ -3352,25 +3422,25 @@ class ServerAPI(object):
for version in versions
}
- def get_last_version_by_subset_id(
+ def get_last_version_by_product_id(
self,
project_name,
- subset_id,
+ product_id,
active=True,
fields=None,
own_attributes=False
):
- """Query last version entity by subset id.
+ """Query last version entity by product id.
Args:
project_name (str): Project where to look for representation.
- subset_id (str): Subset id.
- active (Union[bool, None]): Receive active/inactive entities.
+ product_id (str): Product id.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for representations.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Queried version entity or None.
@@ -3378,7 +3448,7 @@ class ServerAPI(object):
versions = self.get_versions(
project_name,
- subset_ids=[subset_id],
+ product_ids=[product_id],
latest=True,
active=active,
fields=fields,
@@ -3388,27 +3458,27 @@ class ServerAPI(object):
return version
return None
- def get_last_version_by_subset_name(
+ def get_last_version_by_product_name(
self,
project_name,
- subset_name,
+ product_name,
folder_id,
active=True,
fields=None,
own_attributes=False
):
- """Query last version entity by subset name and folder id.
+ """Query last version entity by product name and folder id.
Args:
project_name (str): Project where to look for representation.
- subset_name (str): Subset name.
+ product_name (str): Product name.
folder_id (str): Folder id.
- active (Union[bool, None]): Receive active/inactive entities.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]): fields to be queried
for representations.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Queried version entity or None.
@@ -3417,21 +3487,21 @@ class ServerAPI(object):
if not folder_id:
return None
- subset = self.get_subset_by_name(
- project_name, subset_name, folder_id, fields=["_id"]
+ product = self.get_product_by_name(
+ project_name, product_name, folder_id, fields=["_id"]
)
- if not subset:
+ if not product:
return None
- return self.get_last_version_by_subset_id(
+ return self.get_last_version_by_product_id(
project_name,
- subset["id"],
+ product["id"],
active=active,
fields=fields,
own_attributes=own_attributes
)
def version_is_latest(self, project_name, version_id):
- """Is version latest from a subset.
+ """Is version latest from a product.
Args:
project_name (str): Project where to look for representation.
@@ -3452,13 +3522,13 @@ class ServerAPI(object):
project_query.set_filter("name", project_name_var)
version_query = project_query.add_field("version")
version_query.set_filter("id", version_id_var)
- subset_query = version_query.add_field("subset")
- latest_version_query = subset_query.add_field("latestVersion")
+ product_query = version_query.add_field("product")
+ latest_version_query = product_query.add_field("latestVersion")
latest_version_query.add_field("id")
parsed_data = query.query(self)
latest_version = (
- parsed_data["project"]["version"]["subset"]["latestVersion"]
+ parsed_data["project"]["version"]["product"]["latestVersion"]
)
return latest_version["id"] == version_id
@@ -3481,22 +3551,23 @@ class ServerAPI(object):
Args:
project_name (str): Name of project where to look for versions.
- representation_ids (Iterable[str]): Representation ids used for
- representation filtering.
- representation_names (Iterable[str]): Representation names used for
- representation filtering.
- version_ids (Iterable[str]): Version ids used for
+ representation_ids (Optional[Iterable[str]]): Representation ids
+ used for representation filtering.
+ representation_names (Optional[Iterable[str]]): Representation
+ names used for representation filtering.
+ version_ids (Optional[Iterable[str]]): Version ids used for
representation filtering. Versions are parents of
representations.
- names_by_version_ids (bool): Find representations by names and
- version ids. This filter discard all other filters.
- active (Union[bool, None]): Receive active/inactive entities.
+ names_by_version_ids (Optional[bool]): Find representations
+ by names and version ids. This filter discard all
+ other filters.
+ active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
representation. All possible fields are returned if 'None' is
passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[Dict[str, Any]]: Queried representation entities.
@@ -3594,10 +3665,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where to look for representation.
representation_id (str): Id of representation.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for representations.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Queried representation entity or None.
@@ -3628,10 +3699,10 @@ class ServerAPI(object):
project_name (str): Project where to look for representation.
representation_name (str): Representation name.
version_id (str): Version id.
- fields (Union[Iterable[str], None]): fields to be queried
+ fields (Optional[Iterable[str]]): fields to be queried
for representations.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Queried representation entity or None.
@@ -3674,11 +3745,11 @@ class ServerAPI(object):
}
version_fields = self.get_default_fields_for_type("version")
- subset_fields = self.get_default_fields_for_type("subset")
+ product_fields = self.get_default_fields_for_type("product")
folder_fields = self.get_default_fields_for_type("folder")
query = representations_parents_qraphql_query(
- version_fields, subset_fields, folder_fields
+ version_fields, product_fields, folder_fields
)
query.set_variable_value("projectName", project_name)
query.set_variable_value("representationIds", list(repre_ids))
@@ -3687,10 +3758,10 @@ class ServerAPI(object):
for repre in parsed_data["project"]["representations"]:
repre_id = repre["id"]
version = repre.pop("version")
- subset = version.pop("subset")
- folder = subset.pop("folder")
+ product = version.pop("product")
+ folder = product.pop("folder")
output[repre_id] = RepresentationParents(
- version, subset, folder, project
+ version, product, folder, project
)
return output
@@ -3726,9 +3797,10 @@ class ServerAPI(object):
"""Find representation ids which match passed context filters.
Each representation has context integrated on representation entity in
- database. The context may contain project, folder, task name or subset,
- family and many more. This implementation gives option to quickly
- filter representation based on representation data in database.
+ database. The context may contain project, folder, task name or
+ product name, product type and many more. This implementation gives
+ option to quickly filter representation based on representation data
+ in database.
Context filters have defined structure. To define filter of nested
subfield use dot '.' as delimiter (For example 'task.name').
@@ -3737,10 +3809,11 @@ class ServerAPI(object):
Args:
project_name (str): Project where to look for representations.
context_filters (dict[str, list[str]]): Filters of context fields.
- representation_names (Iterable[str]): Representation names, can be
- used as additional filter for representations by their names.
- version_ids (Iterable[str]): Version ids, can be used as additional
- filter for representations by their parent ids.
+ representation_names (Optional[Iterable[str]]): Representation
+ names, can be used as additional filter for representations
+ by their names.
+ version_ids (Optional[Iterable[str]]): Version ids, can be used
+ as additional filter for representations by their parent ids.
Returns:
list[str]: Representation ids that match passed filters.
@@ -3752,7 +3825,7 @@ class ServerAPI(object):
>>> project_name = "testProject"
>>> filters = {
... "task.name": ["[aA]nimation"],
- ... "subset": [".*[Mm]ain"]
+ ... "product": [".*[Mm]ain"]
... }
>>> repre_ids = get_repre_ids_by_context_filters(
... project_name, filters)
@@ -3818,11 +3891,11 @@ class ServerAPI(object):
workfile_ids (Optional[Iterable[str]]): Workfile ids.
task_ids (Optional[Iterable[str]]): Task ids.
paths (Optional[Iterable[str]]): Rootless workfiles paths.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
representation. All possible fields are returned if 'None' is
passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Generator[dict[str, Any]]: Queried workfile info entites.
@@ -3873,11 +3946,11 @@ class ServerAPI(object):
project_name (str): Project under which the entity is located.
task_id (str): Task id.
path (str): Rootless workfile path.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
representation. All possible fields are returned if 'None' is
passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Workfile info entity or None.
@@ -3904,11 +3977,11 @@ class ServerAPI(object):
Args:
project_name (str): Project under which the entity is located.
workfile_id (str): Workfile info id.
- fields (Union[Iterable[str], None]): Fields to be queried for
+ fields (Optional[Iterable[str]]): Fields to be queried for
representation. All possible fields are returned if 'None' is
passed.
- own_attributes (bool): Attribute values that are not explicitly set
- on entity will have 'None' value.
+ own_attributes (Optional[bool]): Attribute values that are
+ not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Workfile info entity or None.
@@ -3944,18 +4017,18 @@ class ServerAPI(object):
methods 'get_folder_thumbnail', 'get_version_thumbnail' or
'get_workfile_thumbnail'.
We do recommend pass thumbnail id if you have access to it. Each
- entity that allows thumbnails has 'thumbnailId' field so it can
- be queried.
+ entity that allows thumbnails has 'thumbnailId' field, so it
+ can be queried.
Args:
project_name (str): Project under which the entity is located.
entity_type (str): Entity type which passed entity id represents.
entity_id (str): Entity id for which thumbnail should be returned.
- thumbnail_id (str): Prepared thumbnail id from entity. Used only
- to check if thumbnail was already cached.
+ thumbnail_id (Optional[str]): Prepared thumbnail id from entity.
+ Used only to check if thumbnail was already cached.
Returns:
- Union[str, None]: Path to downlaoded thumbnail or none if entity
+ Union[str, None]: Path to downloaded thumbnail or none if entity
does not have any (or if user does not have permissions).
"""
@@ -3989,7 +4062,7 @@ class ServerAPI(object):
if thumbnail_id is None:
return None
- # Cache thumbnail and return it's path
+ # Cache thumbnail and return path
return self._thumbnail_cache.store_thumbnail(
project_name,
thumbnail_id,
@@ -4005,11 +4078,11 @@ class ServerAPI(object):
Args:
project_name (str): Project under which the entity is located.
folder_id (str): Folder id for which thumbnail should be returned.
- thumbnail_id (str): Prepared thumbnail id from entity. Used only
- to check if thumbnail was already cached.
+ thumbnail_id (Optional[str]): Prepared thumbnail id from entity.
+ Used only to check if thumbnail was already cached.
Returns:
- Union[str, None]: Path to downlaoded thumbnail or none if entity
+ Union[str, None]: Path to downloaded thumbnail or none if entity
does not have any (or if user does not have permissions).
"""
@@ -4026,11 +4099,11 @@ class ServerAPI(object):
project_name (str): Project under which the entity is located.
version_id (str): Version id for which thumbnail should be
returned.
- thumbnail_id (str): Prepared thumbnail id from entity. Used only
- to check if thumbnail was already cached.
+ thumbnail_id (Optional[str]): Prepared thumbnail id from entity.
+ Used only to check if thumbnail was already cached.
Returns:
- Union[str, None]: Path to downlaoded thumbnail or none if entity
+ Union[str, None]: Path to downloaded thumbnail or none if entity
does not have any (or if user does not have permissions).
"""
@@ -4047,11 +4120,11 @@ class ServerAPI(object):
project_name (str): Project under which the entity is located.
workfile_id (str): Worfile id for which thumbnail should be
returned.
- thumbnail_id (str): Prepared thumbnail id from entity. Used only
- to check if thumbnail was already cached.
+ thumbnail_id (Optional[str]): Prepared thumbnail id from entity.
+ Used only to check if thumbnail was already cached.
Returns:
- Union[str, None]: Path to downlaoded thumbnail or none if entity
+ Union[str, None]: Path to downloaded thumbnail or none if entity
does not have any (or if user does not have permissions).
"""
@@ -4089,7 +4162,7 @@ class ServerAPI(object):
project_name (str): Project where the thumbnail will be created
and can be used.
src_filepath (str): Filepath to thumbnail which should be uploaded.
- thumbnail_id (str): Prepared if of thumbnail.
+ thumbnail_id (Optional[str]): Prepared if of thumbnail.
Returns:
str: Created thumbnail id.
@@ -4161,7 +4234,7 @@ class ServerAPI(object):
This project creation function is not validating project entity on
creation. It is because project entity is created blindly with only
- minimum required information about project which is it's name, code.
+ minimum required information about project which is name and code.
Entered project name must be unique and project must not exist yet.
@@ -4172,9 +4245,9 @@ class ServerAPI(object):
Args:
project_name (str): New project name. Should be unique.
project_code (str): Project's code should be unique too.
- library_project (bool): Project is library project.
- preset_name (str): Name of anatomy preset. Default is used if not
- passed.
+ library_project (Optional[bool]): Project is library project.
+ preset_name (Optional[str]): Name of anatomy preset. Default is
+ used if not passed.
Raises:
ValueError: When project name already exists.
@@ -4498,12 +4571,12 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- entity_type (Literal["folder", "task", "subset",
+ entity_type (Literal["folder", "task", "product",
"version", "representations"]): Entity type.
- entity_ids (Union[Iterable[str], None]): Ids of entities for which
+ entity_ids (Optional[Iterable[str]]): Ids of entities for which
links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4518,10 +4591,10 @@ class ServerAPI(object):
query_func = tasks_graphql_query
id_filter_key = "taskIds"
project_sub_key = "tasks"
- elif entity_type == "subset":
- query_func = subsets_graphql_query
- id_filter_key = "subsetIds"
- project_sub_key = "subsets"
+ elif entity_type == "product":
+ query_func = products_graphql_query
+ id_filter_key = "productIds"
+ project_sub_key = "products"
elif entity_type == "version":
query_func = versions_graphql_query
id_filter_key = "versionIds"
@@ -4534,7 +4607,7 @@ class ServerAPI(object):
raise ValueError("Unknown type \"{}\". Expected {}".format(
entity_type,
", ".join(
- ("folder", "task", "subset", "version", "representation")
+ ("folder", "task", "product", "version", "representation")
)
))
@@ -4572,10 +4645,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- folder_ids (Union[Iterable[str], None]): Ids of folders for which
+ folder_ids (Optional[Iterable[str]]): Ids of folders for which
links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4597,9 +4670,9 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- folder_id (str): Id of folder for which links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ folder_id (str): Folder id for which links should be received.
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4621,10 +4694,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- task_ids (Union[Iterable[str], None]): Ids of tasks for which
+ task_ids (Optional[Iterable[str]]): Ids of tasks for which
links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4646,9 +4719,9 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- task_id (str): Id of task for which links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ task_id (str): Task id for which links should be received.
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4659,54 +4732,54 @@ class ServerAPI(object):
project_name, [task_id], link_types, link_direction
)[task_id]
- def get_subsets_links(
+ def get_products_links(
self,
project_name,
- subset_ids=None,
+ product_ids=None,
link_types=None,
link_direction=None
):
- """Query subsets links from server.
+ """Query products links from server.
Args:
project_name (str): Project where links are.
- subset_ids (Union[Iterable[str], None]): Ids of subsets for which
+ product_ids (Optional[Iterable[str]]): Ids of products for which
links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
- dict[str, list[dict[str, Any]]]: Link info by subset ids.
+ dict[str, list[dict[str, Any]]]: Link info by product ids.
"""
return self.get_entities_links(
- project_name, "subset", subset_ids, link_types, link_direction
+ project_name, "product", product_ids, link_types, link_direction
)
- def get_subset_links(
+ def get_product_links(
self,
project_name,
- subset_id,
+ product_id,
link_types=None,
link_direction=None
):
- """Query subset links from server.
+ """Query product links from server.
Args:
project_name (str): Project where links are.
- subset_id (str): Id of subset for which links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ product_id (str): Product id for which links should be received.
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
- list[dict[str, Any]]: Link info of subset.
+ list[dict[str, Any]]: Link info of product.
"""
- return self.get_subsets_links(
- project_name, [subset_id], link_types, link_direction
- )[subset_id]
+ return self.get_products_links(
+ project_name, [product_id], link_types, link_direction
+ )[product_id]
def get_versions_links(
self,
@@ -4719,10 +4792,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- version_ids (Union[Iterable[str], None]): Ids of versions for which
+ version_ids (Optional[Iterable[str]]): Ids of versions for which
links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4744,9 +4817,9 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- version_id (str): Id of version for which links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ version_id (str): Version id for which links should be received.
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4768,10 +4841,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- representation_ids (Union[Iterable[str], None]): Ids of
+ representation_ids (Optional[Iterable[str]]): Ids of
representations for which links should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4797,10 +4870,10 @@ class ServerAPI(object):
Args:
project_name (str): Project where links are.
- representation_id (str): Id of representation for which links
+ representation_id (str): Representation id for which links
should be received.
- link_types (Union[Iterable[str], None]): Link type filters.
- link_direction (Union[Literal["in", "out"], None]): Link direction
+ link_types (Optional[Iterable[str]]): Link type filters.
+ link_direction (Optional[Literal["in", "out"]]): Link direction
filter.
Returns:
@@ -4829,11 +4902,11 @@ class ServerAPI(object):
project_name (str): On which project should be operations
processed.
operations (list[dict[str, Any]]): Operations to be processed.
- can_fail (bool): Server will try to process all operations even if
- one of them fails.
- raise_on_fail (bool): Raise exception if an operation fails.
- You can handle failed operations on your own when set to
- 'False'.
+ can_fail (Optional[bool]): Server will try to process all
+ operations even if one of them fails.
+ raise_on_fail (Optional[bool]): Raise exception if an operation
+ fails. You can handle failed operations on your own
+ when set to 'False'.
Raises:
ValueError: Operations can't be converted to json string.
diff --git a/openpype/vendor/python/common/ayon_api/utils.py b/openpype/vendor/python/common/ayon_api/utils.py
index 28971f7de5..d1f108a220 100644
--- a/openpype/vendor/python/common/ayon_api/utils.py
+++ b/openpype/vendor/python/common/ayon_api/utils.py
@@ -22,7 +22,7 @@ SLUGIFY_SEP_WHITELIST = " ,./\\;:!|*^#@~+-_="
RepresentationParents = collections.namedtuple(
"RepresentationParents",
- ("version", "subset", "folder", "project")
+ ("version", "product", "folder", "project")
)
diff --git a/openpype/vendor/python/common/ayon_api/version.py b/openpype/vendor/python/common/ayon_api/version.py
index 9b38175335..d464469cf7 100644
--- a/openpype/vendor/python/common/ayon_api/version.py
+++ b/openpype/vendor/python/common/ayon_api/version.py
@@ -1,2 +1,2 @@
"""Package declaring Python API for Ayon server."""
-__version__ = "0.1.18"
+__version__ = "0.2.0"