Ayon-Python-Api 1.0.0__tar.gz → 1.0.0rc1__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 (23) hide show
  1. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/PKG-INFO +1 -1
  2. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/__init__.py +4 -0
  3. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/_api.py +10 -0
  4. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/constants.py +0 -12
  5. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/entity_hub.py +11 -30
  6. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/exceptions.py +1 -4
  7. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/graphql_queries.py +10 -6
  8. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/server_api.py +238 -139
  9. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/version.py +1 -1
  10. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_python_api.egg-info/PKG-INFO +1 -1
  11. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/pyproject.toml +1 -1
  12. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/LICENSE +0 -0
  13. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/README.md +0 -0
  14. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/events.py +0 -0
  15. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/graphql.py +0 -0
  16. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/operations.py +0 -0
  17. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_api/utils.py +0 -0
  18. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_python_api.egg-info/SOURCES.txt +0 -0
  19. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_python_api.egg-info/dependency_links.txt +0 -0
  20. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_python_api.egg-info/requires.txt +0 -0
  21. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/ayon_python_api.egg-info/top_level.txt +0 -0
  22. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/setup.cfg +0 -0
  23. {ayon-python-api-1.0.0 → ayon-python-api-1.0.0rc1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 1.0.0
3
+ Version: 1.0.0rc1
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -75,6 +75,8 @@ from ._api import (
75
75
  download_installer,
76
76
  upload_installer,
77
77
 
78
+ get_dependencies_info,
79
+ update_dependency_info,
78
80
  get_dependency_packages,
79
81
  create_dependency_package,
80
82
  update_dependency_package,
@@ -275,6 +277,8 @@ __all__ = (
275
277
  "download_installer",
276
278
  "upload_installer",
277
279
 
280
+ "get_dependencies_info",
281
+ "update_dependency_info",
278
282
  "get_dependency_packages",
279
283
  "create_dependency_package",
280
284
  "update_dependency_package",
@@ -611,6 +611,16 @@ def upload_installer(*args, **kwargs):
611
611
 
612
612
 
613
613
  # Dependency packages
614
+ def get_dependencies_info(*args, **kwargs):
615
+ con = get_server_api_connection()
616
+ return con.get_dependencies_info(*args, **kwargs)
617
+
618
+
619
+ def update_dependency_info(*args, **kwargs):
620
+ con = get_server_api_connection()
621
+ return con.update_dependency_info(*args, **kwargs)
622
+
623
+
614
624
  def download_dependency_package(*args, **kwargs):
615
625
  con = get_server_api_connection()
616
626
  return con.download_dependency_package(*args, **kwargs)
@@ -146,15 +146,3 @@ DEFAULT_EVENT_FIELDS = {
146
146
  "updatedAt",
147
147
  "user",
148
148
  }
149
-
150
- DEFAULT_LINK_FIELDS = {
151
- "id",
152
- "linkType",
153
- "projectName",
154
- "entityType",
155
- "entityId",
156
- "name",
157
- "direction",
158
- "description",
159
- "author",
160
- }
@@ -7,21 +7,9 @@ import six
7
7
  from ._api import get_server_api_connection
8
8
  from .utils import create_entity_id, convert_entity_id, slugify_string
9
9
 
10
-
11
- class _CustomNone(object):
12
- def __init__(self, name=None):
13
- self._name = name or "CustomNone"
14
-
15
- def __repr__(self):
16
- return "<{}>".format(self._name)
17
-
18
- def __bool__(self):
19
- return False
20
-
21
-
22
- UNKNOWN_VALUE = _CustomNone("UNKNOWN_VALUE")
23
- PROJECT_PARENT_ID = _CustomNone("PROJECT_PARENT_ID")
24
- _NOT_SET = _CustomNone("_NOT_SET")
10
+ UNKNOWN_VALUE = object()
11
+ PROJECT_PARENT_ID = object()
12
+ _NOT_SET = object()
25
13
 
26
14
 
27
15
  class EntityHub(object):
@@ -231,10 +219,7 @@ class EntityHub(object):
231
219
  return None
232
220
 
233
221
  if entity_type == "folder":
234
- folder_entity = self.add_folder(entity_data)
235
- folder_entity.has_published_content = entity_data["hasProducts"]
236
- return folder_entity
237
-
222
+ return self.add_folder(entity_data)
238
223
  elif entity_type == "task":
239
224
  return self.add_task(entity_data)
240
225
 
@@ -486,14 +471,13 @@ class EntityHub(object):
486
471
  }
487
472
  for folder in folders:
488
473
  folder_entity = self._entities_by_id.get(folder["id"])
489
- if folder_entity is None:
490
- folder_entity = self.add_folder(folder)
491
- children_ids.add(folder_entity.id)
492
-
493
- elif folder_entity.parent_id == entity.id:
494
- children_ids.add(folder_entity.id)
474
+ if folder_entity is not None:
475
+ if folder_entity.parent_id == entity.id:
476
+ children_ids.add(folder_entity.id)
477
+ continue
495
478
 
496
- folder_entity.has_published_content = folder["hasProducts"]
479
+ folder_entity = self.add_folder(folder)
480
+ children_ids.add(folder_entity.id)
497
481
 
498
482
  for task in tasks:
499
483
  task_entity = self._entities_by_id.get(task["id"])
@@ -1300,10 +1284,7 @@ class BaseEntity(object):
1300
1284
  changes["name"] = self._name
1301
1285
 
1302
1286
  if self._entity_hub.allow_data_changes:
1303
- if (
1304
- self._data is not UNKNOWN_VALUE
1305
- and self._orig_data != self._data
1306
- ):
1287
+ if self._orig_data != self._data:
1307
1288
  changes["data"] = self._data
1308
1289
 
1309
1290
  if self._orig_thumbnail_id != self._thumbnail_id:
@@ -53,10 +53,7 @@ class GraphQlQueryFailed(Exception):
53
53
  msg = error["message"]
54
54
  path = error.get("path")
55
55
  if path:
56
- msg += " on item '{}'".format("/".join(
57
- # Convert to string
58
- str(x) for x in path
59
- ))
56
+ msg += " on item '{}'".format("/".join(path))
60
57
  locations = error.get("locations")
61
58
  if locations:
62
59
  _locations = [
@@ -1,6 +1,5 @@
1
1
  import collections
2
2
 
3
- from .constants import DEFAULT_LINK_FIELDS
4
3
  from .graphql import FIELD_VALUE, GraphQlQuery
5
4
 
6
5
 
@@ -31,7 +30,16 @@ def add_links_fields(entity_field, nested_fields):
31
30
  return
32
31
  links_fields = nested_fields.pop("links")
33
32
 
34
- link_edge_fields = set(DEFAULT_LINK_FIELDS)
33
+ link_edge_fields = {
34
+ "id",
35
+ "linkType",
36
+ "projectName",
37
+ "entityType",
38
+ "entityId",
39
+ "direction",
40
+ "description",
41
+ "author",
42
+ }
35
43
  if isinstance(links_fields, dict):
36
44
  simple_fields = set(links_fields)
37
45
  simple_variant = len(simple_fields - link_edge_fields) == 0
@@ -41,12 +49,8 @@ def add_links_fields(entity_field, nested_fields):
41
49
 
42
50
  link_field = entity_field.add_field_with_edges("links")
43
51
 
44
- link_name_var = link_field.add_variable("linkNames", "[String!]")
45
- link_name_regex_var = link_field.add_variable("linkNameRegex", "String!")
46
52
  link_type_var = link_field.add_variable("linkTypes", "[String!]")
47
53
  link_dir_var = link_field.add_variable("linkDirection", "String!")
48
- link_field.set_filter("names", link_name_var)
49
- link_field.set_filter("nameEx", link_name_regex_var)
50
54
  link_field.set_filter("linkTypes", link_type_var)
51
55
  link_field.set_filter("direction", link_dir_var)
52
56
 
@@ -8,7 +8,6 @@ import collections
8
8
  import platform
9
9
  import copy
10
10
  import uuid
11
- import warnings
12
11
  from contextlib import contextmanager
13
12
 
14
13
  import six
@@ -43,7 +42,6 @@ from .constants import (
43
42
  DEFAULT_WORKFILE_INFO_FIELDS,
44
43
  DEFAULT_EVENT_FIELDS,
45
44
  DEFAULT_USER_FIELDS,
46
- DEFAULT_LINK_FIELDS,
47
45
  )
48
46
  from .graphql import GraphQlQuery, INTROSPECTION_QUERY
49
47
  from .graphql_queries import (
@@ -188,8 +186,6 @@ class RestApiResponse(object):
188
186
  raise ServerError(self._data["detail"])
189
187
  raise ValueError("Response is not available.")
190
188
 
191
- if self.status_code == 401:
192
- raise UnauthorizedError("Missing or invalid authentication token")
193
189
  try:
194
190
  self._response.raise_for_status()
195
191
  except requests.exceptions.HTTPError as exc:
@@ -917,7 +913,6 @@ class ServerAPI(object):
917
913
  """
918
914
 
919
915
  response = self.get("info")
920
- response.raise_for_status()
921
916
  return response.data
922
917
 
923
918
  def get_server_version(self):
@@ -986,9 +981,7 @@ class ServerAPI(object):
986
981
 
987
982
  if self._access_token_is_service is not None:
988
983
  response = self.get("users/me")
989
- if response.status == 200:
990
- return response.data
991
- return None
984
+ return response.data
992
985
 
993
986
  self._access_token_is_service = False
994
987
  response = self.get("users/me")
@@ -1029,22 +1022,31 @@ class ServerAPI(object):
1029
1022
  for attr, filter_value in filters.items():
1030
1023
  query.set_variable_value(attr, filter_value)
1031
1024
 
1025
+ # Backwards compatibility for server 0.3.x
1026
+ # - will be removed in future releases
1027
+ major, minor, _, _, _ = self.server_version_tuple
1028
+ access_groups_field = "accessGroups"
1029
+ if major == 0 and minor <= 3:
1030
+ access_groups_field = "roles"
1031
+
1032
1032
  for parsed_data in query.continuous_query(self):
1033
1033
  for user in parsed_data["users"]:
1034
- user["accessGroups"] = json.loads(
1035
- user["accessGroups"])
1034
+ user[access_groups_field] = json.loads(
1035
+ user[access_groups_field])
1036
1036
  yield user
1037
1037
 
1038
1038
  def get_user(self, username=None):
1039
+ output = None
1039
1040
  if username is None:
1040
1041
  output = self._get_user_info()
1041
- if output is None:
1042
- raise UnauthorizedError("User is not authorized.")
1043
- return output
1042
+ else:
1043
+ response = self.get("users/{}".format(username))
1044
+ if response.status == 200:
1045
+ output = response.data
1044
1046
 
1045
- response = self.get("users/{}".format(username))
1046
- response.raise_for_status()
1047
- return response.data
1047
+ if output is None:
1048
+ raise UnauthorizedError("User is not authorized.")
1049
+ return output
1048
1050
 
1049
1051
  def get_headers(self, content_type=None):
1050
1052
  if content_type is None:
@@ -1859,7 +1861,10 @@ class ServerAPI(object):
1859
1861
 
1860
1862
  if self._attributes_schema is None:
1861
1863
  result = self.get("attributes")
1862
- result.raise_for_status()
1864
+ if result.status_code != 200:
1865
+ raise UnauthorizedError(
1866
+ "User must be authorized to receive attributes"
1867
+ )
1863
1868
  self._attributes_schema = result.data
1864
1869
  return copy.deepcopy(self._attributes_schema)
1865
1870
 
@@ -2039,6 +2044,14 @@ class ServerAPI(object):
2039
2044
 
2040
2045
  elif entity_type == "user":
2041
2046
  entity_type_defaults = set(DEFAULT_USER_FIELDS)
2047
+ # Backwards compatibility for server 0.3.x
2048
+ # - will be removed in future releases
2049
+ major, minor, _, _, _ = self.server_version_tuple
2050
+ if major == 0 and minor <= 3:
2051
+ entity_type_defaults.discard("accessGroups")
2052
+ entity_type_defaults.discard("defaultAccessGroups")
2053
+ entity_type_defaults.add("roles")
2054
+ entity_type_defaults.add("defaultRoles")
2042
2055
 
2043
2056
  else:
2044
2057
  raise ValueError("Unknown entity type \"{}\"".format(entity_type))
@@ -2293,8 +2306,125 @@ class ServerAPI(object):
2293
2306
  progress=progress
2294
2307
  )
2295
2308
 
2296
- def _get_dependency_package_route(self, filename=None):
2297
- endpoint = "desktop/dependencyPackages"
2309
+ def get_dependencies_info(self):
2310
+ """Information about dependency packages on server.
2311
+
2312
+ Example data structure:
2313
+ {
2314
+ "packages": [
2315
+ {
2316
+ "name": str,
2317
+ "platform": str,
2318
+ "checksum": str,
2319
+ "sources": list[dict[str, Any]],
2320
+ "supportedAddons": dict[str, str],
2321
+ "pythonModules": dict[str, str]
2322
+ }
2323
+ ],
2324
+ "productionPackage": str
2325
+ }
2326
+
2327
+ Deprecated:
2328
+ Deprecated since server version 0.2.1. Use
2329
+ 'get_dependency_packages' instead.
2330
+
2331
+ Returns:
2332
+ dict[str, Any]: Information about dependency packages known for
2333
+ server.
2334
+ """
2335
+
2336
+ major, minor, patch, _, _ = self.server_version_tuple
2337
+ if major == 0 and (minor < 2 or (minor == 2 and patch < 1)):
2338
+ result = self.get("dependencies")
2339
+ return result.data
2340
+ packages = self.get_dependency_packages()
2341
+ packages["productionPackage"] = None
2342
+ return packages
2343
+
2344
+ def update_dependency_info(
2345
+ self,
2346
+ name,
2347
+ platform_name,
2348
+ size,
2349
+ checksum,
2350
+ checksum_algorithm=None,
2351
+ supported_addons=None,
2352
+ python_modules=None,
2353
+ sources=None
2354
+ ):
2355
+ """Update or create dependency package for identifiers.
2356
+
2357
+ The endpoint can be used to create or update dependency package.
2358
+
2359
+
2360
+ Deprecated:
2361
+ Deprecated for server version 0.2.1. Use
2362
+ 'create_dependency_pacakge' instead.
2363
+
2364
+ Args:
2365
+ name (str): Name of dependency package.
2366
+ platform_name (Literal["windows", "linux", "darwin"]): Platform
2367
+ for which is dependency package targeted.
2368
+ size (int): Size of dependency package in bytes.
2369
+ checksum (str): Checksum of archive file where dependencies are.
2370
+ checksum_algorithm (Optional[str]): Algorithm used to calculate
2371
+ checksum. By default, is used 'md5' (defined by server).
2372
+ supported_addons (Optional[dict[str, str]]): Name of addons for
2373
+ which was the package created.
2374
+ '{"<addon name>": "<addon version>", ...}'
2375
+ python_modules (Optional[dict[str, str]]): Python modules in
2376
+ dependencies package.
2377
+ '{"<module name>": "<module version>", ...}'
2378
+ sources (Optional[list[dict[str, Any]]]): Information about
2379
+ sources where dependency package is available.
2380
+ """
2381
+
2382
+ kwargs = {
2383
+ key: value
2384
+ for key, value in (
2385
+ ("checksumAlgorithm", checksum_algorithm),
2386
+ ("supportedAddons", supported_addons),
2387
+ ("pythonModules", python_modules),
2388
+ ("sources", sources),
2389
+ )
2390
+ if value
2391
+ }
2392
+
2393
+ response = self.put(
2394
+ "dependencies",
2395
+ name=name,
2396
+ platform=platform_name,
2397
+ size=size,
2398
+ checksum=checksum,
2399
+ **kwargs
2400
+ )
2401
+ response.raise_for_status("Failed to create/update dependency")
2402
+ return response.data
2403
+
2404
+ def _get_dependency_package_route(
2405
+ self, filename=None, platform_name=None
2406
+ ):
2407
+ major, minor, patch, _, _ = self.server_version_tuple
2408
+ if (major, minor, patch) <= (0, 2, 0):
2409
+ # Backwards compatibility for AYON server 0.2.0 and lower
2410
+ self.log.warning((
2411
+ "Using deprecated dependency package route."
2412
+ " Please update your AYON server to version 0.2.1 or higher."
2413
+ " Backwards compatibility for this route will be removed"
2414
+ " in future releases of ayon-python-api."
2415
+ ))
2416
+ if platform_name is None:
2417
+ platform_name = platform.system().lower()
2418
+ base = "dependencies"
2419
+ if not filename:
2420
+ return base
2421
+ return "{}/{}/{}".format(base, filename, platform_name)
2422
+
2423
+ if (major, minor) <= (0, 3):
2424
+ endpoint = "desktop/dependency_packages"
2425
+ else:
2426
+ endpoint = "desktop/dependencyPackages"
2427
+
2298
2428
  if filename:
2299
2429
  return "{}/{}".format(endpoint, filename)
2300
2430
  return endpoint
@@ -2405,21 +2535,14 @@ class ServerAPI(object):
2405
2535
  """Remove dependency package for specific platform.
2406
2536
 
2407
2537
  Args:
2408
- filename (str): Filename of dependency package.
2409
- platform_name (Optional[str]): Deprecated.
2538
+ filename (str): Filename of dependency package. Or name of package
2539
+ for server version 0.2.0 or lower.
2540
+ platform_name (Optional[str]): Which platform of the package
2541
+ should be removed. Current platform is used if not passed.
2542
+ Deprecated since version 0.2.1
2410
2543
  """
2411
2544
 
2412
- if platform_name is not None:
2413
- warnings.warn(
2414
- (
2415
- "Argument 'platform_name' is deprecated in"
2416
- " 'delete_dependency_package'. The argument will be"
2417
- " removed, please modify your code accordingly."
2418
- ),
2419
- DeprecationWarning
2420
- )
2421
-
2422
- route = self._get_dependency_package_route(filename)
2545
+ route = self._get_dependency_package_route(filename, platform_name)
2423
2546
  response = self.delete(route)
2424
2547
  response.raise_for_status("Failed to delete dependency file")
2425
2548
  return response.data
@@ -2444,25 +2567,18 @@ class ServerAPI(object):
2444
2567
  to download.
2445
2568
  dst_directory (str): Where the file should be downloaded.
2446
2569
  dst_filename (str): Name of destination filename.
2447
- platform_name (Optional[str]): Deprecated.
2570
+ platform_name (Optional[str]): Name of platform for which the
2571
+ dependency package is targeted. Default value is
2572
+ current platform. Deprecated since server version 0.2.1.
2448
2573
  chunk_size (Optional[int]): Download chunk size.
2449
2574
  progress (Optional[TransferProgress]): Object that gives ability
2450
2575
  to track download progress.
2451
2576
 
2452
2577
  Returns:
2453
2578
  str: Filepath to downloaded file.
2454
- """
2579
+ """
2455
2580
 
2456
- if platform_name is not None:
2457
- warnings.warn(
2458
- (
2459
- "Argument 'platform_name' is deprecated in"
2460
- " 'download_dependency_package'. The argument will be"
2461
- " removed, please modify your code accordingly."
2462
- ),
2463
- DeprecationWarning
2464
- )
2465
- route = self._get_dependency_package_route(src_filename)
2581
+ route = self._get_dependency_package_route(src_filename, platform_name)
2466
2582
  package_filepath = os.path.join(dst_directory, dst_filename)
2467
2583
  self.download_file(
2468
2584
  route,
@@ -2481,24 +2597,32 @@ class ServerAPI(object):
2481
2597
  src_filepath (str): Path to a package file.
2482
2598
  dst_filename (str): Dependency package filename or name of package
2483
2599
  for server version 0.2.0 or lower. Must be unique.
2484
- platform_name (Optional[str]): Deprecated.
2600
+ platform_name (Optional[str]): For which platform is the
2601
+ package targeted. Deprecated since server version 0.2.1.
2485
2602
  progress (Optional[TransferProgress]): Object to keep track about
2486
2603
  upload state.
2487
2604
  """
2488
2605
 
2489
- if platform_name is not None:
2490
- warnings.warn(
2491
- (
2492
- "Argument 'platform_name' is deprecated in"
2493
- " 'upload_dependency_package'. The argument will be"
2494
- " removed, please modify your code accordingly."
2495
- ),
2496
- DeprecationWarning
2497
- )
2498
-
2499
- route = self._get_dependency_package_route(dst_filename)
2606
+ route = self._get_dependency_package_route(dst_filename, platform_name)
2500
2607
  self.upload_file(route, src_filepath, progress=progress)
2501
2608
 
2609
+ def create_dependency_package_basename(self, platform_name=None):
2610
+ """Create basename for dependency package file.
2611
+
2612
+ Deprecated:
2613
+ Use 'create_dependency_package_basename' from `ayon_api` or
2614
+ `ayon_api.utils` instead.
2615
+
2616
+ Args:
2617
+ platform_name (Optional[str]): Name of platform for which the
2618
+ bundle is targeted. Default value is current platform.
2619
+
2620
+ Returns:
2621
+ str: Dependency package name with timestamp and platform.
2622
+ """
2623
+
2624
+ return create_dependency_package_basename(platform_name)
2625
+
2502
2626
  def upload_addon_zip(self, src_filepath, progress=None):
2503
2627
  """Upload addon zip file to server.
2504
2628
 
@@ -2526,6 +2650,14 @@ class ServerAPI(object):
2526
2650
  )
2527
2651
  return response.json()
2528
2652
 
2653
+ def _get_bundles_route(self):
2654
+ major, minor, patch, _, _ = self.server_version_tuple
2655
+ # Backwards compatibility for AYON server 0.3.0
2656
+ # - first version where bundles were available
2657
+ if major == 0 and minor == 3 and patch == 0:
2658
+ return "desktop/bundles"
2659
+ return "bundles"
2660
+
2529
2661
  def get_bundles(self):
2530
2662
  """Server bundles with basic information.
2531
2663
 
@@ -2556,7 +2688,7 @@ class ServerAPI(object):
2556
2688
  dict[str, Any]: Server bundles with basic information.
2557
2689
  """
2558
2690
 
2559
- response = self.get("bundles")
2691
+ response = self.get(self._get_bundles_route())
2560
2692
  response.raise_for_status()
2561
2693
  return response.data
2562
2694
 
@@ -2599,7 +2731,7 @@ class ServerAPI(object):
2599
2731
  if value is not None:
2600
2732
  body[key] = value
2601
2733
 
2602
- response = self.post("bundles", **body)
2734
+ response = self.post(self._get_bundles_route(), **body)
2603
2735
  response.raise_for_status()
2604
2736
 
2605
2737
  def update_bundle(
@@ -2634,7 +2766,7 @@ class ServerAPI(object):
2634
2766
  if value is not None
2635
2767
  }
2636
2768
  response = self.patch(
2637
- "{}/{}".format("bundles", bundle_name),
2769
+ "{}/{}".format(self._get_bundles_route(), bundle_name),
2638
2770
  **body
2639
2771
  )
2640
2772
  response.raise_for_status()
@@ -2647,7 +2779,7 @@ class ServerAPI(object):
2647
2779
  """
2648
2780
 
2649
2781
  response = self.delete(
2650
- "{}/{}".format("bundles", bundle_name)
2782
+ "{}/{}".format(self._get_bundles_route(), bundle_name)
2651
2783
  )
2652
2784
  response.raise_for_status()
2653
2785
 
@@ -2970,13 +3102,16 @@ class ServerAPI(object):
2970
3102
  - test how it behaves if there is not any production/staging
2971
3103
  bundle.
2972
3104
 
3105
+ Warnings:
3106
+ For AYON server < 0.3.0 bundle name will be ignored.
3107
+
2973
3108
  Example output:
2974
3109
  {
2975
3110
  "addons": [
2976
3111
  {
2977
3112
  "name": "addon-name",
2978
3113
  "version": "addon-version",
2979
- "settings": {...},
3114
+ "settings": {...}
2980
3115
  "siteSettings": {...}
2981
3116
  }
2982
3117
  ]
@@ -2986,6 +3121,7 @@ class ServerAPI(object):
2986
3121
  dict[str, Any]: All settings for single bundle.
2987
3122
  """
2988
3123
 
3124
+ major, minor, _, _, _ = self.server_version_tuple
2989
3125
  query_values = {
2990
3126
  key: value
2991
3127
  for key, value in (
@@ -3001,8 +3137,21 @@ class ServerAPI(object):
3001
3137
  if site_id:
3002
3138
  query_values["site_id"] = site_id
3003
3139
 
3140
+ if major == 0 and minor >= 3:
3141
+ url = "settings"
3142
+ else:
3143
+ # Backward compatibility for AYON server < 0.3.0
3144
+ url = "settings/addons"
3145
+ query_values.pop("bundle_name", None)
3146
+ for new_key, old_key in (
3147
+ ("project_name", "project"),
3148
+ ("site_id", "site"),
3149
+ ):
3150
+ if new_key in query_values:
3151
+ query_values[old_key] = query_values.pop(new_key)
3152
+
3004
3153
  query = prepare_query_string(query_values)
3005
- response = self.get("settings{}".format(query))
3154
+ response = self.get("{}{}".format(url, query))
3006
3155
  response.raise_for_status()
3007
3156
  return response.data
3008
3157
 
@@ -3045,10 +3194,15 @@ class ServerAPI(object):
3045
3194
  use_site=use_site
3046
3195
  )
3047
3196
  if only_values:
3048
- output = {
3049
- addon["name"]: addon["settings"]
3050
- for addon in output["addons"]
3051
- }
3197
+ major, minor, patch, _, _ = self.server_version_tuple
3198
+ if major == 0 and minor >= 3:
3199
+ output = {
3200
+ addon["name"]: addon["settings"]
3201
+ for addon in output["addons"]
3202
+ }
3203
+ else:
3204
+ # Backward compatibility for AYON server < 0.3.0
3205
+ output = output["settings"]
3052
3206
  return output
3053
3207
 
3054
3208
  def get_addons_project_settings(
@@ -3109,10 +3263,15 @@ class ServerAPI(object):
3109
3263
  use_site=use_site
3110
3264
  )
3111
3265
  if only_values:
3112
- output = {
3113
- addon["name"]: addon["settings"]
3114
- for addon in output["addons"]
3115
- }
3266
+ major, minor, patch, _, _ = self.server_version_tuple
3267
+ if major == 0 and minor >= 3:
3268
+ output = {
3269
+ addon["name"]: addon["settings"]
3270
+ for addon in output["addons"]
3271
+ }
3272
+ else:
3273
+ # Backward compatibility for AYON server < 0.3.0
3274
+ output = output["settings"]
3116
3275
  return output
3117
3276
 
3118
3277
  def get_addons_settings(
@@ -5975,8 +6134,7 @@ class ServerAPI(object):
5975
6134
  input_id,
5976
6135
  input_type,
5977
6136
  output_id,
5978
- output_type,
5979
- link_name=None,
6137
+ output_type
5980
6138
  ):
5981
6139
  """Create link between 2 entities.
5982
6140
 
@@ -5994,8 +6152,6 @@ class ServerAPI(object):
5994
6152
  input_type (str): Entity type of input entity.
5995
6153
  output_id (str): Id of output entity.
5996
6154
  output_type (str): Entity type of output entity.
5997
- link_name (Optional[str]): Name of link.
5998
- Available from server version '1.0.0-rc.6'.
5999
6155
 
6000
6156
  Returns:
6001
6157
  dict[str, str]: Information about link.
@@ -6006,31 +6162,11 @@ class ServerAPI(object):
6006
6162
 
6007
6163
  full_link_type_name = self.get_full_link_type_name(
6008
6164
  link_type_name, input_type, output_type)
6009
-
6010
- kwargs = {
6011
- "input": input_id,
6012
- "output": output_id,
6013
- }
6014
- major, minor, patch, rel, _ = self.server_version_tuple
6015
- rel_regex = re.compile(r"rc\.[0-5]")
6016
- if (
6017
- ((major, minor, patch) == (1, 0, 0) and rel_regex.match(rel))
6018
- or (major, minor, patch) < (1, 0, 0)
6019
- ):
6020
- kwargs["link"] = full_link_type_name
6021
- if link_name:
6022
- raise NotImplementedError((
6023
- "Link name is not supported"
6024
- " for version of AYON server {}"
6025
- ).format(self.server_version))
6026
- else:
6027
- kwargs["linkType"] = full_link_type_name
6028
-
6029
- if link_name:
6030
- kwargs["name"] = link_name
6031
-
6032
6165
  response = self.post(
6033
- "projects/{}/links".format(project_name), **kwargs
6166
+ "projects/{}/links".format(project_name),
6167
+ link=full_link_type_name,
6168
+ input=input_id,
6169
+ output=output_id
6034
6170
  )
6035
6171
  response.raise_for_status()
6036
6172
  return response.data
@@ -6051,9 +6187,7 @@ class ServerAPI(object):
6051
6187
  )
6052
6188
  response.raise_for_status()
6053
6189
 
6054
- def _prepare_link_filters(
6055
- self, filters, link_types, link_direction, link_names, link_name_regex
6056
- ):
6190
+ def _prepare_link_filters(self, filters, link_types, link_direction):
6057
6191
  """Add links filters for GraphQl queries.
6058
6192
 
6059
6193
  Args:
@@ -6061,8 +6195,6 @@ class ServerAPI(object):
6061
6195
  link_types (Union[Iterable[str], None]): Link types filters.
6062
6196
  link_direction (Union[Literal["in", "out"], None]): Direction of
6063
6197
  link "in", "out" or 'None' for both.
6064
- link_names (Union[Iterable[str], None]): Link name filters.
6065
- link_name_regex (Union[str, None]): Regex filter for link name.
6066
6198
 
6067
6199
  Returns:
6068
6200
  bool: Links are valid, and query from server can happen.
@@ -6074,19 +6206,10 @@ class ServerAPI(object):
6074
6206
  return False
6075
6207
  filters["linkTypes"] = list(link_types)
6076
6208
 
6077
- if link_names is not None:
6078
- link_names = set(link_names)
6079
- if not link_names:
6080
- return False
6081
- filters["linkNames"] = list(link_names)
6082
-
6083
6209
  if link_direction is not None:
6084
6210
  if link_direction not in ("in", "out"):
6085
6211
  return False
6086
6212
  filters["linkDirection"] = link_direction
6087
-
6088
- if link_name_regex is not None:
6089
- filters["linkNameRegex"] = link_name_regex
6090
6213
  return True
6091
6214
 
6092
6215
  def get_entities_links(
@@ -6095,9 +6218,7 @@ class ServerAPI(object):
6095
6218
  entity_type,
6096
6219
  entity_ids=None,
6097
6220
  link_types=None,
6098
- link_direction=None,
6099
- link_names=None,
6100
- link_name_regex=None,
6221
+ link_direction=None
6101
6222
  ):
6102
6223
  """Helper method to get links from server for entity types.
6103
6224
 
@@ -6128,8 +6249,6 @@ class ServerAPI(object):
6128
6249
  link_types (Optional[Iterable[str]]): Link type filters.
6129
6250
  link_direction (Optional[Literal["in", "out"]]): Link direction
6130
6251
  filter.
6131
- link_names (Optional[Iterable[str]]): Link name filters.
6132
- link_name_regex (Optional[str]): Regex filter for link name.
6133
6252
 
6134
6253
  Returns:
6135
6254
  dict[str, list[dict[str, Any]]]: Link info by entity ids.
@@ -6173,30 +6292,10 @@ class ServerAPI(object):
6173
6292
  return output
6174
6293
  filters[id_filter_key] = list(entity_ids)
6175
6294
 
6176
- if not self._prepare_link_filters(
6177
- filters, link_types, link_direction, link_names, link_name_regex
6178
- ):
6295
+ if not self._prepare_link_filters(filters, link_types, link_direction):
6179
6296
  return output
6180
6297
 
6181
- link_fields = {"id", "links"}
6182
- # Backwards compatibility for server version 1.0.0-rc.5 and lower
6183
- # ---------
6184
- major, minor, patch, rel, _ = self.server_version_tuple
6185
- rel_regex = re.compile(r"rc\.[0-5]")
6186
- if (
6187
- ((major, minor, patch) == (1, 0, 0) and rel_regex.match(rel))
6188
- or (major, minor, patch) < (1, 0, 0)
6189
- ):
6190
- fields = set(DEFAULT_LINK_FIELDS)
6191
- fields.discard("name")
6192
- link_fields.discard("links")
6193
- link_fields |= {
6194
- "links.{}".format(field)
6195
- for field in fields
6196
- }
6197
- # ---------
6198
-
6199
- query = query_func(link_fields)
6298
+ query = query_func({"id", "links"})
6200
6299
  for attr, filter_value in filters.items():
6201
6300
  query.set_variable_value(attr, filter_value)
6202
6301
 
@@ -1,2 +1,2 @@
1
1
  """Package declaring Python API for Ayon server."""
2
- __version__ = "1.0.0"
2
+ __version__ = "1.0.0-rc.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 1.0.0
3
+ Version: 1.0.0rc1
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ayon-python-api"
3
- version = "1.0.0"
3
+ version = "1.0.0-rc.1"
4
4
  description = "AYON Python API"
5
5
  license = {file = "LICENSE"}
6
6
  readme = {file = "README.md", content-type = "text/markdown"}