Skip to content
2 changes: 2 additions & 0 deletions ayon_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
get_server_version,
get_server_version_tuple,
is_product_base_type_supported,
links_graphql_support_data,
get_users,
get_user_by_name,
get_user,
Expand Down Expand Up @@ -339,6 +340,7 @@
"get_server_version",
"get_server_version_tuple",
"is_product_base_type_supported",
"links_graphql_support_data",
"get_users",
"get_user_by_name",
"get_user",
Expand Down
7 changes: 7 additions & 0 deletions ayon_api/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,13 @@ def is_product_base_type_supported() -> bool:
return con.is_product_base_type_supported()


def links_graphql_support_data() -> bool:
"""Links data can be received by GraphQl.
"""
con = get_server_api_connection()
return con.links_graphql_support_data()


def get_users(
project_name: Optional[str] = None,
usernames: Optional[Iterable[str]] = None,
Expand Down
6 changes: 6 additions & 0 deletions ayon_api/_api_helpers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ def log(self) -> logging.Logger:
def is_product_base_type_supported(self) -> bool:
raise NotImplementedError()

def links_graphql_support_data(self) -> bool:
raise NotImplementedError()

def get_server_version(self) -> str:
raise NotImplementedError()

Expand Down Expand Up @@ -142,6 +145,9 @@ def _prepare_fields(
):
raise NotImplementedError()

def _prepare_link_fields(self, fields: set[str]) -> None:
raise NotImplementedError()

def _prepare_advanced_filters(
self, filters: Union[str, dict[str, Any], None]
) -> Optional[str]:
Expand Down
2 changes: 2 additions & 0 deletions ayon_api/_api_helpers/folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ def get_folders(
if own_attributes:
fields.add("ownAttrib")

self._prepare_link_fields(fields)

query = folders_graphql_query(fields)
for attr, filter_value in graphql_filters.items():
query.set_variable_value(attr, filter_value)
Expand Down
1 change: 1 addition & 0 deletions ayon_api/_api_helpers/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ def get_entities_links(
return output

link_fields = {"id", "links"}
self._prepare_link_fields(link_fields)
query = query_func(link_fields)
for attr, filter_value in filters.items():
query.set_variable_value(attr, filter_value)
Expand Down
2 changes: 2 additions & 0 deletions ayon_api/_api_helpers/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ def get_products(
if filter_value:
graphql_filters[filter_key] = filter_value

self._prepare_link_fields(fields)

query = products_graphql_query(fields)
for attr, filter_value in graphql_filters.items():
query.set_variable_value(attr, filter_value)
Expand Down
2 changes: 2 additions & 0 deletions ayon_api/_api_helpers/representations.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ def get_representations(
fields.discard("files")
fields |= REPRESENTATION_FILES_FIELDS

self._prepare_link_fields(fields)

graphql_filters = {
"projectName": project_name
}
Expand Down
4 changes: 4 additions & 0 deletions ayon_api/_api_helpers/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ def get_tasks(
if active is not None:
fields.add("active")

self._prepare_link_fields(fields)

query = tasks_graphql_query(fields)
for attr, filter_value in graphql_filters.items():
query.set_variable_value(attr, filter_value)
Expand Down Expand Up @@ -267,6 +269,8 @@ def get_tasks_by_folder_paths(
if active is not None:
fields.add("active")

self._prepare_link_fields(fields)

query = tasks_by_folder_paths_graphql_query(fields)
for attr, filter_value in graphql_filters.items():
query.set_variable_value(attr, filter_value)
Expand Down
3 changes: 2 additions & 1 deletion ayon_api/_api_helpers/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def get_versions(
if active is not None:
fields.add("active")

self._prepare_link_fields(fields)

if own_attributes is not _PLACEHOLDER:
warnings.warn(
(
Expand Down Expand Up @@ -116,7 +118,6 @@ def get_versions(
):
return


filters = self._prepare_advanced_filters(filters)
if filters:
graphql_filters["filter"] = filters
Expand Down
2 changes: 2 additions & 0 deletions ayon_api/_api_helpers/workfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def get_workfile_entities(
fields = set(fields)
self._prepare_fields("workfile", fields)

self._prepare_link_fields(fields)

query = workfiles_info_graphql_query(fields)

for attr, filter_value in filters.items():
Expand Down
35 changes: 25 additions & 10 deletions ayon_api/graphql_queries.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
from __future__ import annotations

import collections
import typing

from .constants import DEFAULT_LINK_FIELDS
from .graphql import FIELD_VALUE, GraphQlQuery, fields_to_dict

if typing.TYPE_CHECKING:
from .graphql import (
GraphQlQueryEdgeField,
)


def add_links_fields(entity_field, nested_fields):
def add_links_fields(
entity_field: GraphQlQueryEdgeField,
nested_fields: dict | None,
) -> None:
if "links" not in nested_fields:
return
links_fields = nested_fields.pop("links")

link_edge_fields = set(DEFAULT_LINK_FIELDS)

if isinstance(links_fields, dict):
simple_fields = set(links_fields)
simple_variant = len(simple_fields - link_edge_fields) == 0
diff = simple_fields - link_edge_fields
diff.discard("data")
simple_variant = len(diff) == 0
else:
simple_variant = True
simple_fields = link_edge_fields
Expand Down Expand Up @@ -121,7 +134,7 @@ def product_types_query(fields):
return query


def folders_graphql_query(fields):
def folders_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("FoldersQuery")
project_name_var = query.add_variable("projectName", "String!")
folder_ids_var = query.add_variable("folderIds", "[String!]")
Expand Down Expand Up @@ -161,6 +174,7 @@ def folders_graphql_query(fields):
folders_field.set_filter("filter", filter_var)

nested_fields = fields_to_dict(fields)

add_links_fields(folders_field, nested_fields)

query_queue = collections.deque()
Expand All @@ -179,7 +193,7 @@ def folders_graphql_query(fields):
return query


def tasks_graphql_query(fields):
def tasks_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("TasksQuery")
project_name_var = query.add_variable("projectName", "String!")
task_ids_var = query.add_variable("taskIds", "[String!]")
Expand Down Expand Up @@ -227,7 +241,7 @@ def tasks_graphql_query(fields):
return query


def tasks_by_folder_paths_graphql_query(fields):
def tasks_by_folder_paths_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("TasksByFolderPathQuery")
project_name_var = query.add_variable("projectName", "String!")
task_names_var = query.add_variable("taskNames", "[String!]")
Expand Down Expand Up @@ -258,6 +272,7 @@ def tasks_by_folder_paths_graphql_query(fields):
tasks_field.set_filter("filter", filter_var)

nested_fields = fields_to_dict(fields)

add_links_fields(tasks_field, nested_fields)

query_queue = collections.deque()
Expand All @@ -276,7 +291,7 @@ def tasks_by_folder_paths_graphql_query(fields):
return query


def products_graphql_query(fields):
def products_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("ProductsQuery")

project_name_var = query.add_variable("projectName", "String!")
Expand Down Expand Up @@ -326,7 +341,7 @@ def products_graphql_query(fields):
return query


def versions_graphql_query(fields):
def versions_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("VersionsQuery")

project_name_var = query.add_variable("projectName", "String!")
Expand Down Expand Up @@ -377,7 +392,7 @@ def versions_graphql_query(fields):
return query


def representations_graphql_query(fields):
def representations_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("RepresentationsQuery")

project_name_var = query.add_variable("projectName", "String!")
Expand Down Expand Up @@ -525,7 +540,7 @@ def representations_hierarchy_qraphql_query(
return query


def workfiles_info_graphql_query(fields):
def workfiles_info_graphql_query(fields: set[str]) -> GraphQlQuery:
query = GraphQlQuery("WorkfilesInfo")
project_name_var = query.add_variable("projectName", "String!")
workfiles_info_ids = query.add_variable("workfileIds", "[String!]")
Expand Down
22 changes: 22 additions & 0 deletions ayon_api/server_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
DEFAULT_ACTIVITY_FIELDS,
DEFAULT_USER_FIELDS,
DEFAULT_ENTITY_LIST_FIELDS,
DEFAULT_LINK_FIELDS,
)
from .graphql import INTROSPECTION_QUERY
from .graphql_queries import users_graphql_query
Expand Down Expand Up @@ -329,6 +330,7 @@ def __init__(

self._graphql_allows_traits_in_representations: Optional[bool] = None
self._product_base_type_supported = None
self._links_graphql_support_data = None

self._session = None

Expand Down Expand Up @@ -922,6 +924,15 @@ def is_product_base_type_supported(self) -> bool:
)
return self._product_base_type_supported

def links_graphql_support_data(self) -> bool:
"""Links data can be received by GraphQl."""
if self._links_graphql_support_data is None:
major, minor, patch, _, _ = self.server_version_tuple
self._links_graphql_support_data = (
(major, minor, patch) >= (1, 14, 2)
)
return self._links_graphql_support_data

def _get_user_info(self) -> Optional[dict[str, Any]]:
if self._access_token is None:
return None
Expand Down Expand Up @@ -2445,6 +2456,17 @@ def _prepare_fields(
)
}

def _prepare_link_fields(self, fields: set[str]) -> None:
if "links" not in fields:
return

fields.discard("links")
for field in DEFAULT_LINK_FIELDS:
fields.add(f"links.{field}")

if self.links_graphql_support_data():
fields.add("links.data")

def _prepare_advanced_filters(
self, filters: Union[str, dict[str, Any], None]
) -> Optional[str]:
Expand Down
Loading