Ayon-Python-Api 0.5.2__tar.gz → 0.5.3__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-0.5.2 → ayon-python-api-0.5.3}/PKG-INFO +1 -1
  2. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/_api.py +1 -1
  3. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/constants.py +11 -0
  4. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/entity_hub.py +5 -2
  5. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/server_api.py +83 -15
  6. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/utils.py +25 -1
  7. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/version.py +1 -1
  8. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_python_api.egg-info/PKG-INFO +1 -1
  9. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/pyproject.toml +1 -1
  10. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/LICENSE +0 -0
  11. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/README.md +0 -0
  12. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/__init__.py +0 -0
  13. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/events.py +0 -0
  14. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/exceptions.py +0 -0
  15. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/graphql.py +0 -0
  16. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/graphql_queries.py +0 -0
  17. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_api/operations.py +0 -0
  18. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_python_api.egg-info/SOURCES.txt +0 -0
  19. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_python_api.egg-info/dependency_links.txt +0 -0
  20. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_python_api.egg-info/requires.txt +0 -0
  21. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/ayon_python_api.egg-info/top_level.txt +0 -0
  22. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/setup.cfg +0 -0
  23. {ayon-python-api-0.5.2 → ayon-python-api-0.5.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -374,7 +374,7 @@ def get_default_settings_variant():
374
374
  """
375
375
 
376
376
  con = get_server_api_connection()
377
- return con.get_client_version()
377
+ return con.get_default_settings_variant()
378
378
 
379
379
 
380
380
  def set_default_settings_variant(variant):
@@ -3,6 +3,10 @@ SERVER_URL_ENV_KEY = "AYON_SERVER_URL"
3
3
  SERVER_API_ENV_KEY = "AYON_API_KEY"
4
4
  SERVER_TIMEOUT_ENV_KEY = "AYON_SERVER_TIMEOUT"
5
5
  SERVER_RETRIES_ENV_KEY = "AYON_SERVER_RETRIES"
6
+ # Default variant used for settings
7
+ DEFAULT_VARIANT_ENV_KEY = "AYON_DEFAULT_SETTINGS_VARIANT"
8
+ # Default site id used for connection
9
+ SITE_ID_ENV_KEY = "AYON_SITE_ID"
6
10
 
7
11
  # Backwards compatibility
8
12
  SERVER_TOKEN_ENV_KEY = SERVER_API_ENV_KEY
@@ -40,6 +44,7 @@ DEFAULT_PROJECT_FIELDS = {
40
44
  "code",
41
45
  "config",
42
46
  "createdAt",
47
+ "data",
43
48
  }
44
49
 
45
50
  # --- Folders ---
@@ -52,6 +57,7 @@ DEFAULT_FOLDER_FIELDS = {
52
57
  "parentId",
53
58
  "active",
54
59
  "thumbnailId",
60
+ "data",
55
61
  }
56
62
 
57
63
  # --- Tasks ---
@@ -63,6 +69,7 @@ DEFAULT_TASK_FIELDS = {
63
69
  "folderId",
64
70
  "active",
65
71
  "assignees",
72
+ "data",
66
73
  }
67
74
 
68
75
  # --- Products ---
@@ -72,6 +79,7 @@ DEFAULT_PRODUCT_FIELDS = {
72
79
  "folderId",
73
80
  "active",
74
81
  "productType",
82
+ "data",
75
83
  }
76
84
 
77
85
  # --- Versions ---
@@ -86,6 +94,7 @@ DEFAULT_VERSION_FIELDS = {
86
94
  "thumbnailId",
87
95
  "createdAt",
88
96
  "updatedAt",
97
+ "data",
89
98
  }
90
99
 
91
100
  # --- Representations ---
@@ -96,6 +105,7 @@ DEFAULT_REPRESENTATION_FIELDS = {
96
105
  "createdAt",
97
106
  "active",
98
107
  "versionId",
108
+ "data",
99
109
  }
100
110
 
101
111
  REPRESENTATION_FILES_FIELDS = {
@@ -119,6 +129,7 @@ DEFAULT_WORKFILE_INFO_FIELDS = {
119
129
  "thumbnailId",
120
130
  "updatedAt",
121
131
  "updatedBy",
132
+ "data",
122
133
  }
123
134
 
124
135
  DEFAULT_EVENT_FIELDS = {
@@ -36,15 +36,18 @@ class EntityHub(object):
36
36
  """
37
37
 
38
38
  def __init__(
39
- self, project_name, connection=None, allow_data_changes=False
39
+ self, project_name, connection=None, allow_data_changes=None
40
40
  ):
41
41
  if not connection:
42
42
  connection = get_server_api_connection()
43
- major, minor, _, _, _ = connection.server_version_tuple
43
+ major, minor, patch, _, _ = connection.server_version_tuple
44
44
  path_start_with_slash = True
45
45
  if (major, minor) < (0, 6):
46
46
  path_start_with_slash = False
47
47
 
48
+ if allow_data_changes is None:
49
+ allow_data_changes = connection.graphql_allows_data_in_query
50
+
48
51
  self._connection = connection
49
52
  self._path_start_with_slash = path_start_with_slash
50
53
 
@@ -9,6 +9,9 @@ import platform
9
9
  import copy
10
10
  import uuid
11
11
  from contextlib import contextmanager
12
+
13
+ import six
14
+
12
15
  try:
13
16
  from http import HTTPStatus
14
17
  except ImportError:
@@ -27,7 +30,6 @@ except ImportError:
27
30
  from json import JSONDecodeError as RequestsJSONDecodeError
28
31
 
29
32
  from .constants import (
30
- SERVER_TIMEOUT_ENV_KEY,
31
33
  SERVER_RETRIES_ENV_KEY,
32
34
  DEFAULT_PRODUCT_TYPE_FIELDS,
33
35
  DEFAULT_PROJECT_FIELDS,
@@ -76,8 +78,11 @@ from .utils import (
76
78
  create_dependency_package_basename,
77
79
  ThumbnailContent,
78
80
  get_default_timeout,
81
+ get_default_settings_variant,
82
+ get_default_site_id,
79
83
  )
80
84
 
85
+ _PLACEHOLDER = object()
81
86
  PatternType = type(re.compile(""))
82
87
  JSONDecodeError = getattr(json, "JSONDecodeError", ValueError)
83
88
  # This should be collected from server schema
@@ -363,7 +368,7 @@ class ServerAPI(object):
363
368
  self,
364
369
  base_url,
365
370
  token=None,
366
- site_id=None,
371
+ site_id=_PLACEHOLDER,
367
372
  client_version=None,
368
373
  default_settings_variant=None,
369
374
  sender=None,
@@ -382,11 +387,14 @@ class ServerAPI(object):
382
387
  self._graphql_url = "{}/graphql".format(base_url)
383
388
  self._log = None
384
389
  self._access_token = token
390
+ # Allow to have 'site_id' to 'None'
391
+ if site_id is _PLACEHOLDER:
392
+ site_id = get_default_site_id()
385
393
  self._site_id = site_id
386
394
  self._client_version = client_version
387
395
  self._default_settings_variant = (
388
396
  default_settings_variant
389
- or "production"
397
+ or get_default_settings_variant()
390
398
  )
391
399
  self._sender = sender
392
400
 
@@ -416,6 +424,8 @@ class ServerAPI(object):
416
424
  self._server_version = None
417
425
  self._server_version_tuple = None
418
426
 
427
+ self._graphql_allows_data_in_query = None
428
+
419
429
  self._session = None
420
430
 
421
431
  self._base_functions_mapping = {
@@ -941,6 +951,26 @@ class ServerAPI(object):
941
951
  server_version = property(get_server_version)
942
952
  server_version_tuple = property(get_server_version_tuple)
943
953
 
954
+ @property
955
+ def graphql_allows_data_in_query(self):
956
+ """GraphlQl query can support 'data' field.
957
+
958
+ This applies only to project hierarchy entities 'project', 'folder',
959
+ 'task', 'product', 'version' and 'representation'. Others like 'user'
960
+ still require to use rest api to access 'data'.
961
+
962
+ Returns:
963
+ bool: True if server supports 'data' field in GraphQl query.
964
+ """
965
+
966
+ if self._graphql_allows_data_in_query is None:
967
+ major, minor, patch, _, _ = self.server_version_tuple
968
+ graphql_allows_data_in_query = True
969
+ if (major, minor, patch) < (0, 5, 5):
970
+ graphql_allows_data_in_query = False
971
+ self._graphql_allows_data_in_query = graphql_allows_data_in_query
972
+ return self._graphql_allows_data_in_query
973
+
944
974
  def _get_user_info(self):
945
975
  if self._access_token is None:
946
976
  return None
@@ -1883,31 +1913,45 @@ class ServerAPI(object):
1883
1913
  return set(DEFAULT_EVENT_FIELDS)
1884
1914
 
1885
1915
  if entity_type == "project":
1886
- entity_type_defaults = DEFAULT_PROJECT_FIELDS
1916
+ entity_type_defaults = set(DEFAULT_PROJECT_FIELDS)
1917
+ if not self.graphql_allows_data_in_query:
1918
+ entity_type_defaults.discard("data")
1887
1919
 
1888
1920
  elif entity_type == "folder":
1889
- entity_type_defaults = DEFAULT_FOLDER_FIELDS
1921
+ entity_type_defaults = set(DEFAULT_FOLDER_FIELDS)
1922
+ if not self.graphql_allows_data_in_query:
1923
+ entity_type_defaults.discard("data")
1890
1924
 
1891
1925
  elif entity_type == "task":
1892
- entity_type_defaults = DEFAULT_TASK_FIELDS
1926
+ entity_type_defaults = set(DEFAULT_TASK_FIELDS)
1927
+ if not self.graphql_allows_data_in_query:
1928
+ entity_type_defaults.discard("data")
1893
1929
 
1894
1930
  elif entity_type == "product":
1895
- entity_type_defaults = DEFAULT_PRODUCT_FIELDS
1931
+ entity_type_defaults = set(DEFAULT_PRODUCT_FIELDS)
1932
+ if not self.graphql_allows_data_in_query:
1933
+ entity_type_defaults.discard("data")
1896
1934
 
1897
1935
  elif entity_type == "version":
1898
- entity_type_defaults = DEFAULT_VERSION_FIELDS
1936
+ entity_type_defaults = set(DEFAULT_VERSION_FIELDS)
1937
+ if not self.graphql_allows_data_in_query:
1938
+ entity_type_defaults.discard("data")
1899
1939
 
1900
1940
  elif entity_type == "representation":
1901
1941
  entity_type_defaults = (
1902
1942
  DEFAULT_REPRESENTATION_FIELDS
1903
1943
  | REPRESENTATION_FILES_FIELDS
1904
1944
  )
1945
+ if not self.graphql_allows_data_in_query:
1946
+ entity_type_defaults.discard("data")
1905
1947
 
1906
1948
  elif entity_type == "productType":
1907
- entity_type_defaults = DEFAULT_PRODUCT_TYPE_FIELDS
1949
+ entity_type_defaults = set(DEFAULT_PRODUCT_TYPE_FIELDS)
1908
1950
 
1909
1951
  elif entity_type == "workfile":
1910
- entity_type_defaults = DEFAULT_WORKFILE_INFO_FIELDS
1952
+ entity_type_defaults = set(DEFAULT_WORKFILE_INFO_FIELDS)
1953
+ if not self.graphql_allows_data_in_query:
1954
+ entity_type_defaults.discard("data")
1911
1955
 
1912
1956
  elif entity_type == "user":
1913
1957
  entity_type_defaults = set(DEFAULT_USER_FIELDS)
@@ -3659,7 +3703,7 @@ class ServerAPI(object):
3659
3703
  fields |= self.get_attributes_fields_for_type("folder")
3660
3704
 
3661
3705
  use_rest = False
3662
- if "data" in fields:
3706
+ if "data" in fields and not self.graphql_allows_data_in_query:
3663
3707
  use_rest = True
3664
3708
  fields = {"id"}
3665
3709
 
@@ -3680,6 +3724,8 @@ class ServerAPI(object):
3680
3724
 
3681
3725
  if use_rest:
3682
3726
  folder = self.get_rest_folder(project_name, folder["id"])
3727
+ else:
3728
+ self._convert_entity_data(folder)
3683
3729
 
3684
3730
  if own_attributes:
3685
3731
  fill_own_attribs(folder)
@@ -3897,7 +3943,7 @@ class ServerAPI(object):
3897
3943
  fields |= self.get_attributes_fields_for_type("task")
3898
3944
 
3899
3945
  use_rest = False
3900
- if "data" in fields:
3946
+ if "data" in fields and not self.graphql_allows_data_in_query:
3901
3947
  use_rest = True
3902
3948
  fields = {"id"}
3903
3949
 
@@ -3918,6 +3964,8 @@ class ServerAPI(object):
3918
3964
 
3919
3965
  if use_rest:
3920
3966
  task = self.get_rest_task(project_name, task["id"])
3967
+ else:
3968
+ self._convert_entity_data(task)
3921
3969
 
3922
3970
  if own_attributes:
3923
3971
  fill_own_attribs(task)
@@ -3998,6 +4046,8 @@ class ServerAPI(object):
3998
4046
 
3999
4047
  if use_rest:
4000
4048
  product = self.get_rest_product(project_name, product["id"])
4049
+ else:
4050
+ self._convert_entity_data(product)
4001
4051
 
4002
4052
  if own_attributes:
4003
4053
  fill_own_attribs(product)
@@ -4104,7 +4154,7 @@ class ServerAPI(object):
4104
4154
  fields = self.get_default_fields_for_type("product")
4105
4155
 
4106
4156
  use_rest = False
4107
- if "data" in fields:
4157
+ if "data" in fields and not self.graphql_allows_data_in_query:
4108
4158
  use_rest = True
4109
4159
  fields = {"id"}
4110
4160
 
@@ -4372,7 +4422,7 @@ class ServerAPI(object):
4372
4422
  fields |= {"id", "version"}
4373
4423
 
4374
4424
  use_rest = False
4375
- if "data" in fields:
4425
+ if "data" in fields and not self.graphql_allows_data_in_query:
4376
4426
  use_rest = True
4377
4427
  fields = {"id"}
4378
4428
 
@@ -4452,6 +4502,8 @@ class ServerAPI(object):
4452
4502
  version = self.get_rest_version(
4453
4503
  project_name, version["id"]
4454
4504
  )
4505
+ else:
4506
+ self._convert_entity_data(version)
4455
4507
 
4456
4508
  if own_attributes:
4457
4509
  fill_own_attribs(version)
@@ -4831,7 +4883,7 @@ class ServerAPI(object):
4831
4883
  fields |= self.get_attributes_fields_for_type("representation")
4832
4884
 
4833
4885
  use_rest = False
4834
- if "data" in fields:
4886
+ if "data" in fields and not self.graphql_allows_data_in_query:
4835
4887
  use_rest = True
4836
4888
  fields = {"id"}
4837
4889
 
@@ -4894,6 +4946,8 @@ class ServerAPI(object):
4894
4946
  repre = self.get_rest_representation(
4895
4947
  project_name, repre["id"]
4896
4948
  )
4949
+ else:
4950
+ self._convert_entity_data(repre)
4897
4951
 
4898
4952
  if "context" in repre:
4899
4953
  orig_context = repre["context"]
@@ -5013,6 +5067,10 @@ class ServerAPI(object):
5013
5067
  version = repre.pop("version")
5014
5068
  product = version.pop("product")
5015
5069
  folder = product.pop("folder")
5070
+ self._convert_entity_data(repre)
5071
+ self._convert_entity_data(version)
5072
+ self._convert_entity_data(product)
5073
+ self._convert_entity_data(folder)
5016
5074
  output[repre_id] = RepresentationParents(
5017
5075
  version, product, folder, project
5018
5076
  )
@@ -6323,3 +6381,13 @@ class ServerAPI(object):
6323
6381
  op_result["detail"],
6324
6382
  ))
6325
6383
  return op_results
6384
+
6385
+ def _convert_entity_data(self, entity):
6386
+ if not entity:
6387
+ return
6388
+ entity_data = entity.get("data")
6389
+ if (
6390
+ entity_data is not None
6391
+ and isinstance(entity_data, six.string_types)
6392
+ ):
6393
+ entity["data"] = json.loads(entity_data)
@@ -16,7 +16,11 @@ except ImportError:
16
16
  import requests
17
17
  import unidecode
18
18
 
19
- from .constants import SERVER_TIMEOUT_ENV_KEY
19
+ from .constants import (
20
+ SERVER_TIMEOUT_ENV_KEY,
21
+ DEFAULT_VARIANT_ENV_KEY,
22
+ SITE_ID_ENV_KEY,
23
+ )
20
24
  from .exceptions import UrlError
21
25
 
22
26
  REMOVED_VALUE = object()
@@ -46,6 +50,26 @@ def get_default_timeout():
46
50
  return 10.0
47
51
 
48
52
 
53
+ def get_default_settings_variant():
54
+ """Default settings variant.
55
+
56
+ Returns:
57
+ str: Settings variant from environment variable or 'production'.
58
+ """
59
+
60
+ return os.environ.get(DEFAULT_VARIANT_ENV_KEY) or "production"
61
+
62
+
63
+ def get_default_site_id():
64
+ """Site id used for server connection.
65
+
66
+ Returns:
67
+ Union[str, None]: Site id from environment variable or None.
68
+ """
69
+
70
+ return os.environ.get(SITE_ID_ENV_KEY)
71
+
72
+
49
73
  class ThumbnailContent:
50
74
  """Wrapper for thumbnail content.
51
75
 
@@ -1,2 +1,2 @@
1
1
  """Package declaring Python API for Ayon server."""
2
- __version__ = "0.5.2"
2
+ __version__ = "0.5.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 0.5.2
3
+ Version: 0.5.3
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 = "0.5.2"
3
+ version = "0.5.3"
4
4
  description = "AYON Python API"
5
5
  license = {file = "LICENSE"}
6
6
  readme = {file = "README.md", content-type = "text/markdown"}
File without changes