ayon-python-api 1.2.7__tar.gz → 1.2.9__tar.gz
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_python_api-1.2.7/ayon_python_api.egg-info → ayon_python_api-1.2.9}/PKG-INFO +1 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/__init__.py +4 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api.py +104 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/base.py +6 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/folders.py +9 -5
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/lists.py +44 -5
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/products.py +14 -7
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/representations.py +17 -9
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/tasks.py +20 -7
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/versions.py +14 -6
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/constants.py +1 -4
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/entity_hub.py +2 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/graphql_queries.py +12 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/server_api.py +87 -3
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/typing.py +20 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/version.py +1 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9/ayon_python_api.egg-info}/PKG-INFO +1 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/pyproject.toml +1 -1
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/LICENSE +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/README.md +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/__init__.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/actions.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/activities.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/attributes.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/bundles_addons.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/dependency_packages.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/events.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/installers.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/links.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/projects.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/secrets.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/thumbnails.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/workfiles.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/events.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/exceptions.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/graphql.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/operations.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/utils.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_python_api.egg-info/SOURCES.txt +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_python_api.egg-info/dependency_links.txt +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_python_api.egg-info/requires.txt +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_python_api.egg-info/top_level.txt +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/setup.cfg +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/setup.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/tests/test_entity_hub.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/tests/test_folder_hierarchy.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/tests/test_get_events.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/tests/test_graphql_queries.py +0 -0
- {ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/tests/test_server.py +0 -0
|
@@ -70,6 +70,8 @@ from ._api import (
|
|
|
70
70
|
delete,
|
|
71
71
|
download_file_to_stream,
|
|
72
72
|
download_file,
|
|
73
|
+
download_project_file,
|
|
74
|
+
download_project_file_to_stream,
|
|
73
75
|
upload_file_from_stream,
|
|
74
76
|
upload_file,
|
|
75
77
|
upload_reviewable,
|
|
@@ -349,6 +351,8 @@ __all__ = (
|
|
|
349
351
|
"delete",
|
|
350
352
|
"download_file_to_stream",
|
|
351
353
|
"download_file",
|
|
354
|
+
"download_project_file",
|
|
355
|
+
"download_project_file_to_stream",
|
|
352
356
|
"upload_file_from_stream",
|
|
353
357
|
"upload_file",
|
|
354
358
|
"upload_reviewable",
|
|
@@ -84,6 +84,7 @@ if typing.TYPE_CHECKING:
|
|
|
84
84
|
ActionModeType,
|
|
85
85
|
StreamType,
|
|
86
86
|
EntityListAttributeDefinitionDict,
|
|
87
|
+
AdvancedFilterDict,
|
|
87
88
|
)
|
|
88
89
|
from ._api_helpers.links import CreateLinkData
|
|
89
90
|
|
|
@@ -992,6 +993,80 @@ def download_file(
|
|
|
992
993
|
)
|
|
993
994
|
|
|
994
995
|
|
|
996
|
+
def download_project_file(
|
|
997
|
+
project_name: str,
|
|
998
|
+
file_id: str,
|
|
999
|
+
filepath: str,
|
|
1000
|
+
*,
|
|
1001
|
+
chunk_size: Optional[int] = None,
|
|
1002
|
+
progress: Optional[TransferProgress] = None,
|
|
1003
|
+
) -> TransferProgress:
|
|
1004
|
+
"""Download project file to filepath.
|
|
1005
|
+
|
|
1006
|
+
Project files are usually binary files, such as images, videos,
|
|
1007
|
+
or other media files that can be accessed via api endpoint
|
|
1008
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1009
|
+
|
|
1010
|
+
Args:
|
|
1011
|
+
project_name (str): Project name.
|
|
1012
|
+
file_id (str): File id.
|
|
1013
|
+
filepath (str): Path where file will be downloaded.
|
|
1014
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1015
|
+
in single loop.
|
|
1016
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1017
|
+
to track download progress.
|
|
1018
|
+
|
|
1019
|
+
Returns:
|
|
1020
|
+
TransferProgress: Progress object.
|
|
1021
|
+
|
|
1022
|
+
"""
|
|
1023
|
+
con = get_server_api_connection()
|
|
1024
|
+
return con.download_project_file(
|
|
1025
|
+
project_name=project_name,
|
|
1026
|
+
file_id=file_id,
|
|
1027
|
+
filepath=filepath,
|
|
1028
|
+
chunk_size=chunk_size,
|
|
1029
|
+
progress=progress,
|
|
1030
|
+
)
|
|
1031
|
+
|
|
1032
|
+
|
|
1033
|
+
def download_project_file_to_stream(
|
|
1034
|
+
project_name: str,
|
|
1035
|
+
file_id: str,
|
|
1036
|
+
stream: StreamType,
|
|
1037
|
+
*,
|
|
1038
|
+
chunk_size: Optional[int] = None,
|
|
1039
|
+
progress: Optional[TransferProgress] = None,
|
|
1040
|
+
) -> TransferProgress:
|
|
1041
|
+
"""Download project file to a stream.
|
|
1042
|
+
|
|
1043
|
+
Project files are usually binary files, such as images, videos,
|
|
1044
|
+
or other media files that can be accessed via api endpoint
|
|
1045
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1046
|
+
|
|
1047
|
+
Args:
|
|
1048
|
+
project_name (str): Project name.
|
|
1049
|
+
file_id (str): File id.
|
|
1050
|
+
stream (StreamType): Stream where output will be stored.
|
|
1051
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1052
|
+
in single loop.
|
|
1053
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1054
|
+
to track download progress.
|
|
1055
|
+
|
|
1056
|
+
Returns:
|
|
1057
|
+
TransferProgress: Progress object.
|
|
1058
|
+
|
|
1059
|
+
"""
|
|
1060
|
+
con = get_server_api_connection()
|
|
1061
|
+
return con.download_project_file_to_stream(
|
|
1062
|
+
project_name=project_name,
|
|
1063
|
+
file_id=file_id,
|
|
1064
|
+
stream=stream,
|
|
1065
|
+
chunk_size=chunk_size,
|
|
1066
|
+
progress=progress,
|
|
1067
|
+
)
|
|
1068
|
+
|
|
1069
|
+
|
|
995
1070
|
def upload_file_from_stream(
|
|
996
1071
|
endpoint: str,
|
|
997
1072
|
stream: StreamType,
|
|
@@ -4144,6 +4219,7 @@ def get_folders(
|
|
|
4144
4219
|
tags: Optional[Iterable[str]] = None,
|
|
4145
4220
|
active: Optional[bool] = True,
|
|
4146
4221
|
has_links: Optional[bool] = None,
|
|
4222
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
4147
4223
|
fields: Optional[Iterable[str]] = None,
|
|
4148
4224
|
own_attributes: bool = False,
|
|
4149
4225
|
) -> Generator[FolderDict, None, None]:
|
|
@@ -4185,6 +4261,7 @@ def get_folders(
|
|
|
4185
4261
|
Both are returned if is set to None.
|
|
4186
4262
|
has_links (Optional[Literal[IN, OUT, ANY]]): Filter
|
|
4187
4263
|
representations with IN/OUT/ANY links.
|
|
4264
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
4188
4265
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
4189
4266
|
folder. All possible folder fields are returned
|
|
4190
4267
|
if 'None' is passed.
|
|
@@ -4212,6 +4289,7 @@ def get_folders(
|
|
|
4212
4289
|
tags=tags,
|
|
4213
4290
|
active=active,
|
|
4214
4291
|
has_links=has_links,
|
|
4292
|
+
filters=filters,
|
|
4215
4293
|
fields=fields,
|
|
4216
4294
|
own_attributes=own_attributes,
|
|
4217
4295
|
)
|
|
@@ -4497,6 +4575,7 @@ def get_tasks(
|
|
|
4497
4575
|
statuses: Optional[Iterable[str]] = None,
|
|
4498
4576
|
tags: Optional[Iterable[str]] = None,
|
|
4499
4577
|
active: Optional[bool] = True,
|
|
4578
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
4500
4579
|
fields: Optional[Iterable[str]] = None,
|
|
4501
4580
|
own_attributes: bool = False,
|
|
4502
4581
|
) -> Generator[TaskDict, None, None]:
|
|
@@ -4521,6 +4600,7 @@ def get_tasks(
|
|
|
4521
4600
|
filtering.
|
|
4522
4601
|
active (Optional[bool]): Filter active/inactive tasks.
|
|
4523
4602
|
Both are returned if is set to None.
|
|
4603
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
4524
4604
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
4525
4605
|
folder. All possible folder fields are returned
|
|
4526
4606
|
if 'None' is passed.
|
|
@@ -4543,6 +4623,7 @@ def get_tasks(
|
|
|
4543
4623
|
statuses=statuses,
|
|
4544
4624
|
tags=tags,
|
|
4545
4625
|
active=active,
|
|
4626
|
+
filters=filters,
|
|
4546
4627
|
fields=fields,
|
|
4547
4628
|
own_attributes=own_attributes,
|
|
4548
4629
|
)
|
|
@@ -4621,6 +4702,7 @@ def get_tasks_by_folder_paths(
|
|
|
4621
4702
|
statuses: Optional[Iterable[str]] = None,
|
|
4622
4703
|
tags: Optional[Iterable[str]] = None,
|
|
4623
4704
|
active: Optional[bool] = True,
|
|
4705
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
4624
4706
|
fields: Optional[Iterable[str]] = None,
|
|
4625
4707
|
own_attributes: bool = False,
|
|
4626
4708
|
) -> dict[str, list[TaskDict]]:
|
|
@@ -4643,6 +4725,7 @@ def get_tasks_by_folder_paths(
|
|
|
4643
4725
|
filtering.
|
|
4644
4726
|
active (Optional[bool]): Filter active/inactive tasks.
|
|
4645
4727
|
Both are returned if is set to None.
|
|
4728
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
4646
4729
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
4647
4730
|
folder. All possible folder fields are returned
|
|
4648
4731
|
if 'None' is passed.
|
|
@@ -4665,6 +4748,7 @@ def get_tasks_by_folder_paths(
|
|
|
4665
4748
|
statuses=statuses,
|
|
4666
4749
|
tags=tags,
|
|
4667
4750
|
active=active,
|
|
4751
|
+
filters=filters,
|
|
4668
4752
|
fields=fields,
|
|
4669
4753
|
own_attributes=own_attributes,
|
|
4670
4754
|
)
|
|
@@ -4914,6 +4998,7 @@ def get_products(
|
|
|
4914
4998
|
statuses: Optional[Iterable[str]] = None,
|
|
4915
4999
|
tags: Optional[Iterable[str]] = None,
|
|
4916
5000
|
active: Optional[bool] = True,
|
|
5001
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
4917
5002
|
fields: Optional[Iterable[str]] = None,
|
|
4918
5003
|
own_attributes=_PLACEHOLDER,
|
|
4919
5004
|
) -> Generator[ProductDict, None, None]:
|
|
@@ -4932,6 +5017,8 @@ def get_products(
|
|
|
4932
5017
|
Use 'None' if folder is direct child of project.
|
|
4933
5018
|
product_types (Optional[Iterable[str]]): Product types used for
|
|
4934
5019
|
filtering.
|
|
5020
|
+
product_base_types (Optional[Iterable[str]]): Product base types
|
|
5021
|
+
used for filtering.
|
|
4935
5022
|
product_name_regex (Optional[str]): Filter products by name regex.
|
|
4936
5023
|
product_path_regex (Optional[str]): Filter products by path regex.
|
|
4937
5024
|
Path starts with folder path and ends with product name.
|
|
@@ -4943,6 +5030,7 @@ def get_products(
|
|
|
4943
5030
|
for filtering.
|
|
4944
5031
|
active (Optional[bool]): Filter active/inactive products.
|
|
4945
5032
|
Both are returned if is set to None.
|
|
5033
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
4946
5034
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
4947
5035
|
folder. All possible folder fields are returned
|
|
4948
5036
|
if 'None' is passed.
|
|
@@ -4967,6 +5055,7 @@ def get_products(
|
|
|
4967
5055
|
statuses=statuses,
|
|
4968
5056
|
tags=tags,
|
|
4969
5057
|
active=active,
|
|
5058
|
+
filters=filters,
|
|
4970
5059
|
fields=fields,
|
|
4971
5060
|
own_attributes=own_attributes,
|
|
4972
5061
|
)
|
|
@@ -5249,6 +5338,7 @@ def get_versions(
|
|
|
5249
5338
|
statuses: Optional[Iterable[str]] = None,
|
|
5250
5339
|
tags: Optional[Iterable[str]] = None,
|
|
5251
5340
|
active: Optional[bool] = True,
|
|
5341
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
5252
5342
|
fields: Optional[Iterable[str]] = None,
|
|
5253
5343
|
own_attributes=_PLACEHOLDER,
|
|
5254
5344
|
) -> Generator[VersionDict, None, None]:
|
|
@@ -5275,6 +5365,7 @@ def get_versions(
|
|
|
5275
5365
|
for filtering.
|
|
5276
5366
|
active (Optional[bool]): Receive active/inactive entities.
|
|
5277
5367
|
Both are returned when 'None' is passed.
|
|
5368
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
5278
5369
|
fields (Optional[Iterable[str]]): Fields to be queried
|
|
5279
5370
|
for version. All possible folder fields are returned
|
|
5280
5371
|
if 'None' is passed.
|
|
@@ -5298,6 +5389,7 @@ def get_versions(
|
|
|
5298
5389
|
statuses=statuses,
|
|
5299
5390
|
tags=tags,
|
|
5300
5391
|
active=active,
|
|
5392
|
+
filters=filters,
|
|
5301
5393
|
fields=fields,
|
|
5302
5394
|
own_attributes=own_attributes,
|
|
5303
5395
|
)
|
|
@@ -5743,6 +5835,7 @@ def get_representations(
|
|
|
5743
5835
|
tags: Optional[Iterable[str]] = None,
|
|
5744
5836
|
active: Optional[bool] = True,
|
|
5745
5837
|
has_links: Optional[str] = None,
|
|
5838
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
5746
5839
|
fields: Optional[Iterable[str]] = None,
|
|
5747
5840
|
own_attributes=_PLACEHOLDER,
|
|
5748
5841
|
) -> Generator[RepresentationDict, None, None]:
|
|
@@ -5773,6 +5866,7 @@ def get_representations(
|
|
|
5773
5866
|
Both are returned when 'None' is passed.
|
|
5774
5867
|
has_links (Optional[Literal[IN, OUT, ANY]]): Filter
|
|
5775
5868
|
representations with IN/OUT/ANY links.
|
|
5869
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
5776
5870
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
5777
5871
|
representation. All possible fields are returned if 'None' is
|
|
5778
5872
|
passed.
|
|
@@ -5795,6 +5889,7 @@ def get_representations(
|
|
|
5795
5889
|
tags=tags,
|
|
5796
5890
|
active=active,
|
|
5797
5891
|
has_links=has_links,
|
|
5892
|
+
filters=filters,
|
|
5798
5893
|
fields=fields,
|
|
5799
5894
|
own_attributes=own_attributes,
|
|
5800
5895
|
)
|
|
@@ -7206,7 +7301,15 @@ def get_entity_lists(
|
|
|
7206
7301
|
active: Optional[bool] = None,
|
|
7207
7302
|
fields: Optional[Iterable[str]] = None,
|
|
7208
7303
|
) -> Generator[dict[str, Any], None, None]:
|
|
7209
|
-
"""Fetch entity lists from server.
|
|
7304
|
+
"""Fetch entity lists from AYON server.
|
|
7305
|
+
|
|
7306
|
+
Warnings:
|
|
7307
|
+
You can't get list items for lists with different 'entityType' in
|
|
7308
|
+
one call.
|
|
7309
|
+
|
|
7310
|
+
Notes:
|
|
7311
|
+
To get list items, you have to pass 'items' field or
|
|
7312
|
+
'items.{sub-fields you want}' to 'fields' argument.
|
|
7210
7313
|
|
|
7211
7314
|
Args:
|
|
7212
7315
|
project_name (str): Project name where entity lists are.
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import typing
|
|
5
|
-
from typing import Optional, Any, Iterable
|
|
5
|
+
from typing import Optional, Any, Iterable, Union
|
|
6
6
|
|
|
7
7
|
import requests
|
|
8
8
|
|
|
@@ -142,6 +142,11 @@ class BaseServerAPI:
|
|
|
142
142
|
):
|
|
143
143
|
raise NotImplementedError()
|
|
144
144
|
|
|
145
|
+
def _prepare_advanced_filters(
|
|
146
|
+
self, filters: Union[str, dict[str, Any], None]
|
|
147
|
+
) -> Optional[str]:
|
|
148
|
+
raise NotImplementedError()
|
|
149
|
+
|
|
145
150
|
def _convert_entity_data(self, entity: AnyEntityDict):
|
|
146
151
|
raise NotImplementedError()
|
|
147
152
|
|
|
@@ -21,6 +21,7 @@ if typing.TYPE_CHECKING:
|
|
|
21
21
|
FolderDict,
|
|
22
22
|
FlatFolderDict,
|
|
23
23
|
ProjectHierarchyDict,
|
|
24
|
+
AdvancedFilterDict,
|
|
24
25
|
)
|
|
25
26
|
|
|
26
27
|
|
|
@@ -216,6 +217,7 @@ class FoldersAPI(BaseServerAPI):
|
|
|
216
217
|
tags: Optional[Iterable[str]] = None,
|
|
217
218
|
active: Optional[bool] = True,
|
|
218
219
|
has_links: Optional[bool] = None,
|
|
220
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
219
221
|
fields: Optional[Iterable[str]] = None,
|
|
220
222
|
own_attributes: bool = False
|
|
221
223
|
) -> Generator[FolderDict, None, None]:
|
|
@@ -257,6 +259,7 @@ class FoldersAPI(BaseServerAPI):
|
|
|
257
259
|
Both are returned if is set to None.
|
|
258
260
|
has_links (Optional[Literal[IN, OUT, ANY]]): Filter
|
|
259
261
|
representations with IN/OUT/ANY links.
|
|
262
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
260
263
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
261
264
|
folder. All possible folder fields are returned
|
|
262
265
|
if 'None' is passed.
|
|
@@ -270,11 +273,11 @@ class FoldersAPI(BaseServerAPI):
|
|
|
270
273
|
if not project_name:
|
|
271
274
|
return
|
|
272
275
|
|
|
273
|
-
|
|
276
|
+
graphql_filters = {
|
|
274
277
|
"projectName": project_name
|
|
275
278
|
}
|
|
276
279
|
if not prepare_list_filters(
|
|
277
|
-
|
|
280
|
+
graphql_filters,
|
|
278
281
|
("folderIds", folder_ids),
|
|
279
282
|
("folderPaths", folder_paths),
|
|
280
283
|
("folderNames", folder_names),
|
|
@@ -291,9 +294,10 @@ class FoldersAPI(BaseServerAPI):
|
|
|
291
294
|
("folderHasTasks", has_tasks),
|
|
292
295
|
("folderHasLinks", has_links),
|
|
293
296
|
("folderHasChildren", has_children),
|
|
297
|
+
("filter", self._prepare_advanced_filters(filters)),
|
|
294
298
|
):
|
|
295
299
|
if filter_value is not None:
|
|
296
|
-
|
|
300
|
+
graphql_filters[filter_key] = filter_value
|
|
297
301
|
|
|
298
302
|
if parent_ids is not None:
|
|
299
303
|
parent_ids = set(parent_ids)
|
|
@@ -313,7 +317,7 @@ class FoldersAPI(BaseServerAPI):
|
|
|
313
317
|
parent_ids.remove(project_name)
|
|
314
318
|
parent_ids.add("root")
|
|
315
319
|
|
|
316
|
-
|
|
320
|
+
graphql_filters["parentFolderIds"] = list(parent_ids)
|
|
317
321
|
|
|
318
322
|
if not fields:
|
|
319
323
|
fields = self.get_default_fields_for_type("folder")
|
|
@@ -328,7 +332,7 @@ class FoldersAPI(BaseServerAPI):
|
|
|
328
332
|
fields.add("ownAttrib")
|
|
329
333
|
|
|
330
334
|
query = folders_graphql_query(fields)
|
|
331
|
-
for attr, filter_value in
|
|
335
|
+
for attr, filter_value in graphql_filters.items():
|
|
332
336
|
query.set_variable_value(attr, filter_value)
|
|
333
337
|
|
|
334
338
|
for parsed_data in query.continuous_query(self):
|
|
@@ -26,7 +26,15 @@ class ListsAPI(BaseServerAPI):
|
|
|
26
26
|
active: Optional[bool] = None,
|
|
27
27
|
fields: Optional[Iterable[str]] = None,
|
|
28
28
|
) -> Generator[dict[str, Any], None, None]:
|
|
29
|
-
"""Fetch entity lists from server.
|
|
29
|
+
"""Fetch entity lists from AYON server.
|
|
30
|
+
|
|
31
|
+
Warnings:
|
|
32
|
+
You can't get list items for lists with different 'entityType' in
|
|
33
|
+
one call.
|
|
34
|
+
|
|
35
|
+
Notes:
|
|
36
|
+
To get list items, you have to pass 'items' field or
|
|
37
|
+
'items.{sub-fields you want}' to 'fields' argument.
|
|
30
38
|
|
|
31
39
|
Args:
|
|
32
40
|
project_name (str): Project name where entity lists are.
|
|
@@ -42,7 +50,30 @@ class ListsAPI(BaseServerAPI):
|
|
|
42
50
|
"""
|
|
43
51
|
if fields is None:
|
|
44
52
|
fields = self.get_default_fields_for_type("entityList")
|
|
45
|
-
|
|
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
|
+
o_fields = tuple(fields)
|
|
57
|
+
fields = set()
|
|
58
|
+
requires_attrib = False
|
|
59
|
+
for field in o_fields:
|
|
60
|
+
if field == "attrib" or field.startswith("attrib."):
|
|
61
|
+
requires_attrib = True
|
|
62
|
+
field = "allAttrib"
|
|
63
|
+
fields.add(field)
|
|
64
|
+
|
|
65
|
+
if "items" in fields:
|
|
66
|
+
fields.discard("items")
|
|
67
|
+
fields |= {
|
|
68
|
+
"items.id",
|
|
69
|
+
"items.entityId",
|
|
70
|
+
"items.entityType",
|
|
71
|
+
"items.position",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
available_attribs = []
|
|
75
|
+
if requires_attrib:
|
|
76
|
+
available_attribs = self.get_attributes_for_type("list")
|
|
46
77
|
|
|
47
78
|
if active is not None:
|
|
48
79
|
fields.add("active")
|
|
@@ -66,6 +97,15 @@ class ListsAPI(BaseServerAPI):
|
|
|
66
97
|
if isinstance(attributes, str):
|
|
67
98
|
entity_list["attributes"] = json.loads(attributes)
|
|
68
99
|
|
|
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
|
+
|
|
69
109
|
self._convert_entity_data(entity_list)
|
|
70
110
|
|
|
71
111
|
yield entity_list
|
|
@@ -170,9 +210,8 @@ class ListsAPI(BaseServerAPI):
|
|
|
170
210
|
kwargs[key] = value
|
|
171
211
|
|
|
172
212
|
response = self.post(
|
|
173
|
-
f"projects/{project_name}/lists
|
|
213
|
+
f"projects/{project_name}/lists",
|
|
174
214
|
**kwargs
|
|
175
|
-
|
|
176
215
|
)
|
|
177
216
|
response.raise_for_status()
|
|
178
217
|
return list_id
|
|
@@ -343,7 +382,7 @@ class ListsAPI(BaseServerAPI):
|
|
|
343
382
|
mode (EntityListItemMode): Mode of items update.
|
|
344
383
|
|
|
345
384
|
"""
|
|
346
|
-
response = self.
|
|
385
|
+
response = self.patch(
|
|
347
386
|
f"projects/{project_name}/lists/{list_id}/items",
|
|
348
387
|
items=items,
|
|
349
388
|
mode=mode,
|
|
@@ -18,7 +18,11 @@ from ayon_api.graphql_queries import (
|
|
|
18
18
|
from .base import BaseServerAPI, _PLACEHOLDER
|
|
19
19
|
|
|
20
20
|
if typing.TYPE_CHECKING:
|
|
21
|
-
from ayon_api.typing import
|
|
21
|
+
from ayon_api.typing import (
|
|
22
|
+
ProductDict,
|
|
23
|
+
ProductTypeDict,
|
|
24
|
+
AdvancedFilterDict,
|
|
25
|
+
)
|
|
22
26
|
|
|
23
27
|
|
|
24
28
|
class ProductsAPI(BaseServerAPI):
|
|
@@ -43,6 +47,7 @@ class ProductsAPI(BaseServerAPI):
|
|
|
43
47
|
statuses: Optional[Iterable[str]] = None,
|
|
44
48
|
tags: Optional[Iterable[str]] = None,
|
|
45
49
|
active: Optional[bool] = True,
|
|
50
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
46
51
|
fields: Optional[Iterable[str]] = None,
|
|
47
52
|
own_attributes=_PLACEHOLDER
|
|
48
53
|
) -> Generator[ProductDict, None, None]:
|
|
@@ -74,6 +79,7 @@ class ProductsAPI(BaseServerAPI):
|
|
|
74
79
|
for filtering.
|
|
75
80
|
active (Optional[bool]): Filter active/inactive products.
|
|
76
81
|
Both are returned if is set to None.
|
|
82
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
77
83
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
78
84
|
folder. All possible folder fields are returned
|
|
79
85
|
if 'None' is passed.
|
|
@@ -145,18 +151,18 @@ class ProductsAPI(BaseServerAPI):
|
|
|
145
151
|
fields.add("folderId")
|
|
146
152
|
|
|
147
153
|
# Prepare filters for query
|
|
148
|
-
|
|
154
|
+
graphql_filters = {
|
|
149
155
|
"projectName": project_name
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
if filter_folder_ids:
|
|
153
|
-
|
|
159
|
+
graphql_filters["folderIds"] = list(filter_folder_ids)
|
|
154
160
|
|
|
155
161
|
if filter_product_names:
|
|
156
|
-
|
|
162
|
+
graphql_filters["productNames"] = list(filter_product_names)
|
|
157
163
|
|
|
158
164
|
if not prepare_list_filters(
|
|
159
|
-
|
|
165
|
+
graphql_filters,
|
|
160
166
|
("productIds", product_ids),
|
|
161
167
|
("productTypes", product_types),
|
|
162
168
|
("productBaseTypes", product_base_types),
|
|
@@ -168,12 +174,13 @@ class ProductsAPI(BaseServerAPI):
|
|
|
168
174
|
for filter_key, filter_value in (
|
|
169
175
|
("productNameRegex", product_name_regex),
|
|
170
176
|
("productPathRegex", product_path_regex),
|
|
177
|
+
("filter", self._prepare_advanced_filters(filters)),
|
|
171
178
|
):
|
|
172
179
|
if filter_value:
|
|
173
|
-
|
|
180
|
+
graphql_filters[filter_key] = filter_value
|
|
174
181
|
|
|
175
182
|
query = products_graphql_query(fields)
|
|
176
|
-
for attr, filter_value in
|
|
183
|
+
for attr, filter_value in graphql_filters.items():
|
|
177
184
|
query.set_variable_value(attr, filter_value)
|
|
178
185
|
|
|
179
186
|
parsed_data = query.query(self)
|
|
@@ -20,7 +20,7 @@ from ayon_api.graphql_queries import (
|
|
|
20
20
|
from .base import BaseServerAPI, _PLACEHOLDER
|
|
21
21
|
|
|
22
22
|
if typing.TYPE_CHECKING:
|
|
23
|
-
from ayon_api.typing import RepresentationDict
|
|
23
|
+
from ayon_api.typing import RepresentationDict, AdvancedFilterDict
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class RepresentationsAPI(BaseServerAPI):
|
|
@@ -42,6 +42,7 @@ class RepresentationsAPI(BaseServerAPI):
|
|
|
42
42
|
tags: Optional[Iterable[str]] = None,
|
|
43
43
|
active: Optional[bool] = True,
|
|
44
44
|
has_links: Optional[str] = None,
|
|
45
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
45
46
|
fields: Optional[Iterable[str]] = None,
|
|
46
47
|
own_attributes=_PLACEHOLDER,
|
|
47
48
|
) -> Generator[RepresentationDict, None, None]:
|
|
@@ -72,6 +73,7 @@ class RepresentationsAPI(BaseServerAPI):
|
|
|
72
73
|
Both are returned when 'None' is passed.
|
|
73
74
|
has_links (Optional[Literal[IN, OUT, ANY]]): Filter
|
|
74
75
|
representations with IN/OUT/ANY links.
|
|
76
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
75
77
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
76
78
|
representation. All possible fields are returned if 'None' is
|
|
77
79
|
passed.
|
|
@@ -106,7 +108,7 @@ class RepresentationsAPI(BaseServerAPI):
|
|
|
106
108
|
fields.discard("files")
|
|
107
109
|
fields |= REPRESENTATION_FILES_FIELDS
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
graphql_filters = {
|
|
110
112
|
"projectName": project_name
|
|
111
113
|
}
|
|
112
114
|
|
|
@@ -114,7 +116,7 @@ class RepresentationsAPI(BaseServerAPI):
|
|
|
114
116
|
representation_ids = set(representation_ids)
|
|
115
117
|
if not representation_ids:
|
|
116
118
|
return
|
|
117
|
-
|
|
119
|
+
graphql_filters["representationIds"] = list(representation_ids)
|
|
118
120
|
|
|
119
121
|
version_ids_filter = None
|
|
120
122
|
representation_names_filter = None
|
|
@@ -140,29 +142,35 @@ class RepresentationsAPI(BaseServerAPI):
|
|
|
140
142
|
return
|
|
141
143
|
|
|
142
144
|
if version_ids_filter:
|
|
143
|
-
|
|
145
|
+
graphql_filters["versionIds"] = list(version_ids_filter)
|
|
144
146
|
|
|
145
147
|
if representation_names_filter:
|
|
146
|
-
|
|
148
|
+
graphql_filters["representationNames"] = list(
|
|
149
|
+
representation_names_filter
|
|
150
|
+
)
|
|
147
151
|
|
|
148
152
|
if statuses is not None:
|
|
149
153
|
statuses = set(statuses)
|
|
150
154
|
if not statuses:
|
|
151
155
|
return
|
|
152
|
-
|
|
156
|
+
graphql_filters["representationStatuses"] = list(statuses)
|
|
153
157
|
|
|
154
158
|
if tags is not None:
|
|
155
159
|
tags = set(tags)
|
|
156
160
|
if not tags:
|
|
157
161
|
return
|
|
158
|
-
|
|
162
|
+
graphql_filters["representationTags"] = list(tags)
|
|
159
163
|
|
|
160
164
|
if has_links is not None:
|
|
161
|
-
|
|
165
|
+
graphql_filters["representationHasLinks"] = has_links.upper()
|
|
166
|
+
|
|
167
|
+
filters = self._prepare_advanced_filters(filters)
|
|
168
|
+
if filters:
|
|
169
|
+
graphql_filters["filter"] = filters
|
|
162
170
|
|
|
163
171
|
query = representations_graphql_query(fields)
|
|
164
172
|
|
|
165
|
-
for attr, filter_value in
|
|
173
|
+
for attr, filter_value in graphql_filters.items():
|
|
166
174
|
query.set_variable_value(attr, filter_value)
|
|
167
175
|
|
|
168
176
|
for parsed_data in query.continuous_query(self):
|
|
@@ -17,7 +17,7 @@ from ayon_api.graphql_queries import (
|
|
|
17
17
|
from .base import BaseServerAPI
|
|
18
18
|
|
|
19
19
|
if typing.TYPE_CHECKING:
|
|
20
|
-
from ayon_api.typing import TaskDict
|
|
20
|
+
from ayon_api.typing import TaskDict, AdvancedFilterDict
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class TasksAPI(BaseServerAPI):
|
|
@@ -38,6 +38,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
38
38
|
statuses: Optional[Iterable[str]] = None,
|
|
39
39
|
tags: Optional[Iterable[str]] = None,
|
|
40
40
|
active: Optional[bool] = True,
|
|
41
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
41
42
|
fields: Optional[Iterable[str]] = None,
|
|
42
43
|
own_attributes: bool = False
|
|
43
44
|
) -> Generator[TaskDict, None, None]:
|
|
@@ -62,6 +63,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
62
63
|
filtering.
|
|
63
64
|
active (Optional[bool]): Filter active/inactive tasks.
|
|
64
65
|
Both are returned if is set to None.
|
|
66
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
65
67
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
66
68
|
folder. All possible folder fields are returned
|
|
67
69
|
if 'None' is passed.
|
|
@@ -75,11 +77,11 @@ class TasksAPI(BaseServerAPI):
|
|
|
75
77
|
if not project_name:
|
|
76
78
|
return
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
graphql_filters = {
|
|
79
81
|
"projectName": project_name
|
|
80
82
|
}
|
|
81
83
|
if not prepare_list_filters(
|
|
82
|
-
|
|
84
|
+
graphql_filters,
|
|
83
85
|
("taskIds", task_ids),
|
|
84
86
|
("taskNames", task_names),
|
|
85
87
|
("taskTypes", task_types),
|
|
@@ -91,6 +93,10 @@ class TasksAPI(BaseServerAPI):
|
|
|
91
93
|
):
|
|
92
94
|
return
|
|
93
95
|
|
|
96
|
+
filters = self._prepare_advanced_filters(filters)
|
|
97
|
+
if filters:
|
|
98
|
+
graphql_filters["filter"] = filters
|
|
99
|
+
|
|
94
100
|
if not fields:
|
|
95
101
|
fields = self.get_default_fields_for_type("task")
|
|
96
102
|
else:
|
|
@@ -101,7 +107,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
101
107
|
fields.add("active")
|
|
102
108
|
|
|
103
109
|
query = tasks_graphql_query(fields)
|
|
104
|
-
for attr, filter_value in
|
|
110
|
+
for attr, filter_value in graphql_filters.items():
|
|
105
111
|
query.set_variable_value(attr, filter_value)
|
|
106
112
|
|
|
107
113
|
for parsed_data in query.continuous_query(self):
|
|
@@ -193,6 +199,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
193
199
|
statuses: Optional[Iterable[str]] = None,
|
|
194
200
|
tags: Optional[Iterable[str]] = None,
|
|
195
201
|
active: Optional[bool] = True,
|
|
202
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
196
203
|
fields: Optional[Iterable[str]] = None,
|
|
197
204
|
own_attributes: bool = False
|
|
198
205
|
) -> dict[str, list[TaskDict]]:
|
|
@@ -215,6 +222,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
215
222
|
filtering.
|
|
216
223
|
active (Optional[bool]): Filter active/inactive tasks.
|
|
217
224
|
Both are returned if is set to None.
|
|
225
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
218
226
|
fields (Optional[Iterable[str]]): Fields to be queried for
|
|
219
227
|
folder. All possible folder fields are returned
|
|
220
228
|
if 'None' is passed.
|
|
@@ -230,12 +238,13 @@ class TasksAPI(BaseServerAPI):
|
|
|
230
238
|
if not project_name or not folder_paths:
|
|
231
239
|
return {}
|
|
232
240
|
|
|
233
|
-
|
|
241
|
+
graphql_filters = {
|
|
234
242
|
"projectName": project_name,
|
|
235
243
|
"folderPaths": list(folder_paths),
|
|
236
244
|
}
|
|
245
|
+
|
|
237
246
|
if not prepare_list_filters(
|
|
238
|
-
|
|
247
|
+
graphql_filters,
|
|
239
248
|
("taskNames", task_names),
|
|
240
249
|
("taskTypes", task_types),
|
|
241
250
|
("taskAssigneesAny", assignees),
|
|
@@ -245,6 +254,10 @@ class TasksAPI(BaseServerAPI):
|
|
|
245
254
|
):
|
|
246
255
|
return {}
|
|
247
256
|
|
|
257
|
+
filters = self._prepare_advanced_filters(filters)
|
|
258
|
+
if filters:
|
|
259
|
+
graphql_filters["filter"] = filters
|
|
260
|
+
|
|
248
261
|
if not fields:
|
|
249
262
|
fields = self.get_default_fields_for_type("task")
|
|
250
263
|
else:
|
|
@@ -255,7 +268,7 @@ class TasksAPI(BaseServerAPI):
|
|
|
255
268
|
fields.add("active")
|
|
256
269
|
|
|
257
270
|
query = tasks_by_folder_paths_graphql_query(fields)
|
|
258
|
-
for attr, filter_value in
|
|
271
|
+
for attr, filter_value in graphql_filters.items():
|
|
259
272
|
query.set_variable_value(attr, filter_value)
|
|
260
273
|
|
|
261
274
|
output = {
|
|
@@ -15,7 +15,7 @@ from ayon_api.graphql_queries import versions_graphql_query
|
|
|
15
15
|
from .base import BaseServerAPI, _PLACEHOLDER
|
|
16
16
|
|
|
17
17
|
if typing.TYPE_CHECKING:
|
|
18
|
-
from ayon_api.typing import VersionDict
|
|
18
|
+
from ayon_api.typing import VersionDict, AdvancedFilterDict
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class VersionsAPI(BaseServerAPI):
|
|
@@ -37,6 +37,7 @@ class VersionsAPI(BaseServerAPI):
|
|
|
37
37
|
statuses: Optional[Iterable[str]] = None,
|
|
38
38
|
tags: Optional[Iterable[str]] = None,
|
|
39
39
|
active: Optional[bool] = True,
|
|
40
|
+
filters: Optional[AdvancedFilterDict] = None,
|
|
40
41
|
fields: Optional[Iterable[str]] = None,
|
|
41
42
|
own_attributes=_PLACEHOLDER
|
|
42
43
|
) -> Generator[VersionDict, None, None]:
|
|
@@ -63,6 +64,7 @@ class VersionsAPI(BaseServerAPI):
|
|
|
63
64
|
for filtering.
|
|
64
65
|
active (Optional[bool]): Receive active/inactive entities.
|
|
65
66
|
Both are returned when 'None' is passed.
|
|
67
|
+
filters (Optional[AdvancedFilterDict]): Advanced filtering options.
|
|
66
68
|
fields (Optional[Iterable[str]]): Fields to be queried
|
|
67
69
|
for version. All possible folder fields are returned
|
|
68
70
|
if 'None' is passed.
|
|
@@ -98,11 +100,12 @@ class VersionsAPI(BaseServerAPI):
|
|
|
98
100
|
if not hero and not standard:
|
|
99
101
|
return
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
graphql_filters = {
|
|
102
104
|
"projectName": project_name
|
|
103
105
|
}
|
|
106
|
+
|
|
104
107
|
if not prepare_list_filters(
|
|
105
|
-
|
|
108
|
+
graphql_filters,
|
|
106
109
|
("taskIds", task_ids),
|
|
107
110
|
("versionIds", version_ids),
|
|
108
111
|
("productIds", product_ids),
|
|
@@ -113,6 +116,11 @@ class VersionsAPI(BaseServerAPI):
|
|
|
113
116
|
):
|
|
114
117
|
return
|
|
115
118
|
|
|
119
|
+
|
|
120
|
+
filters = self._prepare_advanced_filters(filters)
|
|
121
|
+
if filters:
|
|
122
|
+
graphql_filters["filter"] = filters
|
|
123
|
+
|
|
116
124
|
queries = []
|
|
117
125
|
# Add filters based on 'hero' and 'standard'
|
|
118
126
|
# NOTE: There is not a filter to "ignore" hero versions or to get
|
|
@@ -123,14 +131,14 @@ class VersionsAPI(BaseServerAPI):
|
|
|
123
131
|
# This query all versions standard + hero
|
|
124
132
|
# - hero must be filtered out if is not enabled during loop
|
|
125
133
|
query = versions_graphql_query(fields)
|
|
126
|
-
for attr, filter_value in
|
|
134
|
+
for attr, filter_value in graphql_filters.items():
|
|
127
135
|
query.set_variable_value(attr, filter_value)
|
|
128
136
|
queries.append(query)
|
|
129
137
|
else:
|
|
130
138
|
if hero:
|
|
131
139
|
# Add hero query if hero is enabled
|
|
132
140
|
hero_query = versions_graphql_query(fields)
|
|
133
|
-
for attr, filter_value in
|
|
141
|
+
for attr, filter_value in graphql_filters.items():
|
|
134
142
|
hero_query.set_variable_value(attr, filter_value)
|
|
135
143
|
|
|
136
144
|
hero_query.set_variable_value("heroOnly", True)
|
|
@@ -138,7 +146,7 @@ class VersionsAPI(BaseServerAPI):
|
|
|
138
146
|
|
|
139
147
|
if standard:
|
|
140
148
|
standard_query = versions_graphql_query(fields)
|
|
141
|
-
for attr, filter_value in
|
|
149
|
+
for attr, filter_value in graphql_filters.items():
|
|
142
150
|
standard_query.set_variable_value(attr, filter_value)
|
|
143
151
|
|
|
144
152
|
if latest:
|
|
@@ -247,6 +247,7 @@ DEFAULT_ACTIVITY_FIELDS = {
|
|
|
247
247
|
DEFAULT_ENTITY_LIST_FIELDS = {
|
|
248
248
|
"id",
|
|
249
249
|
"count",
|
|
250
|
+
"allAttrib",
|
|
250
251
|
"attributes",
|
|
251
252
|
"active",
|
|
252
253
|
"createdBy",
|
|
@@ -259,8 +260,4 @@ DEFAULT_ENTITY_LIST_FIELDS = {
|
|
|
259
260
|
"tags",
|
|
260
261
|
"updatedAt",
|
|
261
262
|
"updatedBy",
|
|
262
|
-
"items.id",
|
|
263
|
-
"items.entityId",
|
|
264
|
-
"items.entityType",
|
|
265
|
-
"items.position",
|
|
266
263
|
}
|
|
@@ -139,6 +139,7 @@ def folders_graphql_query(fields):
|
|
|
139
139
|
"folderAssigneesAll", "[String!]"
|
|
140
140
|
)
|
|
141
141
|
tags_var = query.add_variable("folderTags", "[String!]")
|
|
142
|
+
filter_var = query.add_variable("filter", "String!")
|
|
142
143
|
|
|
143
144
|
project_field = query.add_field("project")
|
|
144
145
|
project_field.set_filter("name", project_name_var)
|
|
@@ -157,6 +158,7 @@ def folders_graphql_query(fields):
|
|
|
157
158
|
folders_field.set_filter("hasTasks", has_tasks_var)
|
|
158
159
|
folders_field.set_filter("hasLinks", has_links_var)
|
|
159
160
|
folders_field.set_filter("hasChildren", has_children_var)
|
|
161
|
+
folders_field.set_filter("filter", filter_var)
|
|
160
162
|
|
|
161
163
|
nested_fields = fields_to_dict(fields)
|
|
162
164
|
add_links_fields(folders_field, nested_fields)
|
|
@@ -188,6 +190,7 @@ def tasks_graphql_query(fields):
|
|
|
188
190
|
assignees_all_var = query.add_variable("taskAssigneesAll", "[String!]")
|
|
189
191
|
statuses_var = query.add_variable("taskStatuses", "[String!]")
|
|
190
192
|
tags_var = query.add_variable("taskTags", "[String!]")
|
|
193
|
+
filter_var = query.add_variable("filter", "String!")
|
|
191
194
|
|
|
192
195
|
project_field = query.add_field("project")
|
|
193
196
|
project_field.set_filter("name", project_name_var)
|
|
@@ -203,6 +206,7 @@ def tasks_graphql_query(fields):
|
|
|
203
206
|
tasks_field.set_filter("assignees", assignees_all_var)
|
|
204
207
|
tasks_field.set_filter("statuses", statuses_var)
|
|
205
208
|
tasks_field.set_filter("tags", tags_var)
|
|
209
|
+
tasks_field.set_filter("filter", filter_var)
|
|
206
210
|
|
|
207
211
|
nested_fields = fields_to_dict(fields)
|
|
208
212
|
add_links_fields(tasks_field, nested_fields)
|
|
@@ -233,6 +237,7 @@ def tasks_by_folder_paths_graphql_query(fields):
|
|
|
233
237
|
assignees_all_var = query.add_variable("taskAssigneesAll", "[String!]")
|
|
234
238
|
statuses_var = query.add_variable("taskStatuses", "[String!]")
|
|
235
239
|
tags_var = query.add_variable("taskTags", "[String!]")
|
|
240
|
+
filter_var = query.add_variable("filter", "String!")
|
|
236
241
|
|
|
237
242
|
project_field = query.add_field("project")
|
|
238
243
|
project_field.set_filter("name", project_name_var)
|
|
@@ -250,6 +255,7 @@ def tasks_by_folder_paths_graphql_query(fields):
|
|
|
250
255
|
tasks_field.set_filter("assignees", assignees_all_var)
|
|
251
256
|
tasks_field.set_filter("statuses", statuses_var)
|
|
252
257
|
tasks_field.set_filter("tags", tags_var)
|
|
258
|
+
tasks_field.set_filter("filter", filter_var)
|
|
253
259
|
|
|
254
260
|
nested_fields = fields_to_dict(fields)
|
|
255
261
|
add_links_fields(tasks_field, nested_fields)
|
|
@@ -284,6 +290,7 @@ def products_graphql_query(fields):
|
|
|
284
290
|
product_path_regex_var = query.add_variable("productPathRegex", "String!")
|
|
285
291
|
statuses_var = query.add_variable("productStatuses", "[String!]")
|
|
286
292
|
tags_var = query.add_variable("productTags", "[String!]")
|
|
293
|
+
filter_var = query.add_variable("filter", "String!")
|
|
287
294
|
|
|
288
295
|
project_field = query.add_field("project")
|
|
289
296
|
project_field.set_filter("name", project_name_var)
|
|
@@ -298,6 +305,7 @@ def products_graphql_query(fields):
|
|
|
298
305
|
products_field.set_filter("tags", tags_var)
|
|
299
306
|
products_field.set_filter("nameEx", product_name_regex_var)
|
|
300
307
|
products_field.set_filter("pathEx", product_path_regex_var)
|
|
308
|
+
products_field.set_filter("filter", filter_var)
|
|
301
309
|
|
|
302
310
|
nested_fields = fields_to_dict(set(fields))
|
|
303
311
|
add_links_fields(products_field, nested_fields)
|
|
@@ -333,6 +341,7 @@ def versions_graphql_query(fields):
|
|
|
333
341
|
)
|
|
334
342
|
statuses_var = query.add_variable("versionStatuses", "[String!]")
|
|
335
343
|
tags_var = query.add_variable("versionTags", "[String!]")
|
|
344
|
+
filter_var = query.add_variable("filter", "String!")
|
|
336
345
|
|
|
337
346
|
project_field = query.add_field("project")
|
|
338
347
|
project_field.set_filter("name", project_name_var)
|
|
@@ -347,6 +356,7 @@ def versions_graphql_query(fields):
|
|
|
347
356
|
versions_field.set_filter("heroOrLatestOnly", hero_or_latest_only_var)
|
|
348
357
|
versions_field.set_filter("statuses", statuses_var)
|
|
349
358
|
versions_field.set_filter("tags", tags_var)
|
|
359
|
+
versions_field.set_filter("filter", filter_var)
|
|
350
360
|
|
|
351
361
|
nested_fields = fields_to_dict(set(fields))
|
|
352
362
|
add_links_fields(versions_field, nested_fields)
|
|
@@ -383,6 +393,7 @@ def representations_graphql_query(fields):
|
|
|
383
393
|
tags_var = query.add_variable(
|
|
384
394
|
"representationTags", "[String!]"
|
|
385
395
|
)
|
|
396
|
+
filter_var = query.add_variable("filter", "String!")
|
|
386
397
|
|
|
387
398
|
project_field = query.add_field("project")
|
|
388
399
|
project_field.set_filter("name", project_name_var)
|
|
@@ -394,6 +405,7 @@ def representations_graphql_query(fields):
|
|
|
394
405
|
repres_field.set_filter("hasLinks", has_links_var)
|
|
395
406
|
repres_field.set_filter("statuses", statuses_var)
|
|
396
407
|
repres_field.set_filter("tags", tags_var)
|
|
408
|
+
repres_field.set_filter("filter", filter_var)
|
|
397
409
|
|
|
398
410
|
nested_fields = fields_to_dict(set(fields))
|
|
399
411
|
add_links_fields(repres_field, nested_fields)
|
|
@@ -1377,9 +1377,11 @@ class ServerAPI(
|
|
|
1377
1377
|
try:
|
|
1378
1378
|
with get_func(url, **kwargs) as response:
|
|
1379
1379
|
response.raise_for_status()
|
|
1380
|
-
progress.
|
|
1381
|
-
|
|
1382
|
-
|
|
1380
|
+
if progress.get_content_size() is None:
|
|
1381
|
+
progress.set_content_size(
|
|
1382
|
+
response.headers["Content-length"]
|
|
1383
|
+
)
|
|
1384
|
+
|
|
1383
1385
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
1384
1386
|
stream.write(chunk)
|
|
1385
1387
|
progress.add_transferred_chunk(len(chunk))
|
|
@@ -1496,6 +1498,76 @@ class ServerAPI(
|
|
|
1496
1498
|
|
|
1497
1499
|
return progress
|
|
1498
1500
|
|
|
1501
|
+
def download_project_file(
|
|
1502
|
+
self,
|
|
1503
|
+
project_name: str,
|
|
1504
|
+
file_id: str,
|
|
1505
|
+
filepath: str,
|
|
1506
|
+
*,
|
|
1507
|
+
chunk_size: Optional[int] = None,
|
|
1508
|
+
progress: Optional[TransferProgress] = None,
|
|
1509
|
+
) -> TransferProgress:
|
|
1510
|
+
"""Download project file to filepath.
|
|
1511
|
+
|
|
1512
|
+
Project files are usually binary files, such as images, videos,
|
|
1513
|
+
or other media files that can be accessed via api endpoint
|
|
1514
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1515
|
+
|
|
1516
|
+
Args:
|
|
1517
|
+
project_name (str): Project name.
|
|
1518
|
+
file_id (str): File id.
|
|
1519
|
+
filepath (str): Path where file will be downloaded.
|
|
1520
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1521
|
+
in single loop.
|
|
1522
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1523
|
+
to track download progress.
|
|
1524
|
+
|
|
1525
|
+
Returns:
|
|
1526
|
+
TransferProgress: Progress object.
|
|
1527
|
+
|
|
1528
|
+
"""
|
|
1529
|
+
return self.download_file(
|
|
1530
|
+
f"api/projects/{project_name}/files/{file_id}",
|
|
1531
|
+
filepath,
|
|
1532
|
+
chunk_size=chunk_size,
|
|
1533
|
+
progress=progress,
|
|
1534
|
+
)
|
|
1535
|
+
|
|
1536
|
+
def download_project_file_to_stream(
|
|
1537
|
+
self,
|
|
1538
|
+
project_name: str,
|
|
1539
|
+
file_id: str,
|
|
1540
|
+
stream: StreamType,
|
|
1541
|
+
*,
|
|
1542
|
+
chunk_size: Optional[int] = None,
|
|
1543
|
+
progress: Optional[TransferProgress] = None,
|
|
1544
|
+
) -> TransferProgress:
|
|
1545
|
+
"""Download project file to a stream.
|
|
1546
|
+
|
|
1547
|
+
Project files are usually binary files, such as images, videos,
|
|
1548
|
+
or other media files that can be accessed via api endpoint
|
|
1549
|
+
'{server url}/api/projects/{project_name}/files/{file_id}'.
|
|
1550
|
+
|
|
1551
|
+
Args:
|
|
1552
|
+
project_name (str): Project name.
|
|
1553
|
+
file_id (str): File id.
|
|
1554
|
+
stream (StreamType): Stream where output will be stored.
|
|
1555
|
+
chunk_size (Optional[int]): Size of chunks that are received
|
|
1556
|
+
in single loop.
|
|
1557
|
+
progress (Optional[TransferProgress]): Object that gives ability
|
|
1558
|
+
to track download progress.
|
|
1559
|
+
|
|
1560
|
+
Returns:
|
|
1561
|
+
TransferProgress: Progress object.
|
|
1562
|
+
|
|
1563
|
+
"""
|
|
1564
|
+
return self.download_file_to_stream(
|
|
1565
|
+
f"api/projects/{project_name}/files/{file_id}",
|
|
1566
|
+
stream,
|
|
1567
|
+
chunk_size=chunk_size,
|
|
1568
|
+
progress=progress,
|
|
1569
|
+
)
|
|
1570
|
+
|
|
1499
1571
|
@staticmethod
|
|
1500
1572
|
def _upload_chunks_iter(
|
|
1501
1573
|
file_stream: StreamType,
|
|
@@ -1884,6 +1956,8 @@ class ServerAPI(
|
|
|
1884
1956
|
|
|
1885
1957
|
elif entity_type == "entityList":
|
|
1886
1958
|
entity_type_defaults = set(DEFAULT_ENTITY_LIST_FIELDS)
|
|
1959
|
+
# Attributes scope is 'list'
|
|
1960
|
+
entity_type = "list"
|
|
1887
1961
|
|
|
1888
1962
|
else:
|
|
1889
1963
|
raise ValueError(f"Unknown entity type \"{entity_type}\"")
|
|
@@ -2191,6 +2265,16 @@ class ServerAPI(
|
|
|
2191
2265
|
)
|
|
2192
2266
|
}
|
|
2193
2267
|
|
|
2268
|
+
def _prepare_advanced_filters(
|
|
2269
|
+
self, filters: Union[str, dict[str, Any], None]
|
|
2270
|
+
) -> Optional[str]:
|
|
2271
|
+
if not filters:
|
|
2272
|
+
return None
|
|
2273
|
+
|
|
2274
|
+
if isinstance(filters, dict):
|
|
2275
|
+
return json.dumps(filters)
|
|
2276
|
+
return filters
|
|
2277
|
+
|
|
2194
2278
|
def _convert_entity_data(self, entity: AnyEntityDict):
|
|
2195
2279
|
if not entity or "data" not in entity:
|
|
2196
2280
|
return
|
|
@@ -602,3 +602,23 @@ StreamType = Union[io.BytesIO, BinaryIO]
|
|
|
602
602
|
class EntityListAttributeDefinitionDict(TypedDict):
|
|
603
603
|
name: str
|
|
604
604
|
data: dict[str, Any]
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
AdvancedFilterOperator = Literal["and", "or"]
|
|
608
|
+
AdvancedFilterConditionOperator = Literal[
|
|
609
|
+
"eq", "lt", "gt", "lte", "gte", "ne",
|
|
610
|
+
"isnull", "notnull",
|
|
611
|
+
"in", "notin", "contains", "excludes",
|
|
612
|
+
"any", "like"
|
|
613
|
+
]
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
class AdvancedFilterConditionDict(TypedDict):
|
|
617
|
+
key: str
|
|
618
|
+
value: Any
|
|
619
|
+
operator: AdvancedFilterConditionOperator
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
class AdvancedFilterDict(TypedDict):
|
|
623
|
+
conditions: list[Union[AdvancedFilterConditionDict, "AdvancedFilterDict"]]
|
|
624
|
+
operator: AdvancedFilterOperator
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""Package declaring Python API for AYON server."""
|
|
2
|
-
__version__ = "1.2.
|
|
2
|
+
__version__ = "1.2.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_api/_api_helpers/dependency_packages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ayon_python_api-1.2.7 → ayon_python_api-1.2.9}/ayon_python_api.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|