ayon-python-api 1.2.3__tar.gz → 1.2.5__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.
Files changed (49) hide show
  1. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/PKG-INFO +7 -2
  2. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/__init__.py +8 -0
  3. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api.py +93 -0
  4. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/base.py +20 -0
  5. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/products.py +35 -3
  6. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/projects.py +165 -39
  7. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/thumbnails.py +70 -0
  8. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/constants.py +11 -0
  9. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/entity_hub.py +44 -1
  10. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/graphql_queries.py +20 -1
  11. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/operations.py +115 -18
  12. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/server_api.py +13 -0
  13. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/typing.py +23 -0
  14. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/version.py +1 -1
  15. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_python_api.egg-info/PKG-INFO +8 -3
  16. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_python_api.egg-info/SOURCES.txt +6 -1
  17. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/pyproject.toml +1 -1
  18. ayon_python_api-1.2.5/tests/test_entity_hub.py +1289 -0
  19. ayon_python_api-1.2.5/tests/test_folder_hierarchy.py +545 -0
  20. ayon_python_api-1.2.5/tests/test_get_events.py +159 -0
  21. ayon_python_api-1.2.5/tests/test_graphql_queries.py +127 -0
  22. ayon_python_api-1.2.5/tests/test_server.py +940 -0
  23. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/LICENSE +0 -0
  24. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/README.md +0 -0
  25. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/__init__.py +0 -0
  26. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/actions.py +0 -0
  27. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/activities.py +0 -0
  28. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/attributes.py +0 -0
  29. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/bundles_addons.py +0 -0
  30. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/dependency_packages.py +0 -0
  31. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/events.py +0 -0
  32. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/folders.py +0 -0
  33. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/installers.py +0 -0
  34. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/links.py +0 -0
  35. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/lists.py +0 -0
  36. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/representations.py +0 -0
  37. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/secrets.py +0 -0
  38. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/tasks.py +0 -0
  39. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/versions.py +0 -0
  40. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/_api_helpers/workfiles.py +0 -0
  41. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/events.py +0 -0
  42. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/exceptions.py +0 -0
  43. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/graphql.py +0 -0
  44. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_api/utils.py +0 -0
  45. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_python_api.egg-info/dependency_links.txt +0 -0
  46. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_python_api.egg-info/requires.txt +0 -0
  47. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/ayon_python_api.egg-info/top_level.txt +0 -0
  48. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/setup.cfg +0 -0
  49. {ayon_python_api-1.2.3 → ayon_python_api-1.2.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: ayon_python_api
3
- Version: 1.2.3
3
+ Version: 1.2.5
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -215,6 +215,11 @@ Classifier: Programming Language :: Python
215
215
  Classifier: Programming Language :: Python :: 3
216
216
  Description-Content-Type: text/markdown
217
217
  License-File: LICENSE
218
+ Requires-Dist: requests>=2.27.1
219
+ Requires-Dist: Unidecode>=1.3.0
220
+ Dynamic: author
221
+ Dynamic: home-page
222
+ Dynamic: license-file
218
223
 
219
224
  # AYON server API
220
225
  Python client for connection server. The client is using REST and GraphQl to communicate with server with `requests` module.
@@ -54,6 +54,7 @@ from ._api import (
54
54
  get_info,
55
55
  get_server_version,
56
56
  get_server_version_tuple,
57
+ is_product_base_type_supported,
57
58
  get_users,
58
59
  get_user_by_name,
59
60
  get_user,
@@ -152,6 +153,7 @@ from ._api import (
152
153
  get_build_in_anatomy_preset,
153
154
  get_rest_project,
154
155
  get_rest_projects,
156
+ get_rest_projects_list,
155
157
  get_project_names,
156
158
  get_projects,
157
159
  get_project,
@@ -271,7 +273,9 @@ from ._api import (
271
273
  get_version_thumbnail,
272
274
  get_workfile_thumbnail,
273
275
  create_thumbnail,
276
+ create_thumbnail_with_stream,
274
277
  update_thumbnail,
278
+ update_thumbnail_from_stream,
275
279
  )
276
280
 
277
281
 
@@ -329,6 +333,7 @@ __all__ = (
329
333
  "get_info",
330
334
  "get_server_version",
331
335
  "get_server_version_tuple",
336
+ "is_product_base_type_supported",
332
337
  "get_users",
333
338
  "get_user_by_name",
334
339
  "get_user",
@@ -427,6 +432,7 @@ __all__ = (
427
432
  "get_build_in_anatomy_preset",
428
433
  "get_rest_project",
429
434
  "get_rest_projects",
435
+ "get_rest_projects_list",
430
436
  "get_project_names",
431
437
  "get_projects",
432
438
  "get_project",
@@ -546,5 +552,7 @@ __all__ = (
546
552
  "get_version_thumbnail",
547
553
  "get_workfile_thumbnail",
548
554
  "create_thumbnail",
555
+ "create_thumbnail_with_stream",
549
556
  "update_thumbnail",
557
+ "update_thumbnail_from_stream",
550
558
  )
@@ -64,6 +64,7 @@ if typing.TYPE_CHECKING:
64
64
  BundlesInfoDict,
65
65
  AnatomyPresetDict,
66
66
  SecretDict,
67
+ ProjectListDict,
67
68
  AnyEntityDict,
68
69
  ProjectDict,
69
70
  FolderDict,
@@ -720,6 +721,13 @@ def get_server_version_tuple() -> ServerVersion:
720
721
  return con.get_server_version_tuple()
721
722
 
722
723
 
724
+ def is_product_base_type_supported() -> bool:
725
+ """Product base types are available on server.
726
+ """
727
+ con = get_server_api_connection()
728
+ return con.is_product_base_type_supported()
729
+
730
+
723
731
  def get_users(
724
732
  project_name: Optional[str] = None,
725
733
  usernames: Optional[Iterable[str]] = None,
@@ -3573,6 +3581,31 @@ def get_rest_projects(
3573
3581
  )
3574
3582
 
3575
3583
 
3584
+ def get_rest_projects_list(
3585
+ active: Optional[bool] = True,
3586
+ library: Optional[bool] = None,
3587
+ ) -> list[ProjectListDict]:
3588
+ """Receive available projects.
3589
+
3590
+ User must be logged in.
3591
+
3592
+ Args:
3593
+ active (Optional[bool]): Filter active/inactive projects. Both
3594
+ are returned if 'None' is passed.
3595
+ library (Optional[bool]): Filter standard/library projects. Both
3596
+ are returned if 'None' is passed.
3597
+
3598
+ Returns:
3599
+ list[ProjectListDict]: List of available projects.
3600
+
3601
+ """
3602
+ con = get_server_api_connection()
3603
+ return con.get_rest_projects_list(
3604
+ active=active,
3605
+ library=library,
3606
+ )
3607
+
3608
+
3576
3609
  def get_project_names(
3577
3610
  active: Optional[bool] = True,
3578
3611
  library: Optional[bool] = None,
@@ -4874,6 +4907,7 @@ def get_products(
4874
4907
  product_names: Optional[Iterable[str]] = None,
4875
4908
  folder_ids: Optional[Iterable[str]] = None,
4876
4909
  product_types: Optional[Iterable[str]] = None,
4910
+ product_base_types: Optional[Iterable[str]] = None,
4877
4911
  product_name_regex: Optional[str] = None,
4878
4912
  product_path_regex: Optional[str] = None,
4879
4913
  names_by_folder_ids: Optional[dict[str, Iterable[str]]] = None,
@@ -4926,6 +4960,7 @@ def get_products(
4926
4960
  product_names=product_names,
4927
4961
  folder_ids=folder_ids,
4928
4962
  product_types=product_types,
4963
+ product_base_types=product_base_types,
4929
4964
  product_name_regex=product_name_regex,
4930
4965
  product_path_regex=product_path_regex,
4931
4966
  names_by_folder_ids=names_by_folder_ids,
@@ -5084,6 +5119,7 @@ def create_product(
5084
5119
  tags: Optional[Iterable[str]] = None,
5085
5120
  status: Optional[str] = None,
5086
5121
  active: Optional[bool] = None,
5122
+ product_base_type: Optional[str] = None,
5087
5123
  product_id: Optional[str] = None,
5088
5124
  ) -> str:
5089
5125
  """Create new product.
@@ -5098,6 +5134,7 @@ def create_product(
5098
5134
  tags (Optional[Iterable[str]]): Product tags.
5099
5135
  status (Optional[str]): Product status.
5100
5136
  active (Optional[bool]): Product active state.
5137
+ product_base_type (Optional[str]): Product base type.
5101
5138
  product_id (Optional[str]): Product id. If not passed new id is
5102
5139
  generated.
5103
5140
 
@@ -5116,6 +5153,7 @@ def create_product(
5116
5153
  tags=tags,
5117
5154
  status=status,
5118
5155
  active=active,
5156
+ product_base_type=product_base_type,
5119
5157
  product_id=product_id,
5120
5158
  )
5121
5159
 
@@ -5126,6 +5164,7 @@ def update_product(
5126
5164
  name: Optional[str] = None,
5127
5165
  folder_id: Optional[str] = None,
5128
5166
  product_type: Optional[str] = None,
5167
+ product_base_type: Optional[str] = None,
5129
5168
  attrib: Optional[dict[str, Any]] = None,
5130
5169
  data: Optional[dict[str, Any]] = None,
5131
5170
  tags: Optional[Iterable[str]] = None,
@@ -5145,6 +5184,7 @@ def update_product(
5145
5184
  name (Optional[str]): New product name.
5146
5185
  folder_id (Optional[str]): New product id.
5147
5186
  product_type (Optional[str]): New product type.
5187
+ product_base_type (Optional[str]): New product base type.
5148
5188
  attrib (Optional[dict[str, Any]]): New product attributes.
5149
5189
  data (Optional[dict[str, Any]]): New product data.
5150
5190
  tags (Optional[Iterable[str]]): New product tags.
@@ -5159,6 +5199,7 @@ def update_product(
5159
5199
  name=name,
5160
5200
  folder_id=folder_id,
5161
5201
  product_type=product_type,
5202
+ product_base_type=product_base_type,
5162
5203
  attrib=attrib,
5163
5204
  data=data,
5164
5205
  tags=tags,
@@ -7726,6 +7767,34 @@ def create_thumbnail(
7726
7767
  )
7727
7768
 
7728
7769
 
7770
+ def create_thumbnail_with_stream(
7771
+ project_name: str,
7772
+ stream: StreamType,
7773
+ thumbnail_id: Optional[str] = None,
7774
+ ) -> str:
7775
+ """Create new thumbnail on server from byte stream.
7776
+
7777
+ Args:
7778
+ project_name (str): Project where the thumbnail will be created
7779
+ and can be used.
7780
+ stream (StreamType): Thumbnail content stream.
7781
+ thumbnail_id (Optional[str]): Prepared if of thumbnail.
7782
+
7783
+ Returns:
7784
+ str: Created thumbnail id.
7785
+
7786
+ Raises:
7787
+ ValueError: When a thumbnail source cannot be processed.
7788
+
7789
+ """
7790
+ con = get_server_api_connection()
7791
+ return con.create_thumbnail_with_stream(
7792
+ project_name=project_name,
7793
+ stream=stream,
7794
+ thumbnail_id=thumbnail_id,
7795
+ )
7796
+
7797
+
7729
7798
  def update_thumbnail(
7730
7799
  project_name: str,
7731
7800
  thumbnail_id: str,
@@ -7751,3 +7820,27 @@ def update_thumbnail(
7751
7820
  thumbnail_id=thumbnail_id,
7752
7821
  src_filepath=src_filepath,
7753
7822
  )
7823
+
7824
+
7825
+ def update_thumbnail_from_stream(
7826
+ project_name: str,
7827
+ thumbnail_id: str,
7828
+ stream: StreamType,
7829
+ ) -> None:
7830
+ """Change thumbnail content by id.
7831
+
7832
+ Update can be also used to create new thumbnail.
7833
+
7834
+ Args:
7835
+ project_name (str): Project where the thumbnail will be created
7836
+ and can be used.
7837
+ thumbnail_id (str): Thumbnail id to update.
7838
+ stream (StreamType): Thumbnail content stream.
7839
+
7840
+ """
7841
+ con = get_server_api_connection()
7842
+ return con.update_thumbnail_from_stream(
7843
+ project_name=project_name,
7844
+ thumbnail_id=thumbnail_id,
7845
+ stream=stream,
7846
+ )
@@ -13,6 +13,8 @@ if typing.TYPE_CHECKING:
13
13
  AnyEntityDict,
14
14
  ServerVersion,
15
15
  ProjectDict,
16
+ StreamType,
17
+ AttributeScope,
16
18
  )
17
19
 
18
20
  _PLACEHOLDER = object()
@@ -23,6 +25,9 @@ class BaseServerAPI:
23
25
  def log(self) -> logging.Logger:
24
26
  raise NotImplementedError()
25
27
 
28
+ def is_product_base_type_supported(self) -> bool:
29
+ raise NotImplementedError()
30
+
26
31
  def get_server_version(self) -> str:
27
32
  raise NotImplementedError()
28
33
 
@@ -84,6 +89,16 @@ class BaseServerAPI:
84
89
  ) -> requests.Response:
85
90
  raise NotImplementedError()
86
91
 
92
+ def upload_file_from_stream(
93
+ self,
94
+ endpoint: str,
95
+ stream: StreamType,
96
+ progress: Optional[TransferProgress] = None,
97
+ request_type: Optional[RequestType] = None,
98
+ **kwargs
99
+ ) -> requests.Response:
100
+ raise NotImplementedError()
101
+
87
102
  def download_file(
88
103
  self,
89
104
  endpoint: str,
@@ -114,6 +129,11 @@ class BaseServerAPI:
114
129
  ) -> Optional[dict[str, Any]]:
115
130
  raise NotImplementedError()
116
131
 
132
+ def get_attributes_fields_for_type(
133
+ self, entity_type: AttributeScope
134
+ ) -> set[str]:
135
+ raise NotImplementedError()
136
+
117
137
  def _prepare_fields(
118
138
  self,
119
139
  entity_type: str,
@@ -5,6 +5,7 @@ import warnings
5
5
  import typing
6
6
  from typing import Optional, Iterable, Generator, Any
7
7
 
8
+ from ayon_api.exceptions import UnsupportedServerVersion
8
9
  from ayon_api.utils import (
9
10
  prepare_list_filters,
10
11
  create_entity_id,
@@ -32,9 +33,10 @@ class ProductsAPI(BaseServerAPI):
32
33
  self,
33
34
  project_name: str,
34
35
  product_ids: Optional[Iterable[str]] = None,
35
- product_names: Optional[Iterable[str]]=None,
36
- folder_ids: Optional[Iterable[str]]=None,
37
- product_types: Optional[Iterable[str]]=None,
36
+ product_names: Optional[Iterable[str]] = None,
37
+ folder_ids: Optional[Iterable[str]] = None,
38
+ product_types: Optional[Iterable[str]] = None,
39
+ product_base_types: Optional[Iterable[str]] = None,
38
40
  product_name_regex: Optional[str] = None,
39
41
  product_path_regex: Optional[str] = None,
40
42
  names_by_folder_ids: Optional[dict[str, Iterable[str]]] = None,
@@ -59,6 +61,8 @@ class ProductsAPI(BaseServerAPI):
59
61
  Use 'None' if folder is direct child of project.
60
62
  product_types (Optional[Iterable[str]]): Product types used for
61
63
  filtering.
64
+ product_base_types (Optional[Iterable[str]]): Product base types
65
+ used for filtering.
62
66
  product_name_regex (Optional[str]): Filter products by name regex.
63
67
  product_path_regex (Optional[str]): Filter products by path regex.
64
68
  Path starts with folder path and ends with product name.
@@ -83,6 +87,11 @@ class ProductsAPI(BaseServerAPI):
83
87
  if not project_name:
84
88
  return
85
89
 
90
+ if product_base_types and not self.is_product_base_type_supported():
91
+ raise UnsupportedServerVersion(
92
+ "Product base type is not supported for your server version."
93
+ )
94
+
86
95
  # Prepare these filters before 'name_by_filter_ids' filter
87
96
  filter_product_names = None
88
97
  if product_names is not None:
@@ -150,6 +159,7 @@ class ProductsAPI(BaseServerAPI):
150
159
  filters,
151
160
  ("productIds", product_ids),
152
161
  ("productTypes", product_types),
162
+ ("productBaseTypes", product_base_types),
153
163
  ("productStatuses", statuses),
154
164
  ("productTags", tags),
155
165
  ):
@@ -378,6 +388,7 @@ class ProductsAPI(BaseServerAPI):
378
388
  tags: Optional[Iterable[str]] =None,
379
389
  status: Optional[str] = None,
380
390
  active: Optional[bool] = None,
391
+ product_base_type: Optional[str] = None,
381
392
  product_id: Optional[str] = None,
382
393
  ) -> str:
383
394
  """Create new product.
@@ -392,6 +403,7 @@ class ProductsAPI(BaseServerAPI):
392
403
  tags (Optional[Iterable[str]]): Product tags.
393
404
  status (Optional[str]): Product status.
394
405
  active (Optional[bool]): Product active state.
406
+ product_base_type (Optional[str]): Product base type.
395
407
  product_id (Optional[str]): Product id. If not passed new id is
396
408
  generated.
397
409
 
@@ -399,6 +411,14 @@ class ProductsAPI(BaseServerAPI):
399
411
  str: Product id.
400
412
 
401
413
  """
414
+ if (
415
+ product_base_type is not None
416
+ and not self.is_product_base_type_supported()
417
+ ):
418
+ raise UnsupportedServerVersion(
419
+ "Product base type is not supported for your server version."
420
+ )
421
+
402
422
  if not product_id:
403
423
  product_id = create_entity_id()
404
424
  create_data = {
@@ -408,6 +428,7 @@ class ProductsAPI(BaseServerAPI):
408
428
  "folderId": folder_id,
409
429
  }
410
430
  for key, value in (
431
+ ("productBaseType", product_base_type),
411
432
  ("attrib", attrib),
412
433
  ("data", data),
413
434
  ("tags", tags),
@@ -431,6 +452,7 @@ class ProductsAPI(BaseServerAPI):
431
452
  name: Optional[str] = None,
432
453
  folder_id: Optional[str] = None,
433
454
  product_type: Optional[str] = None,
455
+ product_base_type: Optional[str] = None,
434
456
  attrib: Optional[dict[str, Any]] = None,
435
457
  data: Optional[dict[str, Any]] = None,
436
458
  tags: Optional[Iterable[str]] = None,
@@ -450,6 +472,7 @@ class ProductsAPI(BaseServerAPI):
450
472
  name (Optional[str]): New product name.
451
473
  folder_id (Optional[str]): New product id.
452
474
  product_type (Optional[str]): New product type.
475
+ product_base_type (Optional[str]): New product base type.
453
476
  attrib (Optional[dict[str, Any]]): New product attributes.
454
477
  data (Optional[dict[str, Any]]): New product data.
455
478
  tags (Optional[Iterable[str]]): New product tags.
@@ -457,10 +480,19 @@ class ProductsAPI(BaseServerAPI):
457
480
  active (Optional[bool]): New product active state.
458
481
 
459
482
  """
483
+ if (
484
+ product_base_type is not None
485
+ and not self.is_product_base_type_supported()
486
+ ):
487
+ raise UnsupportedServerVersion(
488
+ "Product base type is not supported for your server version."
489
+ )
490
+
460
491
  update_data = {}
461
492
  for key, value in (
462
493
  ("name", name),
463
494
  ("productType", product_type),
495
+ ("productBaseType", product_base_type),
464
496
  ("folderId", folder_id),
465
497
  ("attrib", attrib),
466
498
  ("data", data),