ayon-python-api 1.2.15__py3-none-any.whl → 1.2.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ayon_api/__init__.py +4 -0
- ayon_api/_api.py +24 -2
- ayon_api/_api_helpers/attributes.py +99 -30
- ayon_api/_api_helpers/base.py +2 -1
- ayon_api/_api_helpers/lists.py +14 -17
- ayon_api/_api_helpers/projects.py +31 -21
- ayon_api/constants.py +0 -4
- ayon_api/server_api.py +54 -36
- ayon_api/version.py +1 -1
- {ayon_python_api-1.2.15.dist-info → ayon_python_api-1.2.16.dist-info}/METADATA +1 -1
- {ayon_python_api-1.2.15.dist-info → ayon_python_api-1.2.16.dist-info}/RECORD +14 -14
- {ayon_python_api-1.2.15.dist-info → ayon_python_api-1.2.16.dist-info}/WHEEL +0 -0
- {ayon_python_api-1.2.15.dist-info → ayon_python_api-1.2.16.dist-info}/licenses/LICENSE +0 -0
- {ayon_python_api-1.2.15.dist-info → ayon_python_api-1.2.16.dist-info}/top_level.txt +0 -0
ayon_api/__init__.py
CHANGED
|
@@ -148,6 +148,8 @@ from ._api import (
|
|
|
148
148
|
enroll_event_job,
|
|
149
149
|
get_attributes_schema,
|
|
150
150
|
reset_attributes_schema,
|
|
151
|
+
reset_attributes_cache,
|
|
152
|
+
set_attributes_cache_timeout,
|
|
151
153
|
set_attribute_config,
|
|
152
154
|
remove_attribute_config,
|
|
153
155
|
get_attributes_for_type,
|
|
@@ -433,6 +435,8 @@ __all__ = (
|
|
|
433
435
|
"enroll_event_job",
|
|
434
436
|
"get_attributes_schema",
|
|
435
437
|
"reset_attributes_schema",
|
|
438
|
+
"reset_attributes_cache",
|
|
439
|
+
"set_attributes_cache_timeout",
|
|
436
440
|
"set_attribute_config",
|
|
437
441
|
"remove_attribute_config",
|
|
438
442
|
"get_attributes_for_type",
|
ayon_api/_api.py
CHANGED
|
@@ -55,7 +55,6 @@ if typing.TYPE_CHECKING:
|
|
|
55
55
|
EnrollEventData,
|
|
56
56
|
AttributeScope,
|
|
57
57
|
AttributeSchemaDataDict,
|
|
58
|
-
AttributeSchemaDict,
|
|
59
58
|
AttributesSchemaDict,
|
|
60
59
|
AddonsInfoDict,
|
|
61
60
|
InstallersInfoDict,
|
|
@@ -3582,10 +3581,30 @@ def get_attributes_schema(
|
|
|
3582
3581
|
|
|
3583
3582
|
|
|
3584
3583
|
def reset_attributes_schema() -> None:
|
|
3584
|
+
"""Reset attributes schema cache.
|
|
3585
|
+
|
|
3586
|
+
DEPRECATED:
|
|
3587
|
+
Use 'reset_attributes_cache' instead.
|
|
3588
|
+
|
|
3589
|
+
"""
|
|
3585
3590
|
con = get_server_api_connection()
|
|
3586
3591
|
return con.reset_attributes_schema()
|
|
3587
3592
|
|
|
3588
3593
|
|
|
3594
|
+
def reset_attributes_cache() -> None:
|
|
3595
|
+
con = get_server_api_connection()
|
|
3596
|
+
return con.reset_attributes_cache()
|
|
3597
|
+
|
|
3598
|
+
|
|
3599
|
+
def set_attributes_cache_timeout(
|
|
3600
|
+
timeout: int,
|
|
3601
|
+
) -> None:
|
|
3602
|
+
con = get_server_api_connection()
|
|
3603
|
+
return con.set_attributes_cache_timeout(
|
|
3604
|
+
timeout=timeout,
|
|
3605
|
+
)
|
|
3606
|
+
|
|
3607
|
+
|
|
3589
3608
|
def set_attribute_config(
|
|
3590
3609
|
attribute_name: str,
|
|
3591
3610
|
data: AttributeSchemaDataDict,
|
|
@@ -3622,7 +3641,7 @@ def remove_attribute_config(
|
|
|
3622
3641
|
|
|
3623
3642
|
def get_attributes_for_type(
|
|
3624
3643
|
entity_type: AttributeScope,
|
|
3625
|
-
) -> dict[str,
|
|
3644
|
+
) -> dict[str, AttributeSchemaDataDict]:
|
|
3626
3645
|
"""Get attribute schemas available for an entity type.
|
|
3627
3646
|
|
|
3628
3647
|
Example::
|
|
@@ -3670,6 +3689,9 @@ def get_attributes_fields_for_type(
|
|
|
3670
3689
|
) -> set[str]:
|
|
3671
3690
|
"""Prepare attribute fields for entity type.
|
|
3672
3691
|
|
|
3692
|
+
DEPRECATED: Field 'attrib' is marked as deprecated and should not be
|
|
3693
|
+
used for GraphQL queries.
|
|
3694
|
+
|
|
3673
3695
|
Returns:
|
|
3674
3696
|
set[str]: Attributes fields for entity type.
|
|
3675
3697
|
|
|
@@ -1,39 +1,107 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import copy
|
|
4
|
+
import time
|
|
3
5
|
import typing
|
|
4
6
|
from typing import Optional
|
|
5
|
-
import copy
|
|
6
7
|
|
|
7
8
|
from .base import BaseServerAPI
|
|
8
9
|
|
|
9
10
|
if typing.TYPE_CHECKING:
|
|
10
11
|
from ayon_api.typing import (
|
|
11
|
-
AttributeSchemaDataDict,
|
|
12
12
|
AttributeSchemaDict,
|
|
13
|
+
AttributeSchemaDataDict,
|
|
13
14
|
AttributesSchemaDict,
|
|
14
15
|
AttributeScope,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
class _AttributesCache:
|
|
19
|
+
_schema = None
|
|
20
|
+
_last_fetch = 0
|
|
21
|
+
_timeout = 60
|
|
22
|
+
_attributes_by_type = {}
|
|
23
|
+
|
|
24
|
+
def reset_schema(self) -> None:
|
|
25
|
+
self._schema = None
|
|
26
|
+
self._last_fetch = 0
|
|
27
|
+
self._attributes_by_type = {}
|
|
28
|
+
|
|
29
|
+
def set_timeout(self, timeout: int) -> None:
|
|
30
|
+
self._timeout = timeout
|
|
31
|
+
|
|
32
|
+
def get_schema(self) -> AttributesSchemaDict:
|
|
33
|
+
return copy.deepcopy(self._schema)
|
|
34
|
+
|
|
35
|
+
def set_schema(self, schema: AttributesSchemaDict) -> None:
|
|
36
|
+
self._schema = schema
|
|
37
|
+
self._last_fetch = time.time()
|
|
38
|
+
|
|
39
|
+
def is_valid(self) -> bool:
|
|
40
|
+
if self._schema is None:
|
|
41
|
+
return False
|
|
42
|
+
return time.time() - self._last_fetch < self._timeout
|
|
43
|
+
|
|
44
|
+
def invalidate(self) -> None:
|
|
45
|
+
if not self.is_valid():
|
|
46
|
+
self.reset_schema()
|
|
47
|
+
|
|
48
|
+
def get_attributes_for_type(
|
|
49
|
+
self, entity_type: AttributeScope
|
|
50
|
+
) -> list[AttributeSchemaDict]:
|
|
51
|
+
attributes = self._attributes_by_type.get(entity_type)
|
|
52
|
+
if attributes is not None:
|
|
53
|
+
return attributes
|
|
54
|
+
|
|
55
|
+
attributes_schema = self.get_schema()
|
|
56
|
+
if attributes_schema is None:
|
|
57
|
+
raise ValueError("Attributes schema is not cached.")
|
|
58
|
+
|
|
59
|
+
attributes = []
|
|
60
|
+
for attr in attributes_schema["attributes"]:
|
|
61
|
+
if entity_type not in attr["scope"]:
|
|
62
|
+
continue
|
|
63
|
+
attributes.append(attr)
|
|
64
|
+
|
|
65
|
+
self._attributes_by_type[entity_type] = attributes
|
|
66
|
+
return attributes
|
|
67
|
+
|
|
68
|
+
|
|
17
69
|
|
|
18
70
|
class AttributesAPI(BaseServerAPI):
|
|
19
|
-
|
|
20
|
-
_entity_type_attributes_cache = {}
|
|
71
|
+
_attributes_cache = _AttributesCache()
|
|
21
72
|
|
|
22
73
|
def get_attributes_schema(
|
|
23
74
|
self, use_cache: bool = True
|
|
24
75
|
) -> AttributesSchemaDict:
|
|
25
76
|
if not use_cache:
|
|
26
|
-
self.
|
|
77
|
+
self._attributes_cache.reset_schema()
|
|
78
|
+
else:
|
|
79
|
+
self._attributes_cache.invalidate()
|
|
27
80
|
|
|
28
|
-
if self.
|
|
81
|
+
if not self._attributes_cache.is_valid():
|
|
29
82
|
result = self.get("attributes")
|
|
30
83
|
result.raise_for_status()
|
|
31
|
-
self.
|
|
32
|
-
return
|
|
84
|
+
self._attributes_cache.set_schema(result.data)
|
|
85
|
+
return self._attributes_cache.get_schema()
|
|
33
86
|
|
|
34
87
|
def reset_attributes_schema(self) -> None:
|
|
35
|
-
|
|
36
|
-
|
|
88
|
+
"""Reset attributes schema cache.
|
|
89
|
+
|
|
90
|
+
DEPRECATED:
|
|
91
|
+
Use 'reset_attributes_cache' instead.
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
self.log.warning(
|
|
95
|
+
"Used deprecated function 'reset_attributes_schema'."
|
|
96
|
+
" Please use 'reset_attributes_cache' instead."
|
|
97
|
+
)
|
|
98
|
+
self.reset_attributes_cache()
|
|
99
|
+
|
|
100
|
+
def reset_attributes_cache(self) -> None:
|
|
101
|
+
self._attributes_cache.reset_schema()
|
|
102
|
+
|
|
103
|
+
def set_attributes_cache_timeout(self, timeout: int) -> None:
|
|
104
|
+
self._attributes_cache.set_timeout(timeout)
|
|
37
105
|
|
|
38
106
|
def set_attribute_config(
|
|
39
107
|
self,
|
|
@@ -64,12 +132,10 @@ class AttributesAPI(BaseServerAPI):
|
|
|
64
132
|
position=position,
|
|
65
133
|
builtin=builtin
|
|
66
134
|
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
f" {response.detail}"
|
|
72
|
-
)
|
|
135
|
+
response.raise_for_status(
|
|
136
|
+
f"Attribute \"{attribute_name}\" was not created/updated."
|
|
137
|
+
f" {response.detail}"
|
|
138
|
+
)
|
|
73
139
|
|
|
74
140
|
self.reset_attributes_schema()
|
|
75
141
|
|
|
@@ -92,7 +158,7 @@ class AttributesAPI(BaseServerAPI):
|
|
|
92
158
|
|
|
93
159
|
def get_attributes_for_type(
|
|
94
160
|
self, entity_type: AttributeScope
|
|
95
|
-
) -> dict[str,
|
|
161
|
+
) -> dict[str, AttributeSchemaDataDict]:
|
|
96
162
|
"""Get attribute schemas available for an entity type.
|
|
97
163
|
|
|
98
164
|
Example::
|
|
@@ -129,29 +195,32 @@ class AttributesAPI(BaseServerAPI):
|
|
|
129
195
|
for entered entity type.
|
|
130
196
|
|
|
131
197
|
"""
|
|
132
|
-
attributes
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
for attr in
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
attributes[attr_name] = attr["data"]
|
|
141
|
-
|
|
142
|
-
self._entity_type_attributes_cache[entity_type] = attributes
|
|
143
|
-
|
|
144
|
-
return copy.deepcopy(attributes)
|
|
198
|
+
# Make sure attributes are cached
|
|
199
|
+
self.get_attributes_schema()
|
|
200
|
+
return {
|
|
201
|
+
attr["name"]: attr["data"]
|
|
202
|
+
for attr in self._attributes_cache.get_attributes_for_type(
|
|
203
|
+
entity_type
|
|
204
|
+
)
|
|
205
|
+
}
|
|
145
206
|
|
|
146
207
|
def get_attributes_fields_for_type(
|
|
147
208
|
self, entity_type: AttributeScope
|
|
148
209
|
) -> set[str]:
|
|
149
210
|
"""Prepare attribute fields for entity type.
|
|
150
211
|
|
|
212
|
+
DEPRECATED: Field 'attrib' is marked as deprecated and should not be
|
|
213
|
+
used for GraphQL queries.
|
|
214
|
+
|
|
151
215
|
Returns:
|
|
152
216
|
set[str]: Attributes fields for entity type.
|
|
153
217
|
|
|
154
218
|
"""
|
|
219
|
+
self.log.warning(
|
|
220
|
+
"Method 'get_attributes_fields_for_type' is deprecated and should"
|
|
221
|
+
" not be used for GraphQL queries. Use 'allAttrib' field instead"
|
|
222
|
+
" of 'attrib'."
|
|
223
|
+
)
|
|
155
224
|
attributes = self.get_attributes_for_type(entity_type)
|
|
156
225
|
return {
|
|
157
226
|
f"attrib.{attr}"
|
ayon_api/_api_helpers/base.py
CHANGED
|
@@ -15,6 +15,7 @@ if typing.TYPE_CHECKING:
|
|
|
15
15
|
ProjectDict,
|
|
16
16
|
StreamType,
|
|
17
17
|
AttributeScope,
|
|
18
|
+
AttributeSchemaDataDict,
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
_PLACEHOLDER = object()
|
|
@@ -134,7 +135,7 @@ class BaseServerAPI:
|
|
|
134
135
|
|
|
135
136
|
def get_attributes_for_type(
|
|
136
137
|
self, entity_type: AttributeScope
|
|
137
|
-
) ->
|
|
138
|
+
) -> dict[str, AttributeSchemaDataDict]:
|
|
138
139
|
raise NotImplementedError()
|
|
139
140
|
|
|
140
141
|
def get_attributes_fields_for_type(
|
ayon_api/_api_helpers/lists.py
CHANGED
|
@@ -51,16 +51,17 @@ class ListsAPI(BaseServerAPI):
|
|
|
51
51
|
if fields is None:
|
|
52
52
|
fields = self.get_default_fields_for_type("entityList")
|
|
53
53
|
|
|
54
|
-
# List does not have 'attrib' field but has 'allAttrib' field
|
|
55
|
-
# which is json string and contains only values that are set
|
|
56
54
|
o_fields = tuple(fields)
|
|
57
55
|
fields = set()
|
|
58
|
-
|
|
56
|
+
add_all_attrib = False
|
|
59
57
|
for field in o_fields:
|
|
60
58
|
if field == "attrib" or field.startswith("attrib."):
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
add_all_attrib = True
|
|
60
|
+
else:
|
|
61
|
+
fields.add(field)
|
|
62
|
+
|
|
63
|
+
if add_all_attrib:
|
|
64
|
+
fields.add("allAttrib")
|
|
64
65
|
|
|
65
66
|
if "items" in fields:
|
|
66
67
|
fields.discard("items")
|
|
@@ -71,8 +72,8 @@ class ListsAPI(BaseServerAPI):
|
|
|
71
72
|
"items.position",
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
available_attribs =
|
|
75
|
-
if
|
|
75
|
+
available_attribs = {}
|
|
76
|
+
if "allAttrib" in fields:
|
|
76
77
|
available_attribs = self.get_attributes_for_type("list")
|
|
77
78
|
|
|
78
79
|
if active is not None:
|
|
@@ -97,17 +98,13 @@ class ListsAPI(BaseServerAPI):
|
|
|
97
98
|
if isinstance(attributes, str):
|
|
98
99
|
entity_list["attributes"] = json.loads(attributes)
|
|
99
100
|
|
|
100
|
-
if requires_attrib:
|
|
101
|
-
all_attrib = json.loads(
|
|
102
|
-
entity_list.get("allAttrib") or "{}"
|
|
103
|
-
)
|
|
104
|
-
entity_list["attrib"] = {
|
|
105
|
-
attrib_name: all_attrib.get(attrib_name)
|
|
106
|
-
for attrib_name in available_attribs
|
|
107
|
-
}
|
|
108
|
-
|
|
109
101
|
self._convert_entity_data(entity_list)
|
|
110
102
|
|
|
103
|
+
attrib = entity_list.get("attrib")
|
|
104
|
+
if attrib is not None:
|
|
105
|
+
for attrib_name, attrib_data in available_attribs.items():
|
|
106
|
+
attrib.setdefault(attrib_name, attrib_data["default"])
|
|
107
|
+
|
|
111
108
|
yield entity_list
|
|
112
109
|
|
|
113
110
|
def get_entity_list_rest(
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import copy
|
|
4
3
|
import json
|
|
5
4
|
import platform
|
|
6
5
|
import warnings
|
|
@@ -164,8 +163,10 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
164
163
|
return None
|
|
165
164
|
project = response.data
|
|
166
165
|
attrib = project["attrib"]
|
|
167
|
-
for attr_name in
|
|
168
|
-
|
|
166
|
+
for attr_name, attr_data in (
|
|
167
|
+
self.get_attributes_for_type("project").items()
|
|
168
|
+
):
|
|
169
|
+
attrib.setdefault(attr_name, attr_data["default"])
|
|
169
170
|
self._fill_project_entity_data(project)
|
|
170
171
|
return project
|
|
171
172
|
|
|
@@ -663,7 +664,7 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
663
664
|
if fields is None:
|
|
664
665
|
return set(), ProjectFetchType.REST
|
|
665
666
|
|
|
666
|
-
|
|
667
|
+
rest_fields = {
|
|
667
668
|
"name",
|
|
668
669
|
"code",
|
|
669
670
|
"active",
|
|
@@ -671,10 +672,11 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
671
672
|
"updatedAt",
|
|
672
673
|
}
|
|
673
674
|
graphql_fields = set()
|
|
674
|
-
if len(fields -
|
|
675
|
+
if len(fields - rest_fields) == 0:
|
|
675
676
|
return graphql_fields, ProjectFetchType.RESTList
|
|
676
677
|
|
|
677
678
|
must_use_graphql = False
|
|
679
|
+
add_all_attrib = False
|
|
678
680
|
for field in tuple(fields):
|
|
679
681
|
# Product types are available only in GraphQl
|
|
680
682
|
if field == "usedTags":
|
|
@@ -707,11 +709,12 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
707
709
|
elif field.startswith("bundle"):
|
|
708
710
|
graphql_fields.add(field)
|
|
709
711
|
|
|
710
|
-
elif field == "attrib":
|
|
711
|
-
fields.discard(
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
712
|
+
elif field == "attrib" or field.startswith("attrib."):
|
|
713
|
+
fields.discard(field)
|
|
714
|
+
add_all_attrib = True
|
|
715
|
+
|
|
716
|
+
if add_all_attrib:
|
|
717
|
+
graphql_fields.add("allAttrib")
|
|
715
718
|
|
|
716
719
|
# NOTE 'config' in GraphQl is NOT the same as from REST api.
|
|
717
720
|
# - At the moment of this comment there is missing 'productBaseTypes'.
|
|
@@ -807,6 +810,10 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
807
810
|
if project_name is not None:
|
|
808
811
|
query.set_variable_value("projectName", project_name)
|
|
809
812
|
|
|
813
|
+
attributes = {}
|
|
814
|
+
if "allAttrib" in fields:
|
|
815
|
+
attributes = self.get_attributes_for_type("project")
|
|
816
|
+
|
|
810
817
|
for parsed_data in query.continuous_query(self):
|
|
811
818
|
for project in parsed_data["projects"]:
|
|
812
819
|
if active is not None and active is not project["active"]:
|
|
@@ -815,19 +822,22 @@ class ProjectsAPI(BaseServerAPI):
|
|
|
815
822
|
if library is not None and library is not project["library"]:
|
|
816
823
|
continue
|
|
817
824
|
|
|
825
|
+
attrib = None
|
|
818
826
|
all_attrib = project.get("allAttrib")
|
|
819
827
|
if isinstance(all_attrib, str):
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
828
|
+
attrib = json.loads(all_attrib)
|
|
829
|
+
|
|
830
|
+
if attrib is not None:
|
|
831
|
+
# NOTE 'ownAttrib' logic might change in the future if
|
|
832
|
+
# allAttrib would return all attribute values.
|
|
833
|
+
project["ownAttrib"] = list(attrib)
|
|
834
|
+
project["attrib"] = attrib
|
|
835
|
+
for name, attr_data in attributes.items():
|
|
836
|
+
# NOTE 'default' can be 'None'
|
|
837
|
+
attrib.setdefault(name, attr_data["default"])
|
|
838
|
+
|
|
839
|
+
if own_attributes:
|
|
840
|
+
fill_own_attribs(project)
|
|
831
841
|
|
|
832
842
|
self._fill_project_entity_data(project)
|
|
833
843
|
yield project
|
ayon_api/constants.py
CHANGED
|
@@ -33,9 +33,6 @@ DEFAULT_USER_FIELDS = {
|
|
|
33
33
|
"hasPassword",
|
|
34
34
|
"updatedAt",
|
|
35
35
|
"apiKeyPreview",
|
|
36
|
-
"attrib.avatarUrl",
|
|
37
|
-
"attrib.email",
|
|
38
|
-
"attrib.fullName",
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
# --- Project folder types ---
|
|
@@ -104,7 +101,6 @@ DEFAULT_PROJECT_FIELDS = {
|
|
|
104
101
|
"linkTypes",
|
|
105
102
|
"statuses",
|
|
106
103
|
"tags",
|
|
107
|
-
"attrib",
|
|
108
104
|
}
|
|
109
105
|
|
|
110
106
|
# --- Folders ---
|
ayon_api/server_api.py
CHANGED
|
@@ -5,6 +5,7 @@ Provides access to server API.
|
|
|
5
5
|
"""
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import copy
|
|
8
9
|
import os
|
|
9
10
|
import re
|
|
10
11
|
import io
|
|
@@ -1007,29 +1008,37 @@ class ServerAPI(
|
|
|
1007
1008
|
|
|
1008
1009
|
if not fields:
|
|
1009
1010
|
fields = self.get_default_fields_for_type("user")
|
|
1011
|
+
else:
|
|
1012
|
+
fields = set(fields)
|
|
1013
|
+
self._prepare_fields("user", fields)
|
|
1010
1014
|
|
|
1011
|
-
query = users_graphql_query(
|
|
1015
|
+
query = users_graphql_query(fields)
|
|
1012
1016
|
for attr, filter_value in filters.items():
|
|
1013
1017
|
query.set_variable_value(attr, filter_value)
|
|
1014
1018
|
|
|
1015
|
-
attributes =
|
|
1019
|
+
attributes = {}
|
|
1020
|
+
if "allAttrib" in fields:
|
|
1021
|
+
attributes = self.get_attributes_for_type("user")
|
|
1022
|
+
|
|
1016
1023
|
for parsed_data in query.continuous_query(self):
|
|
1017
1024
|
for user in parsed_data["users"]:
|
|
1018
1025
|
access_groups = user.get("accessGroups")
|
|
1019
1026
|
if isinstance(access_groups, str):
|
|
1020
1027
|
user["accessGroups"] = json.loads(access_groups)
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1028
|
+
|
|
1029
|
+
attrib = user.get("allAttrib")
|
|
1030
|
+
if isinstance(attrib, str):
|
|
1031
|
+
attrib = json.loads(attrib)
|
|
1032
|
+
|
|
1033
|
+
if attrib is not None:
|
|
1034
|
+
own_attrib = copy.deepcopy(attrib)
|
|
1035
|
+
user["ownAttrib"] = own_attrib
|
|
1036
|
+
for name, attr_data in attributes.items():
|
|
1037
|
+
attrib.setdefault(name, attr_data["default"])
|
|
1038
|
+
own_attrib.setdefault(name, None)
|
|
1039
|
+
|
|
1040
|
+
user["attrib"] = attrib
|
|
1041
|
+
|
|
1033
1042
|
yield user
|
|
1034
1043
|
|
|
1035
1044
|
def get_user_by_name(
|
|
@@ -1089,10 +1098,9 @@ class ServerAPI(
|
|
|
1089
1098
|
response.raise_for_status()
|
|
1090
1099
|
user = response.data
|
|
1091
1100
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
# user["attrib"].setdefault(attr_name, None)
|
|
1101
|
+
attributes = self.get_attributes_for_type("user")
|
|
1102
|
+
for attr_name, attr_data in attributes.items():
|
|
1103
|
+
user["attrib"].setdefault(attr_name, attr_data["default"])
|
|
1096
1104
|
|
|
1097
1105
|
fill_own_attribs(user)
|
|
1098
1106
|
return user
|
|
@@ -2124,6 +2132,9 @@ class ServerAPI(
|
|
|
2124
2132
|
if entity_type == "activity":
|
|
2125
2133
|
return set(DEFAULT_ACTIVITY_FIELDS)
|
|
2126
2134
|
|
|
2135
|
+
if entity_type == "productType":
|
|
2136
|
+
return set(DEFAULT_PRODUCT_TYPE_FIELDS)
|
|
2137
|
+
|
|
2127
2138
|
if entity_type == "project":
|
|
2128
2139
|
entity_type_defaults = set(DEFAULT_PROJECT_FIELDS)
|
|
2129
2140
|
maj_v, min_v, patch_v, _, _ = self.server_version_tuple
|
|
@@ -2154,9 +2165,6 @@ class ServerAPI(
|
|
|
2154
2165
|
if not self.graphql_allows_traits_in_representations:
|
|
2155
2166
|
entity_type_defaults.discard("traits")
|
|
2156
2167
|
|
|
2157
|
-
elif entity_type == "productType":
|
|
2158
|
-
entity_type_defaults = set(DEFAULT_PRODUCT_TYPE_FIELDS)
|
|
2159
|
-
|
|
2160
2168
|
elif entity_type == "workfile":
|
|
2161
2169
|
entity_type_defaults = set(DEFAULT_WORKFILE_INFO_FIELDS)
|
|
2162
2170
|
|
|
@@ -2165,15 +2173,13 @@ class ServerAPI(
|
|
|
2165
2173
|
|
|
2166
2174
|
elif entity_type == "entityList":
|
|
2167
2175
|
entity_type_defaults = set(DEFAULT_ENTITY_LIST_FIELDS)
|
|
2168
|
-
# Attributes scope is 'list'
|
|
2169
|
-
entity_type = "list"
|
|
2170
2176
|
|
|
2171
2177
|
else:
|
|
2172
2178
|
raise ValueError(f"Unknown entity type \"{entity_type}\"")
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2179
|
+
|
|
2180
|
+
entity_type_defaults.add("allAttrib")
|
|
2181
|
+
|
|
2182
|
+
return entity_type_defaults
|
|
2177
2183
|
|
|
2178
2184
|
def get_rest_entity_by_id(
|
|
2179
2185
|
self,
|
|
@@ -2424,16 +2430,21 @@ class ServerAPI(
|
|
|
2424
2430
|
if not fields:
|
|
2425
2431
|
return
|
|
2426
2432
|
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2433
|
+
add_all_attrib = False
|
|
2434
|
+
for field in tuple(fields):
|
|
2435
|
+
if field == "attrib" or field.startswith("attrib."):
|
|
2436
|
+
fields.discard(field)
|
|
2437
|
+
add_all_attrib = True
|
|
2430
2438
|
|
|
2431
2439
|
if own_attributes:
|
|
2432
2440
|
if entity_type == "project":
|
|
2433
|
-
|
|
2441
|
+
add_all_attrib = True
|
|
2434
2442
|
elif entity_type in {"folder", "task"}:
|
|
2435
2443
|
fields.add("ownAttrib")
|
|
2436
2444
|
|
|
2445
|
+
if add_all_attrib:
|
|
2446
|
+
fields.add("allAttrib")
|
|
2447
|
+
|
|
2437
2448
|
if entity_type != "project":
|
|
2438
2449
|
return
|
|
2439
2450
|
|
|
@@ -2499,11 +2510,18 @@ class ServerAPI(
|
|
|
2499
2510
|
return filters
|
|
2500
2511
|
|
|
2501
2512
|
def _convert_entity_data(self, entity: AnyEntityDict):
|
|
2502
|
-
if not entity
|
|
2513
|
+
if not entity:
|
|
2503
2514
|
return
|
|
2504
2515
|
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2516
|
+
if "data" in entity:
|
|
2517
|
+
entity_data = entity["data"] or {}
|
|
2518
|
+
if isinstance(entity_data, str):
|
|
2519
|
+
entity_data = json.loads(entity_data)
|
|
2520
|
+
|
|
2521
|
+
entity["data"] = entity_data
|
|
2508
2522
|
|
|
2509
|
-
entity
|
|
2523
|
+
all_attrib = entity.get("allAttrib")
|
|
2524
|
+
if isinstance(all_attrib, str):
|
|
2525
|
+
# NOTE: This expects server returns all attributes available for
|
|
2526
|
+
# the entity type.
|
|
2527
|
+
entity["attrib"] = json.loads(all_attrib)
|
ayon_api/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Package declaring Python API for AYON server."""
|
|
2
|
-
__version__ = "1.2.
|
|
2
|
+
__version__ = "1.2.16"
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
ayon_api/__init__.py,sha256=
|
|
2
|
-
ayon_api/_api.py,sha256=
|
|
3
|
-
ayon_api/constants.py,sha256=
|
|
1
|
+
ayon_api/__init__.py,sha256=usrX8giHyjygPuFfZrH-3pawLeuslaBui7HLRhbt9ts,14295
|
|
2
|
+
ayon_api/_api.py,sha256=nWs0xNwYQbQUrLLx9_ydg1eF-AYG2sTKKy5oMRVv4A4,243242
|
|
3
|
+
ayon_api/constants.py,sha256=K8RGj9pdDwhXB2gj8W8djsFdVlvAYAUzILSADVUOVCc,4143
|
|
4
4
|
ayon_api/entity_hub.py,sha256=-evWrJsGqbuuL8yqGXuxT2ygjzTbodfURgwfc3xIJ-o,119610
|
|
5
5
|
ayon_api/events.py,sha256=RQ_ct_GTb3KbZ6QWBkYn5m-ZUc6NJDAFFsoy2P_w3dQ,1370
|
|
6
6
|
ayon_api/exceptions.py,sha256=FOOSgShGEqno6U3kxSOdALkWuIhfhuYzSup0TjwkgkM,3495
|
|
7
7
|
ayon_api/graphql.py,sha256=PgsdNVAwZymEOoFqUuTtnswv8bjtV0IIfBij2R9WKPU,29749
|
|
8
8
|
ayon_api/graphql_queries.py,sha256=JWA5LFx9BL2wmoeNXEqFXl1T-ebJKTmEMu-DnOdUE2s,28374
|
|
9
9
|
ayon_api/operations.py,sha256=BL9r5V8wXqHx63FhQOUpayceuMd0A5B-vJIb5TcKynQ,55501
|
|
10
|
-
ayon_api/server_api.py,sha256=
|
|
10
|
+
ayon_api/server_api.py,sha256=vZTxdEYsEuFq7ajte7rkfeUzL3xeYECUTXo09Vtc_Zg,80475
|
|
11
11
|
ayon_api/typing.py,sha256=aawFfY4pJ3Vuh-N4GHpAForH1y8K5xffuSdHBhUOTPM,11997
|
|
12
12
|
ayon_api/utils.py,sha256=QVWtS-29dRFJ6SKSc5GZce9iRHod2AWPC9SfJ40iIOI,32972
|
|
13
|
-
ayon_api/version.py,sha256=
|
|
13
|
+
ayon_api/version.py,sha256=8KsOz1ZANFaOyRRFrX6ttJoeI-eqOBmrX6cbVzU_CAI,75
|
|
14
14
|
ayon_api/_api_helpers/__init__.py,sha256=15wxNshWe1htzZhFnwTTflBfQ3tYJzTe6-0hrEUCQbw,1076
|
|
15
15
|
ayon_api/_api_helpers/actions.py,sha256=OBRAEJSVnhGP0xf8ktQL3M7Ubz64nDmn957qZehaRQ0,10578
|
|
16
16
|
ayon_api/_api_helpers/activities.py,sha256=0iknRHukYsVf0M6KRChBs3EsQH8bgg-yzhAx-1VivYs,10445
|
|
17
|
-
ayon_api/_api_helpers/attributes.py,sha256
|
|
18
|
-
ayon_api/_api_helpers/base.py,sha256=
|
|
17
|
+
ayon_api/_api_helpers/attributes.py,sha256=-_oPy7Xs8UOhe2wWcf0RBEBT2IXh0C-RddcxvgTAqo0,6628
|
|
18
|
+
ayon_api/_api_helpers/base.py,sha256=coGBQmM7yTZlTb1lrVHLRC83nb1DYW0HmF9GabzBgfs,4551
|
|
19
19
|
ayon_api/_api_helpers/bundles_addons.py,sha256=_AvquS0GZuUiGbCapRYu3vb_5Pp835HlbNfg9ipD3VU,31087
|
|
20
20
|
ayon_api/_api_helpers/dependency_packages.py,sha256=nghndRoxwLCo1j9EvBtYRQYBHGoGljuUOGFpYGI7PwE,8211
|
|
21
21
|
ayon_api/_api_helpers/events.py,sha256=j89YfsYXox_wIvMkiyxr3l2dzkA8x-JOgGy6p-7-ndU,17229
|
|
22
22
|
ayon_api/_api_helpers/folders.py,sha256=AvRx5r2V0luERFZ2Z6EOSIRh3Pe_OmLwR-HrrVrrVms,22279
|
|
23
23
|
ayon_api/_api_helpers/installers.py,sha256=Q45sg6rfKUht6g4bSPHHYFj8mDo_EAm9ahg9Zk3pSUs,5552
|
|
24
24
|
ayon_api/_api_helpers/links.py,sha256=ylbk7J3fzGstKI3sWdrpYHbodBuxcBhHvMe2r3AFO8E,22186
|
|
25
|
-
ayon_api/_api_helpers/lists.py,sha256=
|
|
25
|
+
ayon_api/_api_helpers/lists.py,sha256=RxnjBf4oS_aBrAd-nneUis69GGsYG1Q3VNeLxrhY1nE,14912
|
|
26
26
|
ayon_api/_api_helpers/products.py,sha256=fX9Ez_2RGRhDmZU02ucULZzfe8FGZAOFK7Qze1BTI1c,18521
|
|
27
|
-
ayon_api/_api_helpers/projects.py,sha256=
|
|
27
|
+
ayon_api/_api_helpers/projects.py,sha256=qLsTlOZU_UJ27RsbzClGFieqcGEHf5pFY94qKrYOWmA,30287
|
|
28
28
|
ayon_api/_api_helpers/representations.py,sha256=BU0Oq_JOh6F6zIoiEtTGhRoHdr9WwMXMiaDDs-Oc7Yg,27736
|
|
29
29
|
ayon_api/_api_helpers/secrets.py,sha256=L74qN38Bp22tDs9CQHWdgw3gsJm7GbnHKU75mCaWuj8,1955
|
|
30
30
|
ayon_api/_api_helpers/tasks.py,sha256=1bqGOFbbtM_RSHWIirzj1201MsJfe1WAD2zZkVW9UTg,18770
|
|
31
31
|
ayon_api/_api_helpers/thumbnails.py,sha256=2mQWU4cSY98J18ImYYt_5CRpm7DyOCO2wCmcLXwtdhk,12281
|
|
32
32
|
ayon_api/_api_helpers/versions.py,sha256=c9ebZdM9i3J24B4bs2BRRoH937JWvRTWlJ3cFRscdug,22413
|
|
33
33
|
ayon_api/_api_helpers/workfiles.py,sha256=8ksjCZ5xn7nEAKX792PeIwFNF5flslQwzbcHnJZwcu8,17679
|
|
34
|
-
ayon_python_api-1.2.
|
|
35
|
-
ayon_python_api-1.2.
|
|
36
|
-
ayon_python_api-1.2.
|
|
37
|
-
ayon_python_api-1.2.
|
|
38
|
-
ayon_python_api-1.2.
|
|
34
|
+
ayon_python_api-1.2.16.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
35
|
+
ayon_python_api-1.2.16.dist-info/METADATA,sha256=h-RylL5d9L46XX6fyAwhZ_AWTE_DR6KVVx_PlKlcV-s,16266
|
|
36
|
+
ayon_python_api-1.2.16.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
|
37
|
+
ayon_python_api-1.2.16.dist-info/top_level.txt,sha256=PKrQbX5Cz53_UmSTR_nIySnBkGyHcBTS88SCw9tuVlc,9
|
|
38
|
+
ayon_python_api-1.2.16.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|