Ayon-Python-Api 0.1.3__tar.gz → 0.1.6__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 (25) hide show
  1. {ayon-python-api-0.1.3/ayon_python_api.egg-info → ayon-python-api-0.1.6}/PKG-INFO +1 -1
  2. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/__init__.py +70 -3
  3. ayon-python-api-0.1.6/ayon_api/exceptions.py +93 -0
  4. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/graphql.py +2 -33
  5. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/server.py +242 -56
  6. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/server_api.py +120 -10
  7. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/utils.py +2 -16
  8. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/version.py +1 -1
  9. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6/ayon_python_api.egg-info}/PKG-INFO +1 -1
  10. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/pyproject.toml +1 -1
  11. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/setup.py +1 -1
  12. ayon-python-api-0.1.3/ayon_api/exceptions.py +0 -2
  13. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/LICENSE +0 -0
  14. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/README.md +0 -0
  15. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/constants.py +0 -0
  16. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/entity_hub.py +0 -0
  17. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/events.py +0 -0
  18. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/graphql_queries.py +0 -0
  19. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/operations.py +0 -0
  20. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_api/thumbnails.py +0 -0
  21. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_python_api.egg-info/SOURCES.txt +0 -0
  22. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_python_api.egg-info/dependency_links.txt +0 -0
  23. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_python_api.egg-info/requires.txt +0 -0
  24. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/ayon_python_api.egg-info/top_level.txt +0 -0
  25. {ayon-python-api-0.1.3 → ayon-python-api-0.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 0.1.3
3
+ Version: 0.1.6
4
4
  Summary: AYON Python API
5
5
  Home-page: https://github.com/ynput/ayon-python-api
6
6
  Author: ynput.io
@@ -7,12 +7,47 @@ from .server_api import (
7
7
 
8
8
  get_server_api_connection,
9
9
 
10
+ raw_get,
11
+ raw_post,
12
+ raw_put,
13
+ raw_patch,
14
+ raw_delete,
15
+
10
16
  get,
11
17
  post,
12
18
  put,
13
19
  patch,
14
20
  delete,
15
21
 
22
+ download_file,
23
+ upload_file,
24
+
25
+ query_graphql,
26
+
27
+ get_addons_info,
28
+
29
+ get_dependencies_info,
30
+ update_dependency_info,
31
+
32
+ download_dependency_package,
33
+ upload_dependency_package,
34
+ delete_dependency_package,
35
+
36
+ get_full_production_settings,
37
+ get_production_settings,
38
+ get_full_project_settings,
39
+ get_project_settings,
40
+ get_addon_settings,
41
+
42
+ get_user,
43
+ get_users,
44
+
45
+ get_attributes_for_type,
46
+ get_default_fields_for_type,
47
+
48
+ get_project_anatomy_preset,
49
+ get_project_anatomy_presets,
50
+
16
51
  get_projects,
17
52
  get_project,
18
53
  create_project,
@@ -47,9 +82,6 @@ from .server_api import (
47
82
  get_representations_parents,
48
83
  get_representation_parents,
49
84
 
50
- get_project_settings,
51
- get_addon_settings,
52
-
53
85
  create_thumbnail,
54
86
  get_thumbnail,
55
87
  get_folder_thumbnail,
@@ -62,16 +94,50 @@ __all__ = (
62
94
  "ServerAPIBase",
63
95
 
64
96
  "ServerAPI",
97
+
65
98
  "get_server_api_connection",
99
+
100
+ "raw_get",
101
+ "raw_post",
102
+ "raw_put",
103
+ "raw_patch",
104
+ "raw_delete",
105
+
66
106
  "get",
67
107
  "post",
68
108
  "put",
69
109
  "patch",
70
110
  "delete",
71
111
 
112
+ "download_file",
113
+ "upload_file",
114
+
115
+ "query_graphql",
116
+
117
+ "get_addons_info",
118
+
119
+ "get_dependencies_info",
120
+ "update_dependency_info",
121
+
122
+ "download_dependency_package",
123
+ "upload_dependency_package",
124
+ "delete_dependency_package",
125
+
126
+ "get_full_production_settings",
127
+ "get_production_settings",
128
+ "get_full_project_settings",
72
129
  "get_project_settings",
73
130
  "get_addon_settings",
74
131
 
132
+ "get_user",
133
+ "get_users",
134
+
135
+ "get_attributes_for_type",
136
+ "get_default_fields_for_type",
137
+
138
+ "get_project_anatomy_preset",
139
+ "get_project_anatomy_presets",
140
+
75
141
  "get_projects",
76
142
  "get_project",
77
143
  "create_project",
@@ -89,6 +155,7 @@ __all__ = (
89
155
  "get_subset_by_name",
90
156
  "get_subsets",
91
157
  "get_subset_families",
158
+
92
159
  "get_version_by_id",
93
160
  "get_version_by_name",
94
161
  "version_is_latest",
@@ -0,0 +1,93 @@
1
+ import copy
2
+
3
+
4
+ class UrlError(Exception):
5
+ """Url cannot be parsed as url.
6
+
7
+ Exception may contain hints of possible fixes of url that can be used in
8
+ UI if needed.
9
+ """
10
+
11
+ def __init__(self, message, title, hints=None):
12
+ if hints is None:
13
+ hints = []
14
+
15
+ self.title = title
16
+ self.hints = hints
17
+ super(UrlError, self).__init__(message)
18
+
19
+
20
+ class ServerError(Exception):
21
+ pass
22
+
23
+
24
+ class UnauthorizedError(ServerError):
25
+ pass
26
+
27
+
28
+ class AuthenticationError(ServerError):
29
+ pass
30
+
31
+
32
+ class ServerNotReached(ServerError):
33
+ pass
34
+
35
+
36
+ class GraphQlQueryFailed(Exception):
37
+ def __init__(self, errors, query, variables):
38
+ if variables is None:
39
+ variables = {}
40
+
41
+ error_messages = []
42
+ for error in errors:
43
+ msg = error["message"]
44
+ path = error.get("path")
45
+ if path:
46
+ msg += " on item '{}'".format("/".join(path))
47
+ locations = error.get("locations")
48
+ if locations:
49
+ _locations = [
50
+ "Line {} Column {}".format(
51
+ location["line"], location["column"]
52
+ )
53
+ for location in locations
54
+ ]
55
+
56
+ msg += " ({})".format(" and ".join(_locations))
57
+ error_messages.append(msg)
58
+
59
+ message = "GraphQl query Failed"
60
+ if error_messages:
61
+ message = "{}: {}".format(message, " | ".join(error_messages))
62
+
63
+ self.errors = errors
64
+ self.query = query
65
+ self.variables = copy.deepcopy(variables)
66
+ super(GraphQlQueryFailed, self).__init__(message)
67
+
68
+
69
+ class MissingEntityError(Exception):
70
+ pass
71
+
72
+
73
+ class ProjectNotFound(MissingEntityError):
74
+ def __init__(self, project_name, message=None):
75
+ if not message:
76
+ message = "Project \"{}\" was not found".format(project_name)
77
+ self.project_name = project_name
78
+ super(ProjectNotFound, self).__init__(message)
79
+
80
+
81
+ class FolderNotFound(MissingEntityError):
82
+ def __init__(self, project_name, folder_id, message=None):
83
+ self.project_name = project_name
84
+ self.folder_id = folder_id
85
+ if not message:
86
+ message = (
87
+ "Folder with id \"{}\" was not found in project \"{}\""
88
+ ).format(folder_id, project_name)
89
+ super(FolderNotFound, self).__init__(message)
90
+
91
+
92
+ class FailedOperations(Exception):
93
+ pass
@@ -4,6 +4,8 @@ from abc import ABCMeta, abstractproperty, abstractmethod
4
4
 
5
5
  import six
6
6
 
7
+ from .exceptions import GraphQlQueryFailed
8
+
7
9
  FIELD_VALUE = object()
8
10
 
9
11
 
@@ -29,39 +31,6 @@ def fields_to_dict(fields):
29
31
  return output
30
32
 
31
33
 
32
- class GraphQlQueryFailed(Exception):
33
- def __init__(self, errors, query, variables):
34
- if variables is None:
35
- variables = {}
36
-
37
- error_messages = []
38
- for error in errors:
39
- msg = error["message"]
40
- path = error.get("path")
41
- if path:
42
- msg += " on item '{}'".format("/".join(path))
43
- locations = error.get("locations")
44
- if locations:
45
- _locations = [
46
- "Line {} Column {}".format(
47
- location["line"], location["column"]
48
- )
49
- for location in locations
50
- ]
51
-
52
- msg += " ({})".format(" and ".join(_locations))
53
- error_messages.append(msg)
54
-
55
- message = "GraphQl query Failed"
56
- if error_messages:
57
- message = "{}: {}".format(message, " | ".join(error_messages))
58
-
59
- self.errors = errors
60
- self.query = query
61
- self.variables = copy.deepcopy(variables)
62
- super(GraphQlQueryFailed, self).__init__(message)
63
-
64
-
65
34
  class QueryVariable(object):
66
35
  """Object representing single varible used in GraphQlQuery.
67
36
 
@@ -3,6 +3,7 @@ import re
3
3
  import json
4
4
  import logging
5
5
  import collections
6
+ import platform
6
7
  import copy
7
8
  from http import HTTPStatus
8
9
 
@@ -33,6 +34,10 @@ from .graphql_queries import (
33
34
  )
34
35
  from .exceptions import (
35
36
  FailedOperations,
37
+ UnauthorizedError,
38
+ AuthenticationError,
39
+ ServerNotReached,
40
+ ServerError,
36
41
  )
37
42
  from .utils import (
38
43
  logout_from_server,
@@ -49,22 +54,6 @@ PROJECT_NAME_REGEX = re.compile(
49
54
  )
50
55
 
51
56
 
52
- class ServerError(Exception):
53
- pass
54
-
55
-
56
- class UnauthorizedError(ServerError):
57
- pass
58
-
59
-
60
- class AuthenticationError(ServerError):
61
- pass
62
-
63
-
64
- class ServerNotReached(ServerError):
65
- pass
66
-
67
-
68
57
  class RequestType:
69
58
  def __init__(self, name):
70
59
  self.name = name
@@ -81,29 +70,6 @@ class RequestTypes:
81
70
  delete = RequestType("DELETE")
82
71
 
83
72
 
84
- class MissingEntityError(Exception):
85
- pass
86
-
87
-
88
- class ProjectNotFound(MissingEntityError):
89
- def __init__(self, project_name, message=None):
90
- if not message:
91
- message = "Project \"{}\" was not found".format(project_name)
92
- self.project_name = project_name
93
- super(ProjectNotFound, self).__init__(message)
94
-
95
-
96
- class FolderNotFound(MissingEntityError):
97
- def __init__(self, project_name, folder_id, message=None):
98
- self.project_name = project_name
99
- self.folder_id = folder_id
100
- if not message:
101
- message = (
102
- "Folder with id \"{}\" was not found in project \"{}\""
103
- ).format(folder_id, project_name)
104
- super(FolderNotFound, self).__init__(message)
105
-
106
-
107
73
  class RestApiResponse(object):
108
74
  """API Response."""
109
75
 
@@ -187,10 +153,21 @@ class ServerAPIBase(object):
187
153
  Login cause that a session is used
188
154
 
189
155
  Args:
190
- base_url(str): Example: http://localhost:5000
156
+ base_url (str): Example: http://localhost:5000
157
+ token (str): Access token (api key) to server.
158
+ site_id (str): Unique name of site. Should be the same when
159
+ connection is created from the same machine under same user.
160
+ client_version (str): Version of client application (used in
161
+ desktop client application).
191
162
  """
192
163
 
193
- def __init__(self, base_url, token=None):
164
+ def __init__(
165
+ self,
166
+ base_url,
167
+ token=None,
168
+ site_id=None,
169
+ client_version=None
170
+ ):
194
171
  if not base_url:
195
172
  raise ValueError("Invalid server URL {}".format(str(base_url)))
196
173
 
@@ -200,6 +177,8 @@ class ServerAPIBase(object):
200
177
  self._graphl_url = "{}/graphql".format(base_url)
201
178
  self._log = None
202
179
  self._access_token = token
180
+ self._site_id = site_id
181
+ self._client_version = client_version
203
182
  self._access_token_is_service = None
204
183
  self._token_is_valid = None
205
184
  self._server_available = None
@@ -225,6 +204,20 @@ class ServerAPIBase(object):
225
204
  def access_token(self):
226
205
  return self._access_token
227
206
 
207
+ def get_site_id(self):
208
+ return self._site_id
209
+
210
+ def set_site_id(self, site_id):
211
+ if self._site_id == site_id:
212
+ return
213
+ self._site_id = site_id
214
+ # Recreate session on machine id change
215
+ if self._session is not None:
216
+ self.close_session()
217
+ self.create_session()
218
+
219
+ site_id = property(get_site_id, set_site_id)
220
+
228
221
  @property
229
222
  def is_server_available(self):
230
223
  if self._server_available is None:
@@ -249,7 +242,11 @@ class ServerAPIBase(object):
249
242
 
250
243
  def validate_token(self):
251
244
  try:
252
- self.get_user_info()
245
+ # TODO add other possible validations
246
+ # - existence of 'user' key in info
247
+ # - validate that 'site_id' is in 'sites' in info
248
+ self.get_info()
249
+ self.get_user()
253
250
  self._token_is_valid = True
254
251
 
255
252
  except UnauthorizedError:
@@ -259,7 +256,7 @@ class ServerAPIBase(object):
259
256
  def set_token(self, token):
260
257
  self.reset_token()
261
258
  self._access_token = token
262
- self.get_user_info()
259
+ self.get_user()
263
260
 
264
261
  def reset_token(self):
265
262
  self._access_token = None
@@ -294,6 +291,23 @@ class ServerAPIBase(object):
294
291
  self._session_functions_mapping = {}
295
292
  session.close()
296
293
 
294
+ def get_info(self):
295
+ """Get information about current used api key.
296
+
297
+ By default, the 'info' contains only 'uptime' and 'version'. With
298
+ logged user info also contains information about user and machines on
299
+ which was logged in.
300
+
301
+ Todos:
302
+ Use this method for validation of token instead of 'get_user'.
303
+
304
+ Returns:
305
+ Dict[str, Any]: Information from server.
306
+ """
307
+
308
+ response = self.get("info")
309
+ return response.data
310
+
297
311
  def _get_user_info(self):
298
312
  if self._access_token is None:
299
313
  return None
@@ -315,11 +329,23 @@ class ServerAPIBase(object):
315
329
  self._access_token_is_service = None
316
330
  return None
317
331
 
318
- def get_user_info(self):
319
- user_info = self._get_user_info()
320
- if user_info is None:
332
+ def get_users(self):
333
+ # TODO how to find out if user have permission?
334
+ users = self.get("users")
335
+ return users.data
336
+
337
+ def get_user(self, username=None):
338
+ output = None
339
+ if username is None:
340
+ output = self._get_user_info()
341
+ else:
342
+ response = self.get("users/{}".format(username))
343
+ if response.status == 200:
344
+ output = response.data
345
+
346
+ if output is None:
321
347
  raise UnauthorizedError("User is not authorized.")
322
- return user_info
348
+ return output
323
349
 
324
350
  @property
325
351
  def log(self):
@@ -330,7 +356,18 @@ class ServerAPIBase(object):
330
356
  def get_headers(self, content_type=None):
331
357
  if content_type is None:
332
358
  content_type = "application/json"
333
- headers = {"Content-Type": content_type}
359
+
360
+ headers = {
361
+ "Content-Type": content_type,
362
+ "x-ayon-platform": platform.system().lower(),
363
+ "x-ayon-hostname": platform.node(),
364
+ }
365
+ if self._site_id is not None:
366
+ headers["x-ayon-site-id"] = self._site_id
367
+
368
+ if self._client_version is not None:
369
+ headers["x-ayon-version"] = self._client_version
370
+
334
371
  if self._access_token:
335
372
  if self._access_token_is_service:
336
373
  headers["X-Api-Key"] = self._access_token
@@ -342,7 +379,7 @@ class ServerAPIBase(object):
342
379
  def login(self, username, password):
343
380
  if self.has_valid_token:
344
381
  try:
345
- user_info = self.get_user_info()
382
+ user_info = self.get_user()
346
383
  except UnauthorizedError:
347
384
  user_info = {}
348
385
 
@@ -507,6 +544,23 @@ class ServerAPIBase(object):
507
544
  def delete(self, entrypoint, **kwargs):
508
545
  return self.raw_delete(entrypoint, params=kwargs)
509
546
 
547
+ def download_file(self, endpoint, filepath, chunk_size=None):
548
+ if not chunk_size:
549
+ # 1 MB chunk by default
550
+ chunk_size = 1024 * 1024
551
+ dst_directory = os.path.dirname(filepath)
552
+ if not os.path.exists(dst_directory):
553
+ os.makedirs(dst_directory)
554
+
555
+ with open(filepath, "wb") as f_stream:
556
+ with self.raw_get(endpoint, stream=True) as response:
557
+ for chunk in response.iter_content(chunk_size=chunk_size):
558
+ f_stream.write(chunk)
559
+
560
+ def upload_file(self, endpoint, filepath):
561
+ with open(filepath, "rb") as stream:
562
+ self.raw_post(endpoint, data=stream)
563
+
510
564
  def trigger_server_restart(self):
511
565
  result = self.post("system/restart")
512
566
  if result.status_code != 204:
@@ -709,6 +763,118 @@ class ServerAPIBase(object):
709
763
  }
710
764
  )
711
765
 
766
+ def get_addons_info(self, details=True):
767
+ """Get information about addons available on server.
768
+
769
+ Args:
770
+ details (bool): Detailed data with information how to get client
771
+ code.
772
+ """
773
+
774
+ endpoint = "addons"
775
+ if details:
776
+ endpoint += "?details=1"
777
+ response = self.get(endpoint)
778
+ if response.status != 200:
779
+ raise ServerError(response.text)
780
+ return response.data
781
+
782
+ def get_dependencies_info(self):
783
+ result = self.get("dependencies")
784
+ return result.data
785
+
786
+ def update_dependency_info(
787
+ self,
788
+ name,
789
+ platform_name,
790
+ size,
791
+ checksum,
792
+ checksum_algorithm=None,
793
+ supported_addons=None,
794
+ python_modules=None,
795
+ sources=None
796
+ ):
797
+ """Update or create dependency package infor by it's identifiers.
798
+
799
+ The endpoint can be used to create or update dependency package.
800
+
801
+ Args:
802
+ name (str): Name of dependency package.
803
+ platform_name (Literal["windows", "linux", "darwin"]): Platform for
804
+ which is dependency package targeted.
805
+ size (int): Size of dependency package in bytes.
806
+ checksum (str): Checksum of archive file where dependecies are.
807
+ checksum_algorithm (str): Algorithm used to calculate checksum.
808
+ By default, is used 'md5' (defined by server).
809
+ supported_addons (Dict[str, str]): Name of addons for which was the
810
+ package created ('{"<addon name>": "<addon version>", ...}').
811
+ python_modules (Dict[str, str]): Python modules in dependencies
812
+ package ('{"<module name>": "<module version>", ...}').
813
+ sources (List[Dict[str, Any]]): Information about sources where
814
+ dependency package is available.
815
+ """
816
+
817
+ kwargs = {
818
+ key: value
819
+ for key, value in (
820
+ ("checksumAlgorithm", checksum_algorithm),
821
+ ("supportedAddons", supported_addons),
822
+ ("pythonModules", python_modules),
823
+ ("sources", sources),
824
+ )
825
+ if value
826
+ }
827
+
828
+ response = self.put(
829
+ "dependencies",
830
+ name=name,
831
+ platform=platform_name,
832
+ size=size,
833
+ checksum=checksum,
834
+ **kwargs
835
+ )
836
+ if response.status not in (200, 201):
837
+ raise ServerError("Failed to create/update dependency")
838
+ return response.data
839
+
840
+ def download_dependency_package(
841
+ self,
842
+ dst_directory,
843
+ package_name,
844
+ platform_name=None
845
+ ):
846
+ if platform_name is None:
847
+ platform_name = platform.system().lower()
848
+
849
+ package_filepath = os.path.join(dst_directory, package_name + ".zip")
850
+ self.download_file(
851
+ "dependencies/{}/{}".format(package_name, platform_name),
852
+ package_filepath
853
+ )
854
+ return package_filepath
855
+
856
+ def upload_dependency_package(
857
+ self, filepath, package_name, platform_name=None
858
+ ):
859
+ if platform_name is None:
860
+ platform_name = platform.system().lower()
861
+
862
+ self.upload_file(
863
+ "dependencies/{}/{}".format(package_name, platform_name),
864
+ filepath
865
+ )
866
+
867
+ def delete_dependency_package(self, package_name, platform_name=None):
868
+ if platform_name is None:
869
+ platform_name = platform.system().lower()
870
+
871
+ response = self.delete(
872
+ "dependencies/{}/{}".format(package_name, platform_name),
873
+ )
874
+ if response.status != 200:
875
+ raise ServerError("Failed to delete dependency file")
876
+ return response.data
877
+
712
878
  # Anatomy presets
713
879
  def get_project_anatomy_presets(self, add_default=True):
714
880
  result = self.get("anatomy/presets")
@@ -749,13 +915,32 @@ class ServerAPIBase(object):
749
915
  return full_settings
750
916
  return full_settings["settings"]
751
917
 
752
- def get_addon_settings(self, addon_name, addon_version, project_name):
918
+ def get_addon_studio_settings(self, addon_name, addon_version):
919
+ result = self.get(
920
+ "addons/{}/{}/settings".format(addon_name, addon_version)
921
+ )
922
+ if result.status != 200:
923
+ raise ServerError(result.text)
924
+ return result.data
925
+
926
+ def get_addon_project_settings(
927
+ self, addon_name, addon_version, project_name
928
+ ):
753
929
  result = self.get(
754
930
  "addons/{}/{}/settings/{}".format(
755
- addon_name, addon_version, project_name))
756
- if result.status == 200:
757
- return result.data
758
- return None
931
+ addon_name, addon_version, project_name
932
+ )
933
+ )
934
+ if result.status != 200:
935
+ raise ServerError(result.text)
936
+ return result.data
937
+
938
+ def get_addon_settings(self, addon_name, addon_version, project_name=None):
939
+ if project_name is None:
940
+ return self.get_addon_studio_settings(addon_name, addon_version)
941
+ return self.get_addon_project_settings(
942
+ addon_name, addon_version, project_name
943
+ )
759
944
 
760
945
  # Entity getters
761
946
  def get_rest_project(self, project_name):
@@ -1900,6 +2085,7 @@ class ServerAPIBase(object):
1900
2085
  version_ids=[version_id],
1901
2086
  active=None,
1902
2087
  fields=fields,
2088
+ own_attributes=own_attributes
1903
2089
  )
1904
2090
  for representation in representations:
1905
2091
  return representation
@@ -1955,7 +2141,7 @@ class ServerAPIBase(object):
1955
2141
  fields=None,
1956
2142
  own_attributes=False
1957
2143
  ):
1958
- filters = {}
2144
+ filters = {"projectName": project_name}
1959
2145
  if task_ids is not None:
1960
2146
  task_ids = set(task_ids)
1961
2147
  if not task_ids:
@@ -1980,7 +2166,7 @@ class ServerAPIBase(object):
1980
2166
  if own_attributes:
1981
2167
  fields.add("ownAttrib")
1982
2168
 
1983
- query = workfiles_info_graphql_query()
2169
+ query = workfiles_info_graphql_query(fields)
1984
2170
 
1985
2171
  for attr, filter_value in filters.items():
1986
2172
  query.set_variable_value(attr, filter_value)
@@ -85,6 +85,31 @@ def get_server_api_connection():
85
85
  return GlobalContext.get_server_api_connection()
86
86
 
87
87
 
88
+ def raw_get(*args, **kwargs):
89
+ con = get_server_api_connection()
90
+ return con.raw_get(*args, **kwargs)
91
+
92
+
93
+ def raw_post(*args, **kwargs):
94
+ con = get_server_api_connection()
95
+ return con.raw_post(*args, **kwargs)
96
+
97
+
98
+ def raw_put(*args, **kwargs):
99
+ con = get_server_api_connection()
100
+ return con.raw_put(*args, **kwargs)
101
+
102
+
103
+ def raw_patch(*args, **kwargs):
104
+ con = get_server_api_connection()
105
+ return con.raw_patch(*args, **kwargs)
106
+
107
+
108
+ def raw_delete(*args, **kwargs):
109
+ con = get_server_api_connection()
110
+ return con.raw_delete(*args, **kwargs)
111
+
112
+
88
113
  def get(*args, **kwargs):
89
114
  con = get_server_api_connection()
90
115
  return con.get(*args, **kwargs)
@@ -110,6 +135,101 @@ def delete(*args, **kwargs):
110
135
  return con.delete(*args, **kwargs)
111
136
 
112
137
 
138
+ def download_file(*args, **kwargs):
139
+ con = get_server_api_connection()
140
+ return con.download_file(*args, **kwargs)
141
+
142
+
143
+ def upload_file(*args, **kwargs):
144
+ con = get_server_api_connection()
145
+ return con.upload_file(*args, **kwargs)
146
+
147
+
148
+ def query_graphql(*args, **kwargs):
149
+ con = get_server_api_connection()
150
+ return con.query_graphql(*args, **kwargs)
151
+
152
+
153
+ def get_users(*args, **kwargs):
154
+ con = get_server_api_connection()
155
+ return con.get_users(*args, **kwargs)
156
+
157
+
158
+ def get_user(*args, **kwargs):
159
+ con = get_server_api_connection()
160
+ return con.get_user(*args, **kwargs)
161
+
162
+
163
+ def get_attributes_for_type(*args, **kwargs):
164
+ con = get_server_api_connection()
165
+ return con.get_attributes_for_type(*args, **kwargs)
166
+
167
+
168
+ def get_addons_info(*args, **kwargs):
169
+ con = get_server_api_connection()
170
+ return con.get_addons_info(*args, **kwargs)
171
+
172
+
173
+ def get_dependencies_info(*args, **kwargs):
174
+ con = get_server_api_connection()
175
+ return con.get_dependencies_info(*args, **kwargs)
176
+
177
+
178
+ def update_dependency_info(*args, **kwargs):
179
+ con = get_server_api_connection()
180
+ return con.update_dependency_info(*args, **kwargs)
181
+
182
+
183
+ def download_dependency_package(*args, **kwargs):
184
+ con = get_server_api_connection()
185
+ return con.download_dependency_package(*args, **kwargs)
186
+
187
+
188
+ def upload_dependency_package(*args, **kwargs):
189
+ con = get_server_api_connection()
190
+ return con.upload_dependency_package(*args, **kwargs)
191
+
192
+
193
+ def delete_dependency_package(*args, **kwargs):
194
+ con = get_server_api_connection()
195
+ return con.delete_dependency_package(*args, **kwargs)
196
+
197
+
198
+ def get_project_anatomy_presets(*args, **kwargs):
199
+ con = get_server_api_connection()
200
+ return con.get_project_anatomy_presets(*args, **kwargs)
201
+
202
+
203
+ def get_project_anatomy_preset(*args, **kwargs):
204
+ con = get_server_api_connection()
205
+ return con.get_project_anatomy_preset(*args, **kwargs)
206
+
207
+
208
+ def get_full_production_settings(*args, **kwargs):
209
+ con = get_server_api_connection()
210
+ return con.get_full_production_settings(*args, **kwargs)
211
+
212
+
213
+ def get_production_settings(*args, **kwargs):
214
+ con = get_server_api_connection()
215
+ return con.get_production_settings(*args, **kwargs)
216
+
217
+
218
+ def get_full_project_settings(*args, **kwargs):
219
+ con = get_server_api_connection()
220
+ return con.get_full_project_settings(*args, **kwargs)
221
+
222
+
223
+ def get_project_settings(*args, **kwargs):
224
+ con = get_server_api_connection()
225
+ return con.get_project_settings(*args, **kwargs)
226
+
227
+
228
+ def get_addon_settings(*args, **kwargs):
229
+ con = get_server_api_connection()
230
+ return con.get_addon_settings(*args, **kwargs)
231
+
232
+
113
233
  def get_project(*args, **kwargs):
114
234
  con = get_server_api_connection()
115
235
  return con.get_project(*args, **kwargs)
@@ -245,16 +365,6 @@ def get_representations_parents(*args, **kwargs):
245
365
  return con.get_representations_parents(*args, **kwargs)
246
366
 
247
367
 
248
- def get_project_settings(*args, **kwargs):
249
- con = get_server_api_connection()
250
- return con.get_project_settings(*args, **kwargs)
251
-
252
-
253
- def get_addon_settings(*args, **kwargs):
254
- con = get_server_api_connection()
255
- return con.get_addon_settings(*args, **kwargs)
256
-
257
-
258
368
  def create_project(
259
369
  project_name,
260
370
  project_code,
@@ -7,6 +7,8 @@ except ImportError:
7
7
 
8
8
  import requests
9
9
 
10
+ from .exceptions import UrlError
11
+
10
12
  REMOVED_VALUE = object()
11
13
 
12
14
 
@@ -97,22 +99,6 @@ def prepare_entity_changes(old_entity, new_entity, replace=False):
97
99
  return changes
98
100
 
99
101
 
100
- class UrlError(Exception):
101
- """Url cannot be parsed as url.
102
-
103
- Exception may contain hints of possible fixes of url that can be used in
104
- UI if needed.
105
- """
106
-
107
- def __init__(self, message, title, hints=None):
108
- if hints is None:
109
- hints = []
110
-
111
- self.title = title
112
- self.hints = hints
113
- super(UrlError, self).__init__(message)
114
-
115
-
116
102
  def _try_parse_url(url):
117
103
  try:
118
104
  return urlparse(url)
@@ -1,2 +1,2 @@
1
1
  """Package declaring Python API for Ayon server."""
2
- __version__ = "0.1.3"
2
+ __version__ = "0.1.6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ayon-python-api
3
- Version: 0.1.3
3
+ Version: 0.1.6
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
  [tool.poetry]
2
2
  name = "ayon_api"
3
- version = "0.1.3"
3
+ version = "0.1.6"
4
4
  description = "Python api for AYON server"
5
5
  authors = ["ynput.io <info@ynput.io>"]
6
6
 
@@ -34,5 +34,5 @@ setup(
34
34
  dependency_links=[
35
35
  "appdirs @ git+https://github.com/ActiveState/appdirs.git@master"
36
36
  ],
37
- keywords=["AYON", "ynput", "OpenPype", "vfx"]
37
+ keywords=["AYON", "ynput", "OpenPype", "vfx"],
38
38
  )
@@ -1,2 +0,0 @@
1
- class FailedOperations(Exception):
2
- pass
File without changes