Ayon-Python-Api 0.2.0__py3-none-any.whl → 0.2.2__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 CHANGED
@@ -59,13 +59,31 @@ from ._api import (
59
59
  get_addon_url,
60
60
  download_addon_private_file,
61
61
 
62
+ get_installers,
63
+ create_installer,
64
+ update_installer,
65
+ delete_installer,
66
+ download_installer,
67
+ upload_installer,
68
+
62
69
  get_dependencies_info,
63
70
  update_dependency_info,
71
+ get_dependency_packages,
72
+ create_dependency_package,
73
+ update_dependency_package,
74
+ delete_dependency_package,
64
75
 
65
76
  download_dependency_package,
66
77
  upload_dependency_package,
67
- delete_dependency_package,
68
78
 
79
+ get_bundles,
80
+ create_bundle,
81
+ update_bundle,
82
+ delete_bundle,
83
+
84
+ get_info,
85
+ get_server_version,
86
+ get_server_version_tuple,
69
87
  get_user,
70
88
  get_users,
71
89
 
@@ -87,15 +105,18 @@ from ._api import (
87
105
  get_addons_project_settings,
88
106
  get_addons_settings,
89
107
 
108
+ get_project_names,
90
109
  get_projects,
91
110
  get_project,
92
111
  create_project,
112
+ update_project,
93
113
  delete_project,
94
114
 
95
115
  get_folder_by_id,
96
116
  get_folder_by_name,
97
117
  get_folder_by_path,
98
118
  get_folders,
119
+ get_folders_hierarchy,
99
120
 
100
121
  get_tasks,
101
122
 
@@ -218,13 +239,31 @@ __all__ = (
218
239
  "get_addon_url",
219
240
  "download_addon_private_file",
220
241
 
242
+ "get_installers",
243
+ "create_installer",
244
+ "update_installer",
245
+ "delete_installer",
246
+ "download_installer",
247
+ "upload_installer",
248
+
221
249
  "get_dependencies_info",
222
250
  "update_dependency_info",
251
+ "get_dependency_packages",
252
+ "create_dependency_package",
253
+ "update_dependency_package",
254
+ "delete_dependency_package",
223
255
 
224
256
  "download_dependency_package",
225
257
  "upload_dependency_package",
226
- "delete_dependency_package",
227
258
 
259
+ "get_bundles",
260
+ "create_bundle",
261
+ "update_bundle",
262
+ "delete_bundle",
263
+
264
+ "get_info",
265
+ "get_server_version",
266
+ "get_server_version_tuple",
228
267
  "get_user",
229
268
  "get_users",
230
269
 
@@ -245,9 +284,11 @@ __all__ = (
245
284
  "get_addons_project_settings",
246
285
  "get_addons_settings",
247
286
 
287
+ "get_project_names",
248
288
  "get_projects",
249
289
  "get_project",
250
290
  "create_project",
291
+ "update_project",
251
292
  "delete_project",
252
293
 
253
294
  "get_folder_by_id",
ayon_api/_api.py CHANGED
@@ -531,6 +531,53 @@ def download_addon_private_file(*args, **kwargs):
531
531
  return con.download_addon_private_file(*args, **kwargs)
532
532
 
533
533
 
534
+ def get_info(*args, **kwargs):
535
+ con = get_server_api_connection()
536
+ return con.get_info(*args, **kwargs)
537
+
538
+
539
+ def get_server_version(*args, **kwargs):
540
+ con = get_server_api_connection()
541
+ return con.get_server_version(*args, **kwargs)
542
+
543
+
544
+ def get_server_version_tuple(*args, **kwargs):
545
+ con = get_server_api_connection()
546
+ return con.get_server_version_tuple(*args, **kwargs)
547
+
548
+
549
+ # Installers
550
+ def get_installers(*args, **kwargs):
551
+ con = get_server_api_connection()
552
+ return con.get_installers(*args, **kwargs)
553
+
554
+
555
+ def create_installer(*args, **kwargs):
556
+ con = get_server_api_connection()
557
+ return con.create_installer(*args, **kwargs)
558
+
559
+
560
+ def update_installer(*args, **kwargs):
561
+ con = get_server_api_connection()
562
+ return con.update_installer(*args, **kwargs)
563
+
564
+
565
+ def delete_installer(*args, **kwargs):
566
+ con = get_server_api_connection()
567
+ return con.delete_installer(*args, **kwargs)
568
+
569
+
570
+ def download_installer(*args, **kwargs):
571
+ con = get_server_api_connection()
572
+ con.download_installer(*args, **kwargs)
573
+
574
+
575
+ def upload_installer(*args, **kwargs):
576
+ con = get_server_api_connection()
577
+ con.upload_installer(*args, **kwargs)
578
+
579
+
580
+ # Dependency packages
534
581
  def get_dependencies_info(*args, **kwargs):
535
582
  con = get_server_api_connection()
536
583
  return con.get_dependencies_info(*args, **kwargs)
@@ -551,6 +598,21 @@ def upload_dependency_package(*args, **kwargs):
551
598
  return con.upload_dependency_package(*args, **kwargs)
552
599
 
553
600
 
601
+ def get_dependency_packages(*args, **kwargs):
602
+ con = get_server_api_connection()
603
+ return con.get_dependency_packages(*args, **kwargs)
604
+
605
+
606
+ def create_dependency_package(*args, **kwargs):
607
+ con = get_server_api_connection()
608
+ return con.create_dependency_package(*args, **kwargs)
609
+
610
+
611
+ def update_dependency_package(*args, **kwargs):
612
+ con = get_server_api_connection()
613
+ return con.update_dependency_package(*args, **kwargs)
614
+
615
+
554
616
  def delete_dependency_package(*args, **kwargs):
555
617
  con = get_server_api_connection()
556
618
  return con.delete_dependency_package(*args, **kwargs)
@@ -561,6 +623,26 @@ def get_project_anatomy_presets(*args, **kwargs):
561
623
  return con.get_project_anatomy_presets(*args, **kwargs)
562
624
 
563
625
 
626
+ def get_bundles(*args, **kwargs):
627
+ con = get_server_api_connection()
628
+ return con.get_bundles(*args, **kwargs)
629
+
630
+
631
+ def create_bundle(*args, **kwargs):
632
+ con = get_server_api_connection()
633
+ return con.create_bundle(*args, **kwargs)
634
+
635
+
636
+ def update_bundle(*args, **kwargs):
637
+ con = get_server_api_connection()
638
+ return con.update_bundle(*args, **kwargs)
639
+
640
+
641
+ def delete_bundle(*args, **kwargs):
642
+ con = get_server_api_connection()
643
+ return con.delete_bundle(*args, **kwargs)
644
+
645
+
564
646
  def get_project_anatomy_preset(*args, **kwargs):
565
647
  con = get_server_api_connection()
566
648
  return con.get_project_anatomy_preset(*args, **kwargs)
@@ -621,6 +703,11 @@ def get_addons_settings(*args, **kwargs):
621
703
  return con.get_addons_settings(*args, **kwargs)
622
704
 
623
705
 
706
+ def get_project_names(*args, **kwargs):
707
+ con = get_server_api_connection()
708
+ return con.get_project_names(*args, **kwargs)
709
+
710
+
624
711
  def get_project(*args, **kwargs):
625
712
  con = get_server_api_connection()
626
713
  return con.get_project(*args, **kwargs)
@@ -636,6 +723,11 @@ def get_folders(*args, **kwargs):
636
723
  return con.get_folders(*args, **kwargs)
637
724
 
638
725
 
726
+ def get_folders_hierarchy(*args, **kwargs):
727
+ con = get_server_api_connection()
728
+ return con.get_folders_hierarchy(*args, **kwargs)
729
+
730
+
639
731
  def get_tasks(*args, **kwargs):
640
732
  con = get_server_api_connection()
641
733
  return con.get_tasks(*args, **kwargs)
@@ -801,6 +893,11 @@ def create_project(
801
893
  )
802
894
 
803
895
 
896
+ def update_project(project_name, *args, **kwargs):
897
+ con = get_server_api_connection()
898
+ return con.update_project(project_name, *args, **kwargs)
899
+
900
+
804
901
  def delete_project(project_name):
805
902
  con = get_server_api_connection()
806
903
  return con.delete_project(project_name)
ayon_api/entity_hub.py CHANGED
@@ -683,6 +683,82 @@ class EntityHub(object):
683
683
  "entityId": entity.id
684
684
  }
685
685
 
686
+ def _pre_commit_types_changes(
687
+ self, project_changes, orig_types, changes_key, post_changes
688
+ ):
689
+ """Compare changes of types on a project.
690
+
691
+ Compare old and new types. Change project changes content if some old
692
+ types were removed. In that case the final change of types will
693
+ happen when all other entities have changed.
694
+
695
+ Args:
696
+ project_changes (dict[str, Any]): Project changes.
697
+ orig_types (list[dict[str, Any]]): Original types.
698
+ changes_key (Literal[folderTypes, taskTypes]): Key of type changes
699
+ in project changes.
700
+ post_changes (dict[str, Any]): An object where post changes will
701
+ be stored.
702
+ """
703
+
704
+ if changes_key not in project_changes:
705
+ return
706
+
707
+ new_types = project_changes[changes_key]
708
+
709
+ orig_types_by_name = {
710
+ type_info["name"]: type_info
711
+ for type_info in orig_types
712
+ }
713
+ new_names = {
714
+ type_info["name"]
715
+ for type_info in new_types
716
+ }
717
+ diff_names = set(orig_types_by_name) - new_names
718
+ if not diff_names:
719
+ return
720
+
721
+ # Create copy of folder type changes to post changes
722
+ # - post changes will be commited at the end
723
+ post_changes[changes_key] = copy.deepcopy(new_types)
724
+
725
+ for type_name in diff_names:
726
+ new_types.append(orig_types_by_name[type_name])
727
+
728
+ def _pre_commit_project(self):
729
+ """Some project changes cannot be committed before hierarchy changes.
730
+
731
+ It is not possible to change folder types or task types if there are
732
+ existing hierarchy items using the removed types. For that purposes
733
+ is first committed union of all old and new types and post changes
734
+ are prepared when all existing entities are changed.
735
+
736
+ Returns:
737
+ dict[str, Any]: Changes that will be committed after hierarchy
738
+ changes.
739
+ """
740
+
741
+ project_changes = self.project_entity.changes
742
+
743
+ post_changes = {}
744
+ if not project_changes:
745
+ return post_changes
746
+
747
+ self._pre_commit_types_changes(
748
+ project_changes,
749
+ self.project_entity.get_orig_folder_types(),
750
+ "folderType",
751
+ post_changes
752
+ )
753
+ self._pre_commit_types_changes(
754
+ project_changes,
755
+ self.project_entity.get_orig_task_types(),
756
+ "taskType",
757
+ post_changes
758
+ )
759
+ self._connection.update_project(self.project_name, **project_changes)
760
+ return post_changes
761
+
686
762
  def commit_changes(self):
687
763
  """Commit any changes that happened on entities.
688
764
 
@@ -690,6 +766,9 @@ class EntityHub(object):
690
766
  Use Operations Session instead of known operations body.
691
767
  """
692
768
 
769
+ post_project_changes = self._pre_commit_project()
770
+ self.project_entity.lock()
771
+
693
772
  project_changes = self.project_entity.changes
694
773
  if project_changes:
695
774
  response = self._connection.patch(
@@ -760,6 +839,9 @@ class EntityHub(object):
760
839
  self._connection.send_batch_operations(
761
840
  self.project_name, operations_body
762
841
  )
842
+ if post_project_changes:
843
+ self._connection.update_project(
844
+ self.project_name, **post_project_changes)
763
845
 
764
846
  self.lock()
765
847
 
@@ -1463,6 +1545,9 @@ class ProjectEntity(BaseEntity):
1463
1545
 
1464
1546
  parent = property(get_parent, set_parent)
1465
1547
 
1548
+ def get_orig_folder_types(self):
1549
+ return copy.deepcopy(self._orig_folder_types)
1550
+
1466
1551
  def get_folder_types(self):
1467
1552
  return copy.deepcopy(self._folder_types)
1468
1553
 
@@ -1474,6 +1559,9 @@ class ProjectEntity(BaseEntity):
1474
1559
  new_folder_types.append(folder_type)
1475
1560
  self._folder_types = new_folder_types
1476
1561
 
1562
+ def get_orig_task_types(self):
1563
+ return copy.deepcopy(self._orig_task_types)
1564
+
1477
1565
  def get_task_types(self):
1478
1566
  return copy.deepcopy(self._task_types)
1479
1567
 
ayon_api/server_api.py CHANGED
@@ -4,6 +4,7 @@ import io
4
4
  import json
5
5
  import logging
6
6
  import collections
7
+ import datetime
7
8
  import platform
8
9
  import copy
9
10
  import uuid
@@ -70,6 +71,14 @@ PROJECT_NAME_REGEX = re.compile(
70
71
  "^[{}]+$".format(PROJECT_NAME_ALLOWED_SYMBOLS)
71
72
  )
72
73
 
74
+ VERSION_REGEX = re.compile(
75
+ r"(?P<major>0|[1-9]\d*)"
76
+ r"\.(?P<minor>0|[1-9]\d*)"
77
+ r"\.(?P<patch>0|[1-9]\d*)"
78
+ r"(?:-(?P<prerelease>[a-zA-Z\d\-.]*))?"
79
+ r"(?:\+(?P<buildmetadata>[a-zA-Z\d\-.]*))?"
80
+ )
81
+
73
82
 
74
83
  def _get_description(response):
75
84
  if HTTPStatus is None:
@@ -304,6 +313,11 @@ class ServerAPI(object):
304
313
  default_settings_variant (Optional[str]): Settings variant used by
305
314
  default if a method for settings won't get any (by default is
306
315
  'production').
316
+ ssl_verify (Union[bool, str, None]): Verify SSL certificate
317
+ Looks for env variable value 'AYON_CA_FILE' by default. If not
318
+ available then 'True' is used.
319
+ cert (Optional[str]): Path to certificate file. Looks for env
320
+ variable value 'AYON_CERT_FILE' by default.
307
321
  """
308
322
 
309
323
  def __init__(
@@ -312,7 +326,9 @@ class ServerAPI(object):
312
326
  token=None,
313
327
  site_id=None,
314
328
  client_version=None,
315
- default_settings_variant=None
329
+ default_settings_variant=None,
330
+ ssl_verify=None,
331
+ cert=None,
316
332
  ):
317
333
  if not base_url:
318
334
  raise ValueError("Invalid server URL {}".format(str(base_url)))
@@ -326,9 +342,24 @@ class ServerAPI(object):
326
342
  self._site_id = site_id
327
343
  self._client_version = client_version
328
344
  self._default_settings_variant = default_settings_variant
345
+
346
+ if ssl_verify is None:
347
+ # Custom AYON env variable for CA file or 'True'
348
+ # - that should cover most default behaviors in 'requests'
349
+ # with 'certifi'
350
+ ssl_verify = os.environ.get("AYON_CA_FILE") or True
351
+
352
+ if cert is None:
353
+ cert = os.environ.get("AYON_CERT_FILE")
354
+
355
+ self._ssl_verify = ssl_verify
356
+ self._cert = cert
357
+
329
358
  self._access_token_is_service = None
330
359
  self._token_is_valid = None
331
360
  self._server_available = None
361
+ self._server_version = None
362
+ self._server_version_tuple = None
332
363
 
333
364
  self._session = None
334
365
 
@@ -363,6 +394,54 @@ class ServerAPI(object):
363
394
  base_url = property(get_base_url)
364
395
  rest_url = property(get_rest_url)
365
396
 
397
+ def get_ssl_verify(self):
398
+ """Enable ssl verification.
399
+
400
+ Returns:
401
+ bool: Current state of ssl verification.
402
+ """
403
+
404
+ return self._ssl_verify
405
+
406
+ def set_ssl_verify(self, ssl_verify):
407
+ """Change ssl verification state.
408
+
409
+ Args:
410
+ ssl_verify (Union[bool, str, None]): Enabled/disable
411
+ ssl verification, can be a path to file.
412
+ """
413
+
414
+ if self._ssl_verify == ssl_verify:
415
+ return
416
+ self._ssl_verify = ssl_verify
417
+ if self._session is not None:
418
+ self._session.verify = ssl_verify
419
+
420
+ def get_cert(self):
421
+ """Current cert file used for connection to server.
422
+
423
+ Returns:
424
+ Union[str, None]: Path to cert file.
425
+ """
426
+
427
+ return self._cert
428
+
429
+ def set_cert(self, cert):
430
+ """Change cert file used for connection to server.
431
+
432
+ Args:
433
+ cert (Union[str, None]): Path to cert file.
434
+ """
435
+
436
+ if cert == self._cert:
437
+ return
438
+ self._cert = cert
439
+ if self._session is not None:
440
+ self._session.cert = cert
441
+
442
+ ssl_verify = property(get_ssl_verify, set_ssl_verify)
443
+ cert = property(get_cert, set_cert)
444
+
366
445
  @property
367
446
  def access_token(self):
368
447
  """Access token used for authorization to server.
@@ -534,7 +613,11 @@ class ServerAPI(object):
534
613
  @property
535
614
  def is_server_available(self):
536
615
  if self._server_available is None:
537
- response = requests.get(self._base_url)
616
+ response = requests.get(
617
+ self._base_url,
618
+ cert=self._cert,
619
+ verify=self._ssl_verify
620
+ )
538
621
  self._server_available = response.status_code == 200
539
622
  return self._server_available
540
623
 
@@ -585,6 +668,8 @@ class ServerAPI(object):
585
668
  self.validate_token()
586
669
 
587
670
  session = requests.Session()
671
+ session.cert = self._cert
672
+ session.verify = self._ssl_verify
588
673
  session.headers.update(self.get_headers())
589
674
 
590
675
  self._session_functions_mapping = {
@@ -631,12 +716,52 @@ class ServerAPI(object):
631
716
  Use this method for validation of token instead of 'get_user'.
632
717
 
633
718
  Returns:
634
- Dict[str, Any]: Information from server.
719
+ dict[str, Any]: Information from server.
635
720
  """
636
721
 
637
722
  response = self.get("info")
638
723
  return response.data
639
724
 
725
+ def get_server_version(self):
726
+ """Get server version.
727
+
728
+ Version should match semantic version (https://semver.org/).
729
+
730
+ Returns:
731
+ str: Server version.
732
+ """
733
+
734
+ if self._server_version is None:
735
+ self._server_version = self.get_info()["version"]
736
+ return self._server_version
737
+
738
+ def get_server_version_tuple(self):
739
+ """Get server version as tuple.
740
+
741
+ Version should match semantic version (https://semver.org/).
742
+
743
+ This function only returns first three numbers of version.
744
+
745
+ Returns:
746
+ Tuple[int, int, int, Union[str, None], Union[str, None]]: Server
747
+ version.
748
+ """
749
+
750
+ if self._server_version_tuple is None:
751
+ re_match = VERSION_REGEX.fullmatch(
752
+ self.get_server_version())
753
+ self._server_version_tuple = (
754
+ int(re_match.group("major")),
755
+ int(re_match.group("minor")),
756
+ int(re_match.group("patch")),
757
+ re_match.group("prerelease"),
758
+ re_match.group("buildmetadata")
759
+ )
760
+ return self._server_version_tuple
761
+
762
+ server_version = property(get_server_version)
763
+ server_version_tuple = property(get_server_version_tuple)
764
+
640
765
  def _get_user_info(self):
641
766
  if self._access_token is None:
642
767
  return None
@@ -869,7 +994,7 @@ class ServerAPI(object):
869
994
  event_id (str): Id of event.
870
995
 
871
996
  Returns:
872
- Dict[str, Any]: Full event data.
997
+ dict[str, Any]: Full event data.
873
998
  """
874
999
 
875
1000
  response = self.get("events/{}".format(event_id))
@@ -902,7 +1027,7 @@ class ServerAPI(object):
902
1027
  for each event.
903
1028
 
904
1029
  Returns:
905
- Generator[Dict[str, Any]]: Available events matching filters.
1030
+ Generator[dict[str, Any]]: Available events matching filters.
906
1031
  """
907
1032
 
908
1033
  filters = {}
@@ -1269,7 +1394,7 @@ class ServerAPI(object):
1269
1394
  Cache schema - How to find out it is outdated?
1270
1395
 
1271
1396
  Returns:
1272
- Dict[str, Any]: Full server schema.
1397
+ dict[str, Any]: Full server schema.
1273
1398
  """
1274
1399
 
1275
1400
  url = "{}/openapi.json".format(self._base_url)
@@ -1287,7 +1412,7 @@ class ServerAPI(object):
1287
1412
  e.g. 'config' has just object definition without reference schema.
1288
1413
 
1289
1414
  Returns:
1290
- Dict[str, Any]: Component schemas.
1415
+ dict[str, Any]: Component schemas.
1291
1416
  """
1292
1417
 
1293
1418
  server_schema = self.get_server_schema()
@@ -1395,7 +1520,7 @@ class ServerAPI(object):
1395
1520
  received.
1396
1521
 
1397
1522
  Returns:
1398
- Dict[str, Dict[str, Any]]: Attribute schemas that are available
1523
+ dict[str, dict[str, Any]]: Attribute schemas that are available
1399
1524
  for entered entity type.
1400
1525
  """
1401
1526
  attributes = self._entity_type_attributes_cache.get(entity_type)
@@ -1563,6 +1688,148 @@ class ServerAPI(object):
1563
1688
  )
1564
1689
  return dst_filepath
1565
1690
 
1691
+ def get_installers(self, version=None, platform_name=None):
1692
+ """Information about desktop application installers on server.
1693
+
1694
+ Desktop application installers are helpers to download/update AYON
1695
+ desktop application for artists.
1696
+
1697
+ Args:
1698
+ version (Optional[str]): Filter installers by version.
1699
+ platform_name (Optional[str]): Filter installers by platform name.
1700
+
1701
+ Returns:
1702
+ list[dict[str, Any]]:
1703
+ """
1704
+
1705
+ query_fields = [
1706
+ "{}={}".format(key, value)
1707
+ for key, value in (
1708
+ ("version", version),
1709
+ ("platform", platform_name),
1710
+ )
1711
+ if value
1712
+ ]
1713
+ query = ""
1714
+ if query_fields:
1715
+ query = "?{}".format(",".join(query_fields))
1716
+
1717
+ response = self.get("desktop/installers{}".format(query))
1718
+ response.raise_for_status()
1719
+ return response.data
1720
+
1721
+ def create_installer(
1722
+ self,
1723
+ filename,
1724
+ version,
1725
+ python_version,
1726
+ platform_name,
1727
+ python_modules,
1728
+ checksum,
1729
+ checksum_type,
1730
+ file_size,
1731
+ sources=None,
1732
+ ):
1733
+ """Create new installer information on server.
1734
+
1735
+ This step will create only metadata. Make sure to upload installer
1736
+ to the server using 'upload_installer' method.
1737
+
1738
+ Args:
1739
+ filename (str): Installer filename.
1740
+ version (str): Version of installer.
1741
+ python_version (str): Version of Python.
1742
+ platform_name (str): Name of platform.
1743
+ python_modules (dict[str, str]): Python modules that are available
1744
+ in installer.
1745
+ checksum (str): Installer file checksum.
1746
+ checksum_type (str): Type of checksum used to create checksum.
1747
+ file_size (int): File size.
1748
+ sources (Optional[list[dict[str, Any]]]): List of sources that
1749
+ can be used to download file.
1750
+ """
1751
+
1752
+ body = {
1753
+ "filename": filename,
1754
+ "version": version,
1755
+ "pythonVersion": python_version,
1756
+ "platform": platform_name,
1757
+ "pythonModules": python_modules,
1758
+ "checksum": checksum,
1759
+ "checksumType": checksum_type,
1760
+ "size": file_size,
1761
+ }
1762
+ if sources:
1763
+ body["sources"] = sources
1764
+
1765
+ response = self.post("desktop/installers", **body)
1766
+ response.raise_for_status()
1767
+
1768
+ def update_installer(self, filename, sources):
1769
+ """Update installer information on server.
1770
+
1771
+ Args:
1772
+ filename (str): Installer filename.
1773
+ sources (list[dict[str, Any]]): List of sources that
1774
+ can be used to download file. Fully replaces existing sources.
1775
+ """
1776
+
1777
+ response = self.post(
1778
+ "desktop/installers/{}".format(filename),
1779
+ sources=sources
1780
+ )
1781
+ response.raise_for_status()
1782
+
1783
+ def delete_installer(self, filename):
1784
+ """Delete installer from server.
1785
+
1786
+ Args:
1787
+ filename (str): Installer filename.
1788
+ """
1789
+
1790
+ response = self.delete("dekstop/installers/{}".format(filename))
1791
+ response.raise_for_status()
1792
+
1793
+ def download_installer(
1794
+ self,
1795
+ filename,
1796
+ dst_filepath,
1797
+ chunk_size=None,
1798
+ progress=None
1799
+ ):
1800
+ """Download installer file from server.
1801
+
1802
+ Args:
1803
+ filename (str): Installer filename.
1804
+ dst_filepath (str): Destination filepath.
1805
+ chunk_size (Optional[int]): Download chunk size.
1806
+ progress (Optional[TransferProgress]): Object that gives ability
1807
+ to track download progress.
1808
+ """
1809
+
1810
+ self.download_file(
1811
+ "desktop/installers/{}".format(filename),
1812
+ dst_filepath,
1813
+ chunk_size=chunk_size,
1814
+ progress=progress
1815
+ )
1816
+
1817
+ def upload_installer(self, src_filepath, dst_filename, progress=None):
1818
+ """Upload installer file to server.
1819
+
1820
+ Args:
1821
+ src_filepath (str): Source filepath.
1822
+ dst_filename (str): Destination filename.
1823
+ progress (Optional[TransferProgress]): Object that gives ability
1824
+ to track download progress.
1825
+ """
1826
+
1827
+ self.upload_file(
1828
+ "desktop/installers/{}".format(dst_filename),
1829
+ src_filepath,
1830
+ progress=progress
1831
+ )
1832
+
1566
1833
  def get_dependencies_info(self):
1567
1834
  """Information about dependency packages on server.
1568
1835
 
@@ -1581,13 +1848,22 @@ class ServerAPI(object):
1581
1848
  "productionPackage": str
1582
1849
  }
1583
1850
 
1851
+ Deprecated:
1852
+ Deprecated since server version 0.2.1. Use
1853
+ 'get_dependency_packages' instead.
1854
+
1584
1855
  Returns:
1585
1856
  dict[str, Any]: Information about dependency packages known for
1586
1857
  server.
1587
1858
  """
1588
1859
 
1589
- result = self.get("dependencies")
1590
- return result.data
1860
+ major, minor, patch, _, _ = self.server_version_tuple
1861
+ if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
1862
+ result = self.get("dependencies")
1863
+ return result.data
1864
+ packages = self.get_dependency_packages()
1865
+ packages["productionPackage"] = None
1866
+ return packages
1591
1867
 
1592
1868
  def update_dependency_info(
1593
1869
  self,
@@ -1604,21 +1880,26 @@ class ServerAPI(object):
1604
1880
 
1605
1881
  The endpoint can be used to create or update dependency package.
1606
1882
 
1883
+
1884
+ Deprecated:
1885
+ Deprecated for server version 0.2.1. Use
1886
+ 'create_dependency_pacakge' instead.
1887
+
1607
1888
  Args:
1608
1889
  name (str): Name of dependency package.
1609
- platform_name (Literal["windows", "linux", "darwin"]): Platform for
1610
- which is dependency package targeted.
1890
+ platform_name (Literal["windows", "linux", "darwin"]): Platform
1891
+ for which is dependency package targeted.
1611
1892
  size (int): Size of dependency package in bytes.
1612
1893
  checksum (str): Checksum of archive file where dependencies are.
1613
1894
  checksum_algorithm (Optional[str]): Algorithm used to calculate
1614
1895
  checksum. By default, is used 'md5' (defined by server).
1615
- supported_addons (Optional[Dict[str, str]]): Name of addons for
1896
+ supported_addons (Optional[dict[str, str]]): Name of addons for
1616
1897
  which was the package created.
1617
1898
  '{"<addon name>": "<addon version>", ...}'
1618
- python_modules (Optional[Dict[str, str]]): Python modules in
1899
+ python_modules (Optional[dict[str, str]]): Python modules in
1619
1900
  dependencies package.
1620
1901
  '{"<module name>": "<module version>", ...}'
1621
- sources (Optional[List[Dict[str, Any]]]): Information about
1902
+ sources (Optional[list[dict[str, Any]]]): Information about
1622
1903
  sources where dependency package is available.
1623
1904
  """
1624
1905
 
@@ -1645,27 +1926,153 @@ class ServerAPI(object):
1645
1926
  raise ServerError("Failed to create/update dependency")
1646
1927
  return response.data
1647
1928
 
1929
+ def get_dependency_packages(self):
1930
+ """Information about dependency packages on server.
1931
+
1932
+ To download dependency package, use 'download_dependency_package'
1933
+ method and pass in 'filename'.
1934
+
1935
+ Example data structure:
1936
+ {
1937
+ "packages": [
1938
+ {
1939
+ "filename": str,
1940
+ "platform": str,
1941
+ "checksum": str,
1942
+ "checksumAlgorithm": str,
1943
+ "size": int,
1944
+ "sources": list[dict[str, Any]],
1945
+ "supportedAddons": dict[str, str],
1946
+ "pythonModules": dict[str, str]
1947
+ }
1948
+ ]
1949
+ }
1950
+
1951
+ Returns:
1952
+ dict[str, Any]: Information about dependency packages known for
1953
+ server.
1954
+ """
1955
+
1956
+ result = self.get("desktop/dependency_packages")
1957
+ result.raise_for_status()
1958
+ return result.data
1959
+
1960
+ def create_dependency_package(
1961
+ self,
1962
+ filename,
1963
+ python_modules,
1964
+ source_addons,
1965
+ installer_version,
1966
+ checksum,
1967
+ checksum_algorithm,
1968
+ file_size,
1969
+ sources=None,
1970
+ platform_name=None,
1971
+ ):
1972
+ """Create dependency package on server.
1973
+
1974
+ The package will be created on a server, it is also required to upload
1975
+ the package archive file (using 'upload_dependency_package').
1976
+
1977
+ Args:
1978
+ filename (str): Filename of dependency package.
1979
+ python_modules (dict[str, str]): Python modules in dependency
1980
+ package.
1981
+ '{"<module name>": "<module version>", ...}'
1982
+ source_addons (dict[str, str]): Name of addons for which is
1983
+ dependency package created.
1984
+ '{"<addon name>": "<addon version>", ...}'
1985
+ installer_version (str): Version of installer for which was
1986
+ package created.
1987
+ checksum (str): Checksum of archive file where dependencies are.
1988
+ checksum_algorithm (str): Algorithm used to calculate checksum.
1989
+ file_size (Optional[int]): Size of file.
1990
+ sources (Optional[list[dict[str, Any]]]): Information about
1991
+ sources from where it is possible to get file.
1992
+ platform_name (Optional[str]): Name of platform for which is
1993
+ dependency package targeted. Default value is
1994
+ current platform.
1995
+ """
1996
+
1997
+ post_body = {
1998
+ "filename": filename,
1999
+ "pythonModules": python_modules,
2000
+ "sourceAddons": source_addons,
2001
+ "installerVersion": installer_version,
2002
+ "checksum": checksum,
2003
+ "checksumAlgorithm": checksum_algorithm,
2004
+ "size": file_size,
2005
+ "platform": platform_name or platform.system().lower(),
2006
+ }
2007
+ if sources:
2008
+ post_body["sources"] = sources
2009
+
2010
+ response = self.post("desktop/dependency_packages", **post_body)
2011
+ response.raise_for_status()
2012
+
2013
+ def update_dependency_package(self, filename, sources):
2014
+ """Update dependency package metadata on server.
2015
+
2016
+ Args:
2017
+ filename (str): Filename of dependency package.
2018
+ sources (list[dict[str, Any]]): Information about
2019
+ sources from where it is possible to get file. Fully replaces
2020
+ existing sources.
2021
+ """
2022
+
2023
+ response = self.patch(
2024
+ "desktop/dependency_packages/{}".format(filename),
2025
+ sources=sources
2026
+ )
2027
+ response.raise_for_status()
2028
+
2029
+ def delete_dependency_package(self, filename, platform_name=None):
2030
+ """Remove dependency package for specific platform.
2031
+
2032
+ Args:
2033
+ filename (str): Filename of dependency package. Or name of package
2034
+ for server version 0.2.0 or lower.
2035
+ platform_name (Optional[str]): Which platform of the package
2036
+ should be removed. Current platform is used if not passed.
2037
+ Deprecated since version 0.2.1
2038
+ """
2039
+
2040
+ major, minor, patch, _, _ = self.server_version_tuple
2041
+ if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
2042
+ if platform_name is None:
2043
+ platform_name = platform.system().lower()
2044
+ url = "dependencies/{}/{}".format(filename, platform_name)
2045
+ else:
2046
+ url = "desktop/dependency_packages/{}".format(filename)
2047
+
2048
+ response = self.delete(url)
2049
+ if response.status != 200:
2050
+ raise ServerError("Failed to delete dependency file")
2051
+ return response.data
2052
+
1648
2053
  def download_dependency_package(
1649
2054
  self,
1650
- package_name,
2055
+ src_filename,
1651
2056
  dst_directory,
1652
- filename,
2057
+ dst_filename,
1653
2058
  platform_name=None,
1654
2059
  chunk_size=None,
1655
2060
  progress=None,
1656
2061
  ):
1657
2062
  """Download dependency package from server.
1658
2063
 
1659
- This method requires to have authorized token available. The package is
1660
- only downloaded.
2064
+ This method requires to have authorized token available. The package
2065
+ is only downloaded.
1661
2066
 
1662
2067
  Args:
1663
- package_name (str): Name of package to download.
2068
+ src_filename (str): Filename of dependency pacakge.
2069
+ For server version 0.2.0 and lower it is name of package
2070
+ to download.
1664
2071
  dst_directory (str): Where the file should be downloaded.
1665
- filename (str): Name of destination filename.
2072
+ dst_filename (str): Name of destination filename.
1666
2073
  platform_name (Optional[str]): Name of platform for which the
1667
2074
  dependency package is targeted. Default value is
1668
- current platform.
2075
+ current platform. Deprecated since server version 0.2.1.
1669
2076
  chunk_size (Optional[int]): Download chunk size.
1670
2077
  progress (Optional[TransferProgress]): Object that gives ability
1671
2078
  to track download progress.
@@ -1673,12 +2080,18 @@ class ServerAPI(object):
1673
2080
  Returns:
1674
2081
  str: Filepath to downloaded file.
1675
2082
  """
1676
- if platform_name is None:
1677
- platform_name = platform.system().lower()
1678
2083
 
1679
- package_filepath = os.path.join(dst_directory, filename)
2084
+ major, minor, patch, _, _ = self.server_version_tuple
2085
+ if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
2086
+ if platform_name is None:
2087
+ platform_name = platform.system().lower()
2088
+ url = "dependencies/{}/{}".format(src_filename, platform_name)
2089
+ else:
2090
+ url = "desktop/dependency_packages/{}".format(src_filename)
2091
+
2092
+ package_filepath = os.path.join(dst_directory, dst_filename)
1680
2093
  self.download_file(
1681
- "dependencies/{}/{}".format(package_name, platform_name),
2094
+ url,
1682
2095
  package_filepath,
1683
2096
  chunk_size=chunk_size,
1684
2097
  progress=progress
@@ -1686,47 +2099,170 @@ class ServerAPI(object):
1686
2099
  return package_filepath
1687
2100
 
1688
2101
  def upload_dependency_package(
1689
- self, filepath, package_name, platform_name=None, progress=None
2102
+ self, src_filepath, dst_filename, platform_name=None, progress=None
1690
2103
  ):
1691
2104
  """Upload dependency package to server.
1692
2105
 
1693
2106
  Args:
1694
- filepath (str): Path to a package file.
1695
- package_name (str): Name of package. Must be unique.
2107
+ src_filepath (str): Path to a package file.
2108
+ dst_filename (str): Dependency package filename or name of package
2109
+ for server version 0.2.0 or lower. Must be unique.
1696
2110
  platform_name (Optional[str]): For which platform is the
1697
- package targeted.
2111
+ package targeted. Deprecated since server version 0.2.1.
1698
2112
  progress (Optional[TransferProgress]): Object to keep track about
1699
2113
  upload state.
1700
2114
  """
1701
2115
 
1702
- if platform_name is None:
1703
- platform_name = platform.system().lower()
2116
+ major, minor, patch, _, _ = self.server_version_tuple
2117
+ if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
2118
+ if platform_name is None:
2119
+ platform_name = platform.system().lower()
2120
+ url = "dependencies/{}/{}".format(dst_filename, platform_name)
2121
+ else:
2122
+ url = "desktop/dependency_packages/{}".format(dst_filename)
1704
2123
 
1705
- self.upload_file(
1706
- "dependencies/{}/{}".format(package_name, platform_name),
1707
- filepath,
1708
- progress=progress
1709
- )
2124
+ self.upload_file(url, src_filepath, progress=progress)
1710
2125
 
1711
- def delete_dependency_package(self, package_name, platform_name=None):
1712
- """Remove dependency package for specific platform.
2126
+ def create_dependency_package_basename(self, platform_name=None):
2127
+ """Create basename for dependency package file.
1713
2128
 
1714
2129
  Args:
1715
- package_name (str): Name of package to remove.
1716
- platform_name (Optional[str]): Which platform of the package
1717
- should be removed. Current platform is used if not passed.
2130
+ platform_name (Optional[str]): Name of platform for which the
2131
+ bundle is targeted. Default value is current platform.
2132
+
2133
+ Returns:
2134
+ str: Dependency package name with timestamp and platform.
1718
2135
  """
1719
2136
 
1720
2137
  if platform_name is None:
1721
2138
  platform_name = platform.system().lower()
1722
2139
 
1723
- response = self.delete(
1724
- "dependencies/{}/{}".format(package_name, platform_name),
1725
- )
1726
- if response.status != 200:
1727
- raise ServerError("Failed to delete dependency file")
2140
+ now_date = datetime.datetime.now()
2141
+ time_stamp = now_date.strftime("%y%m%d%H%M")
2142
+ return "ayon_{}_{}".format(time_stamp, platform_name)
2143
+
2144
+ def get_bundles(self):
2145
+ """Server bundles with basic information.
2146
+
2147
+ Example output:
2148
+ {
2149
+ "bundles": [
2150
+ {
2151
+ "name": "my_bundle",
2152
+ "createdAt": "2023-06-12T15:37:02.420260",
2153
+ "installerVersion": "1.0.0",
2154
+ "addons": {
2155
+ "core": "1.2.3"
2156
+ },
2157
+ "dependencyPackages": {
2158
+ "windows": "a_windows_package123.zip",
2159
+ "linux": "a_linux_package123.zip",
2160
+ "darwin": "a_mac_package123.zip"
2161
+ },
2162
+ "isProduction": False,
2163
+ "isStaging": False
2164
+ }
2165
+ ],
2166
+ "productionBundle": "my_bundle",
2167
+ "stagingBundle": "test_bundle"
2168
+ }
2169
+
2170
+ Returns:
2171
+ dict[str, Any]: Server bundles with basic information.
2172
+ """
2173
+
2174
+ response = self.get("desktop/bundles")
2175
+ response.raise_for_status()
1728
2176
  return response.data
1729
2177
 
2178
+ def create_bundle(
2179
+ self,
2180
+ name,
2181
+ addon_versions,
2182
+ installer_version,
2183
+ dependency_packages=None,
2184
+ is_production=None,
2185
+ is_staging=None
2186
+ ):
2187
+ """Create bundle on server.
2188
+
2189
+ Bundle cannot be changed once is created. Only isProduction, isStaging
2190
+ and dependency packages can change after creation.
2191
+
2192
+ Args:
2193
+ name (str): Name of bundle.
2194
+ addon_versions (dict[str, str]): Addon versions.
2195
+ installer_version (Union[str, None]): Installer version.
2196
+ dependency_packages (Optional[dict[str, str]]): Dependency
2197
+ package names. Keys are platform names and values are name of
2198
+ packages.
2199
+ is_production (Optional[bool]): Bundle will be marked as
2200
+ production.
2201
+ is_staging (Optional[bool]): Bundle will be marked as staging.
2202
+ """
2203
+
2204
+ body = {
2205
+ "name": name,
2206
+ "installerVersion": installer_version,
2207
+ "addons": addon_versions,
2208
+ }
2209
+ for key, value in (
2210
+ ("dependencyPackages", dependency_packages),
2211
+ ("isProduction", is_production),
2212
+ ("isStaging", is_staging),
2213
+ ):
2214
+ if value is not None:
2215
+ body[key] = value
2216
+
2217
+ response = self.post("desktop/bundles", **body)
2218
+ response.raise_for_status()
2219
+
2220
+ def update_bundle(
2221
+ self,
2222
+ bundle_name,
2223
+ dependency_packages=None,
2224
+ is_production=None,
2225
+ is_staging=None
2226
+ ):
2227
+ """Update bundle on server.
2228
+
2229
+ Dependency packages can be update only for single platform. Others
2230
+ will be left untouched. Use 'None' value to unset dependency package
2231
+ from bundle.
2232
+
2233
+ Args:
2234
+ bundle_name (str): Name of bundle.
2235
+ dependency_packages (Optional[dict[str, str]]): Dependency pacakge
2236
+ names that should be used with the bundle.
2237
+ is_production (Optional[bool]): Bundle will be marked as
2238
+ production.
2239
+ is_staging (Optional[bool]): Bundle will be marked as staging.
2240
+ """
2241
+
2242
+ body = {
2243
+ key: value
2244
+ for key, value in (
2245
+ ("dependencyPackages", dependency_packages),
2246
+ ("isProduction", is_production),
2247
+ ("isStaging", is_staging),
2248
+ )
2249
+ if value is not None
2250
+ }
2251
+ response = self.patch(
2252
+ "desktop/bundles/{}".format(bundle_name), **body
2253
+ )
2254
+ response.raise_for_status()
2255
+
2256
+ def delete_bundle(self, bundle_name):
2257
+ """Delete bundle from server.
2258
+
2259
+ Args:
2260
+ bundle_name (str): Name of bundle to delete.
2261
+ """
2262
+
2263
+ response = self.delete("desktop/bundles/{}".format(bundle_name))
2264
+ response.raise_for_status()
2265
+
1730
2266
  # Anatomy presets
1731
2267
  def get_project_anatomy_presets(self):
1732
2268
  """Anatomy presets available on server.
@@ -2150,7 +2686,7 @@ class ServerAPI(object):
2150
2686
  project_name (str): Name of project.
2151
2687
 
2152
2688
  Returns:
2153
- Union[Dict[str, Any], None]: Project entity data or 'None' if
2689
+ Union[dict[str, Any], None]: Project entity data or 'None' if
2154
2690
  project was not found.
2155
2691
  """
2156
2692
 
@@ -2174,7 +2710,7 @@ class ServerAPI(object):
2174
2710
  are returned if 'None' is passed.
2175
2711
 
2176
2712
  Returns:
2177
- Generator[Dict[str, Any]]: Available projects.
2713
+ Generator[dict[str, Any]]: Available projects.
2178
2714
  """
2179
2715
 
2180
2716
  for project_name in self.get_project_names(active, library):
@@ -2235,7 +2771,7 @@ class ServerAPI(object):
2235
2771
  are returned if 'None' is passed.
2236
2772
 
2237
2773
  Returns:
2238
- List[str]: List of available project names.
2774
+ list[str]: List of available project names.
2239
2775
  """
2240
2776
 
2241
2777
  query_keys = {}
@@ -2276,7 +2812,7 @@ class ServerAPI(object):
2276
2812
  not explicitly set on entity will have 'None' value.
2277
2813
 
2278
2814
  Returns:
2279
- Generator[Dict[str, Any]]: Queried projects.
2815
+ Generator[dict[str, Any]]: Queried projects.
2280
2816
  """
2281
2817
 
2282
2818
  if fields is None:
@@ -2316,7 +2852,7 @@ class ServerAPI(object):
2316
2852
  not explicitly set on entity will have 'None' value.
2317
2853
 
2318
2854
  Returns:
2319
- Union[Dict[str, Any], None]: Project entity data or None
2855
+ Union[dict[str, Any], None]: Project entity data or None
2320
2856
  if project was not found.
2321
2857
  """
2322
2858
 
@@ -3112,7 +3648,7 @@ class ServerAPI(object):
3112
3648
  not explicitly set on entity will have 'None' value.
3113
3649
 
3114
3650
  Returns:
3115
- Generator[Dict[str, Any]]: Queried version entities.
3651
+ Generator[dict[str, Any]]: Queried version entities.
3116
3652
  """
3117
3653
 
3118
3654
  if not fields:
@@ -3570,7 +4106,7 @@ class ServerAPI(object):
3570
4106
  not explicitly set on entity will have 'None' value.
3571
4107
 
3572
4108
  Returns:
3573
- Generator[Dict[str, Any]]: Queried representation entities.
4109
+ Generator[dict[str, Any]]: Queried representation entities.
3574
4110
  """
3575
4111
 
3576
4112
  if not fields:
@@ -4253,7 +4789,7 @@ class ServerAPI(object):
4253
4789
  ValueError: When project name already exists.
4254
4790
 
4255
4791
  Returns:
4256
- Dict[str, Any]: Created project entity.
4792
+ dict[str, Any]: Created project entity.
4257
4793
  """
4258
4794
 
4259
4795
  if self.get_project(project_name):
@@ -4286,6 +4822,70 @@ class ServerAPI(object):
4286
4822
 
4287
4823
  return self.get_project(project_name)
4288
4824
 
4825
+ def update_project(
4826
+ self,
4827
+ project_name,
4828
+ library=None,
4829
+ folder_types=None,
4830
+ task_types=None,
4831
+ link_types=None,
4832
+ statuses=None,
4833
+ tags=None,
4834
+ config=None,
4835
+ attrib=None,
4836
+ data=None,
4837
+ active=None,
4838
+ project_code=None,
4839
+ **changes
4840
+ ):
4841
+ """Update project entity on server.
4842
+
4843
+ Args:
4844
+ project_name (str): Name of project.
4845
+ library (Optional[bool]): Change library state.
4846
+ folder_types (Optional[list[dict[str, Any]]]): Folder type
4847
+ definitions.
4848
+ task_types (Optional[list[dict[str, Any]]]): Task type
4849
+ definitions.
4850
+ link_types (Optional[list[dict[str, Any]]]): Link type
4851
+ definitions.
4852
+ statuses (Optional[list[dict[str, Any]]]): Status definitions.
4853
+ tags (Optional[list[dict[str, Any]]]): List of tags available to
4854
+ set on entities.
4855
+ config (Optional[dict[dict[str, Any]]]): Project anatomy config
4856
+ with templates and roots.
4857
+ attrib (Optional[dict[str, Any]]): Project attributes to change.
4858
+ data (Optional[dict[str, Any]]): Custom data of a project. This
4859
+ value will 100% override project data.
4860
+ active (Optional[bool]): Change active state of a project.
4861
+ project_code (Optional[str]): Change project code. Not recommended
4862
+ during production.
4863
+ **changes: Other changed keys based on Rest API documentation.
4864
+ """
4865
+
4866
+ changes.update({
4867
+ key: value
4868
+ for key, value in (
4869
+ ("library", library),
4870
+ ("folderTypes", folder_types),
4871
+ ("taskTypes", task_types),
4872
+ ("linkTypes", link_types),
4873
+ ("statuses", statuses),
4874
+ ("tags", tags),
4875
+ ("config", config),
4876
+ ("attrib", attrib),
4877
+ ("data", data),
4878
+ ("active", active),
4879
+ ("code", project_code),
4880
+ )
4881
+ if value is not None
4882
+ })
4883
+ response = self.patch(
4884
+ "projects/{}".format(project_name),
4885
+ **changes
4886
+ )
4887
+ response.raise_for_status()
4888
+
4289
4889
  def delete_project(self, project_name):
4290
4890
  """Delete project from server.
4291
4891
 
ayon_api/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """Package declaring Python API for Ayon server."""
2
- __version__ = "0.2.0"
2
+ __version__ = "0.2.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -1,18 +1,18 @@
1
- ayon_api/__init__.py,sha256=KY3i3TZ_2q6U4k5UeqW-YqEKUEgjYQatmGPAuGc3UyU,6445
2
- ayon_api/_api.py,sha256=NKx5eKVhPLLQ68-4pIoA8YkC_jjRylbBvqemuMm-FaU,27676
1
+ ayon_api/__init__.py,sha256=RJqmUxlG08JfMyO7AwpIoZeRp2TURt2Qiy4eHd3s2FQ,7328
2
+ ayon_api/_api.py,sha256=XxAKKnsyly_4gt9SC1-ZZUIgtzdRNIZowNEHIjQdgBY,30191
3
3
  ayon_api/constants.py,sha256=BRhTb_yX_FaQIzeIIdUGh-fKXhiZJbFA0M_zvi9MKWQ,1755
4
- ayon_api/entity_hub.py,sha256=2oiifXj3b6zPULTKSXKB8rOKwty9KkFRUCoUA3N73Jw,56730
4
+ ayon_api/entity_hub.py,sha256=UH1-aWqftdmZAQDGqsjhpvNwAP6_bTFUk-nC-RIraO4,59757
5
5
  ayon_api/events.py,sha256=aJJbAZJ5t0t6x4VQMRfdmOGhIbiRFB0OTUGiKnasFGw,1415
6
6
  ayon_api/exceptions.py,sha256=FHGlt6TyKNc0OC8H0zxoNIS4KljPExM2mgDpCh9cYiI,2691
7
7
  ayon_api/graphql.py,sha256=4u2pSS85uDsoap0tOkAmi6KCjeKHKClH3Cd7AfY8vGM,25639
8
8
  ayon_api/graphql_queries.py,sha256=1f_fAoV1d5rvrlbJ6IPbrcrU56jmrJ-1-ieCW-B5ac8,15583
9
9
  ayon_api/operations.py,sha256=55NDgRPDhJ5faU0xUnqC2dktwx5ebJSfHkLmncismKg,19430
10
- ayon_api/server_api.py,sha256=cI9254PTYpYnZn1IDMXuwe-Jr94Qdiqi20UZg1GeOc0,161889
10
+ ayon_api/server_api.py,sha256=9Fvp8-XWg81JiqQjhmyj6ECD3b0YRbIZH9sJHTm6N2s,182164
11
11
  ayon_api/thumbnails.py,sha256=ofm6pBzGCMShryRUP76-qT9xJPtqRZn1kpoX7kVk_WA,6856
12
12
  ayon_api/utils.py,sha256=YhQkEHCho1M0D5oQHz0gl3dad-jw5nWGnvOBtvCxVHM,11714
13
- ayon_api/version.py,sha256=g_6teH09QTD4EcZ2mM1D-LWLLWYDvu96Jx0JfM06uag,74
14
- ayon_python_api-0.2.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
15
- ayon_python_api-0.2.0.dist-info/METADATA,sha256=E4QwuEIa3NRDx_WmkY04jT5G_cSd_qsUfxqEz3yn45Q,3263
16
- ayon_python_api-0.2.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
17
- ayon_python_api-0.2.0.dist-info/top_level.txt,sha256=PKrQbX5Cz53_UmSTR_nIySnBkGyHcBTS88SCw9tuVlc,9
18
- ayon_python_api-0.2.0.dist-info/RECORD,,
13
+ ayon_api/version.py,sha256=fHHwWLQEHvfwcM-NaNKV7T0r1P4zj0OAyiJ7LD0i298,74
14
+ ayon_python_api-0.2.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
15
+ ayon_python_api-0.2.2.dist-info/METADATA,sha256=kdPxbr8gk-W3u1jHeahG0xXSlPXYu5EOOre_RcX_hSM,3263
16
+ ayon_python_api-0.2.2.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
17
+ ayon_python_api-0.2.2.dist-info/top_level.txt,sha256=PKrQbX5Cz53_UmSTR_nIySnBkGyHcBTS88SCw9tuVlc,9
18
+ ayon_python_api-0.2.2.dist-info/RECORD,,