Skip to content

Commit 4b24295

Browse files
committed
Merge branch 'develop'
2 parents 7613bfc + ba937a8 commit 4b24295

6 files changed

Lines changed: 158 additions & 22 deletions

File tree

ayon_api/entity_hub.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,15 @@ def query_entities_from_server(self):
589589
parent_id = task["folderId"]
590590
tasks_by_parent_id[parent_id].append(task)
591591

592+
lock_queue = collections.deque()
592593
hierarchy_queue = collections.deque()
593594
hierarchy_queue.append((None, project_entity))
594595
while hierarchy_queue:
595596
item = hierarchy_queue.popleft()
596597
parent_id, parent_entity = item
597598

599+
lock_queue.append(parent_entity)
600+
598601
children_ids = set()
599602
for folder in folders_by_parent_id[parent_id]:
600603
folder_entity = self.add_folder(folder)
@@ -604,10 +607,16 @@ def query_entities_from_server(self):
604607

605608
for task in tasks_by_parent_id[parent_id]:
606609
task_entity = self.add_task(task)
610+
lock_queue.append(task_entity)
607611
children_ids.add(task_entity.id)
608612

609613
parent_entity.fill_children_ids(children_ids)
610-
self.lock()
614+
615+
# Lock entities when all are added to hub
616+
# - lock only entities added in this method
617+
while lock_queue:
618+
entity = lock_queue.popleft()
619+
entity.lock()
611620

612621
def lock(self):
613622
if self._project_entity is None:
@@ -1198,6 +1207,7 @@ def lock(self):
11981207
self._attribs.lock()
11991208

12001209
self._immutable_for_hierarchy_cache = None
1210+
self._created = False
12011211

12021212
def _get_entity_by_id(self, entity_id):
12031213
return self._entity_hub.get_entity_by_id(entity_id)

ayon_api/graphql_queries.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ def representations_graphql_query(fields):
314314
def representations_parents_qraphql_query(
315315
version_fields, subset_fields, folder_fields
316316
):
317-
318317
query = GraphQlQuery("RepresentationsParentsQuery")
319318

320319
project_name_var = query.add_variable("projectName", "String!")
@@ -388,7 +387,7 @@ def workfiles_info_graphql_query(fields):
388387

389388

390389
def events_graphql_query(fields):
391-
query = GraphQlQuery("WorkfilesInfo")
390+
query = GraphQlQuery("Events")
392391
topics_var = query.add_variable("eventTopics", "[String!]")
393392
projects_var = query.add_variable("projectNames", "[String!]")
394393
states_var = query.add_variable("eventStates", "[String!]")

ayon_api/server_api.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
HTTPStatus = None
1515

1616
import requests
17+
from requests.exceptions import JSONDecodeError as RequestsJSONDecodeError
1718

1819
from .constants import (
1920
DEFAULT_PROJECT_FIELDS,
@@ -112,9 +113,9 @@ def headers(self):
112113
@property
113114
def data(self):
114115
if self._data is None:
115-
if self.status != 204:
116+
try:
116117
self._data = self.orig_response.json()
117-
else:
118+
except RequestsJSONDecodeError:
118119
self._data = {}
119120
return self._data
120121

@@ -128,7 +129,10 @@ def content_type(self):
128129

129130
@property
130131
def detail(self):
131-
return self.get("detail", _get_description(self))
132+
detail = self.get("detail")
133+
if detail:
134+
return detail
135+
return _get_description(self)
132136

133137
@property
134138
def status_code(self):
@@ -299,14 +303,6 @@ class ServerAPI(object):
299303
'production').
300304
"""
301305

302-
_entity_types_link_mapping = {
303-
"folder": ("folderIds", "folders"),
304-
"task": ("taskIds", "tasks"),
305-
"subset": ("subsetIds", "subsets"),
306-
"version": ("versionIds", "versions"),
307-
"representation": ("representationIds", "representations"),
308-
}
309-
310306
def __init__(
311307
self,
312308
base_url,
@@ -916,7 +912,7 @@ def get_events(
916912
project_names = set(project_names)
917913
if not project_names:
918914
return
919-
filters["projectName"] = list(project_names)
915+
filters["projectNames"] = list(project_names)
920916

921917
if states is not None:
922918
states = set(states)
@@ -4514,13 +4510,34 @@ def get_entities_links(
45144510
dict[str, list[dict[str, Any]]]: Link info by entity ids.
45154511
"""
45164512

4517-
mapped_type = self._entity_types_link_mapping.get(entity_type)
4518-
if not mapped_type:
4513+
if entity_type == "folder":
4514+
query_func = folders_graphql_query
4515+
id_filter_key = "folderIds"
4516+
project_sub_key = "folders"
4517+
elif entity_type == "task":
4518+
query_func = tasks_graphql_query
4519+
id_filter_key = "taskIds"
4520+
project_sub_key = "tasks"
4521+
elif entity_type == "subset":
4522+
query_func = subsets_graphql_query
4523+
id_filter_key = "subsetIds"
4524+
project_sub_key = "subsets"
4525+
elif entity_type == "version":
4526+
query_func = versions_graphql_query
4527+
id_filter_key = "versionIds"
4528+
project_sub_key = "versions"
4529+
elif entity_type == "representation":
4530+
query_func = representations_graphql_query
4531+
id_filter_key = "representationIds"
4532+
project_sub_key = "representations"
4533+
else:
45194534
raise ValueError("Unknown type \"{}\". Expected {}".format(
4520-
entity_type, ", ".join(self._entity_types_link_mapping.keys())
4535+
entity_type,
4536+
", ".join(
4537+
("folder", "task", "subset", "version", "representation")
4538+
)
45214539
))
45224540

4523-
id_filter_key, project_sub_key = mapped_type
45244541
output = collections.defaultdict(list)
45254542
filters = {
45264543
"projectName": project_name
@@ -4534,7 +4551,7 @@ def get_entities_links(
45344551
if not self._prepare_link_filters(filters, link_types, link_direction):
45354552
return output
45364553

4537-
query = folders_graphql_query({"id", "links"})
4554+
query = query_func({"id", "links"})
45384555
for attr, filter_value in filters.items():
45394556
query.set_variable_value(attr, filter_value)
45404557

ayon_api/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""Package declaring Python API for Ayon server."""
2-
__version__ = "0.1.17"
2+
__version__ = "0.1.18"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "ayon_api"
3-
version = "0.1.17"
3+
version = "0.1.18"
44
description = "Python api for AYON server"
55
authors = ["ynput.io <info@ynput.io>"]
66

tests/test_graphql_queries.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import pytest
2+
from ayon_api.graphql import GraphQlQuery
3+
from ayon_api.graphql_queries import (
4+
project_graphql_query,
5+
folders_graphql_query,
6+
)
7+
8+
9+
@pytest.fixture
10+
def empty_query():
11+
return GraphQlQuery("ProjectQuery")
12+
13+
14+
@pytest.fixture
15+
def project_query():
16+
return project_graphql_query(["name"])
17+
18+
19+
@pytest.fixture
20+
def folder_query():
21+
return folders_graphql_query(["name"])
22+
23+
24+
def test_simple_duplicate_add_variable_exception(empty_query):
25+
key, value_type = "someVariable", "String"
26+
empty_query.add_variable(key, value_type)
27+
with pytest.raises(KeyError):
28+
empty_query.add_variable(key, value_type)
29+
30+
31+
def test_exception_empty_query(empty_query):
32+
with pytest.raises(ValueError, match="Missing fields to query"):
33+
out = empty_query.calculate_query()
34+
35+
36+
def test_simple_output(project_query):
37+
result = project_query.calculate_query()
38+
expected = "query ProjectQuery {\n project {\n name\n }\n}"
39+
assert result == expected
40+
41+
42+
def make_project_query(keys, values, types):
43+
query = project_graphql_query(["name"])
44+
45+
# Function 'project_graphql_query' always adds 'projectName' variable
46+
inserted = {"projectName"}
47+
for key, value_type, value in zip(keys, types, values):
48+
if key not in inserted:
49+
inserted.add(key)
50+
query.add_variable(key, value_type)
51+
query.set_variable_value(key, value)
52+
53+
return query
54+
55+
56+
def make_expected_get_variables_values(keys, values):
57+
return dict(zip(keys, values))
58+
59+
60+
@pytest.mark.parametrize(
61+
"keys, values, types",
62+
[
63+
(["projectName", "projectId", "numOf"],
64+
["kuba_v4_sync", "0x23", 3],
65+
["[String!]", "[String!]", "Int"]),
66+
(["projectName", "testStrInt"],
67+
["my_name", 42],
68+
["[String!]", "[String!]"]),
69+
(["projectName", "testIntStr"],
70+
["my_name", "test_123"],
71+
["[String!]", "Int"]),
72+
])
73+
def test_get_variables_values(keys, values, types):
74+
query = make_project_query(keys, values, types)
75+
# None means: unexpected exception thrown while adding variables
76+
assert query is not None
77+
78+
expected = make_expected_get_variables_values(keys, values)
79+
assert query.get_variables_values() == expected
80+
81+
82+
"""
83+
def test_filtering(empty_query):
84+
assert empty_query._children == []
85+
project_name_var = empty_query.add_variable("projectName", "String!")
86+
project_field = empty_query.add_field("project")
87+
project_field.set_filter("name", project_name_var)
88+
89+
for field in empty_query._children:
90+
print(field.get_filters())
91+
92+
print(empty_query.calculate_query())
93+
94+
95+
def print_rec_filters(field):
96+
print(field.get_filters())
97+
for k in field._children:
98+
print_rec_filters(k)
99+
100+
101+
def test_folders_graphql_query(folder_query):
102+
print(folder_query.calculate_query())
103+
104+
105+
def test_filters(folder_query):
106+
print(folder_query._children[0]._children[0].get_filters())
107+
folder_query._children[0]._children[0].remove_filter("ids")
108+
print(folder_query._children[0]._children[0].get_filters())
109+
print(folder_query.calculate_query())
110+
"""

0 commit comments

Comments
 (0)