gazu 0.10.16__tar.gz → 0.10.18__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 (55) hide show
  1. {gazu-0.10.16 → gazu-0.10.18}/PKG-INFO +2 -1
  2. gazu-0.10.18/gazu/__version__.py +1 -0
  3. {gazu-0.10.16 → gazu-0.10.18}/gazu/asset.py +11 -7
  4. {gazu-0.10.16 → gazu-0.10.18}/gazu/client.py +37 -8
  5. {gazu-0.10.16 → gazu-0.10.18}/gazu/events.py +18 -0
  6. {gazu-0.10.16 → gazu-0.10.18}/gazu/scene.py +6 -2
  7. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/PKG-INFO +2 -1
  8. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/requires.txt +3 -0
  9. {gazu-0.10.16 → gazu-0.10.18}/setup.cfg +1 -0
  10. {gazu-0.10.16 → gazu-0.10.18}/tests/test_client.py +28 -10
  11. {gazu-0.10.16 → gazu-0.10.18}/tests/test_files.py +20 -0
  12. gazu-0.10.16/gazu/__version__.py +0 -1
  13. {gazu-0.10.16 → gazu-0.10.18}/LICENSE +0 -0
  14. {gazu-0.10.16 → gazu-0.10.18}/README.rst +0 -0
  15. {gazu-0.10.16 → gazu-0.10.18}/gazu/__init__.py +0 -0
  16. {gazu-0.10.16 → gazu-0.10.18}/gazu/cache.py +0 -0
  17. {gazu-0.10.16 → gazu-0.10.18}/gazu/casting.py +0 -0
  18. {gazu-0.10.16 → gazu-0.10.18}/gazu/concept.py +0 -0
  19. {gazu-0.10.16 → gazu-0.10.18}/gazu/context.py +0 -0
  20. {gazu-0.10.16 → gazu-0.10.18}/gazu/edit.py +0 -0
  21. {gazu-0.10.16 → gazu-0.10.18}/gazu/encoder.py +0 -0
  22. {gazu-0.10.16 → gazu-0.10.18}/gazu/entity.py +0 -0
  23. {gazu-0.10.16 → gazu-0.10.18}/gazu/exception.py +0 -0
  24. {gazu-0.10.16 → gazu-0.10.18}/gazu/files.py +0 -0
  25. {gazu-0.10.16 → gazu-0.10.18}/gazu/helpers.py +0 -0
  26. {gazu-0.10.16 → gazu-0.10.18}/gazu/person.py +0 -0
  27. {gazu-0.10.16 → gazu-0.10.18}/gazu/playlist.py +0 -0
  28. {gazu-0.10.16 → gazu-0.10.18}/gazu/project.py +0 -0
  29. {gazu-0.10.16 → gazu-0.10.18}/gazu/shot.py +0 -0
  30. {gazu-0.10.16 → gazu-0.10.18}/gazu/sorting.py +0 -0
  31. {gazu-0.10.16 → gazu-0.10.18}/gazu/sync.py +0 -0
  32. {gazu-0.10.16 → gazu-0.10.18}/gazu/task.py +0 -0
  33. {gazu-0.10.16 → gazu-0.10.18}/gazu/user.py +0 -0
  34. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/SOURCES.txt +0 -0
  35. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/dependency_links.txt +0 -0
  36. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/not-zip-safe +0 -0
  37. {gazu-0.10.16 → gazu-0.10.18}/gazu.egg-info/top_level.txt +0 -0
  38. {gazu-0.10.16 → gazu-0.10.18}/pyproject.toml +0 -0
  39. {gazu-0.10.16 → gazu-0.10.18}/setup.py +0 -0
  40. {gazu-0.10.16 → gazu-0.10.18}/tests/test_asset.py +0 -0
  41. {gazu-0.10.16 → gazu-0.10.18}/tests/test_cache.py +0 -0
  42. {gazu-0.10.16 → gazu-0.10.18}/tests/test_casting.py +0 -0
  43. {gazu-0.10.16 → gazu-0.10.18}/tests/test_concept.py +0 -0
  44. {gazu-0.10.16 → gazu-0.10.18}/tests/test_context.py +0 -0
  45. {gazu-0.10.16 → gazu-0.10.18}/tests/test_edit.py +0 -0
  46. {gazu-0.10.16 → gazu-0.10.18}/tests/test_entity.py +0 -0
  47. {gazu-0.10.16 → gazu-0.10.18}/tests/test_helpers.py +0 -0
  48. {gazu-0.10.16 → gazu-0.10.18}/tests/test_person.py +0 -0
  49. {gazu-0.10.16 → gazu-0.10.18}/tests/test_playlist.py +0 -0
  50. {gazu-0.10.16 → gazu-0.10.18}/tests/test_project.py +0 -0
  51. {gazu-0.10.16 → gazu-0.10.18}/tests/test_scene.py +0 -0
  52. {gazu-0.10.16 → gazu-0.10.18}/tests/test_shot.py +0 -0
  53. {gazu-0.10.16 → gazu-0.10.18}/tests/test_sync.py +0 -0
  54. {gazu-0.10.16 → gazu-0.10.18}/tests/test_task.py +0 -0
  55. {gazu-0.10.16 → gazu-0.10.18}/tests/test_user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gazu
3
- Version: 0.10.16
3
+ Version: 0.10.18
4
4
  Summary: Gazu is a client for Zou, the API to store the data of your CG production.
5
5
  Home-page: https://gazu.cg-wire.com/
6
6
  Author: CG Wire
@@ -28,6 +28,7 @@ License-File: LICENSE
28
28
  Requires-Dist: python-socketio[client]<6,>=5.11.0; python_version != "2.7"
29
29
  Requires-Dist: requests>=2.25.1
30
30
  Requires-Dist: Deprecated==1.2.14
31
+ Requires-Dist: pywin32>=308; sys_platform == "win32" and python_version != "2.7"
31
32
  Provides-Extra: dev
32
33
  Requires-Dist: wheel; extra == "dev"
33
34
  Provides-Extra: test
@@ -0,0 +1 @@
1
+ __version__ = "0.10.18"
@@ -166,7 +166,7 @@ def new_asset(
166
166
  project,
167
167
  asset_type,
168
168
  name,
169
- description="",
169
+ description=None,
170
170
  extra_data={},
171
171
  episode=None,
172
172
  client=default,
@@ -189,7 +189,10 @@ def new_asset(
189
189
  asset_type = normalize_model_parameter(asset_type)
190
190
  episode = normalize_model_parameter(episode)
191
191
 
192
- data = {"name": name, "description": description, "data": extra_data}
192
+ data = {"name": name, "data": extra_data}
193
+
194
+ if description is not None:
195
+ data["description"] = description
193
196
 
194
197
  if episode is not None:
195
198
  data["episode_id"] = episode["id"]
@@ -449,7 +452,7 @@ def all_asset_instances_for_asset(asset, client=default):
449
452
 
450
453
 
451
454
  def new_asset_asset_instance(
452
- asset, asset_to_instantiate, description="", client=default
455
+ asset, asset_to_instantiate, description=None, client=default
453
456
  ):
454
457
  """
455
458
  Creates a new asset instance for given asset. The instance number is
@@ -465,10 +468,11 @@ def new_asset_asset_instance(
465
468
  """
466
469
  asset = normalize_model_parameter(asset)
467
470
  asset_to_instantiate = normalize_model_parameter(asset_to_instantiate)
468
- data = {
469
- "asset_to_instantiate_id": asset_to_instantiate["id"],
470
- "description": description,
471
- }
471
+ data = {"asset_to_instantiate_id": asset_to_instantiate["id"]}
472
+
473
+ if description is not None:
474
+ data["description"] = description
475
+
472
476
  return raw.post(
473
477
  "data/assets/%s/asset-asset-instances" % asset["id"],
474
478
  data,
@@ -303,6 +303,32 @@ def delete(path, params=None, client=default_client):
303
303
  return response.text
304
304
 
305
305
 
306
+ def get_message_from_response(
307
+ response, default_message="No additional information"
308
+ ):
309
+ """
310
+ A utility function that handles Zou's inconsistent message keys.
311
+ For a given request, checks if any error messages or regular messages were given and returns their value.
312
+ If no messages are found, returns a default message.
313
+
314
+ Args:
315
+ response: requests.Request - A response to check.
316
+ default_message: str - An optional default value to revert to if no message is detected.
317
+
318
+ Returns:
319
+ The message of a given response, or a default message - if any.
320
+ """
321
+ message = default_message
322
+ message_json = response.json()
323
+
324
+ for key in ["error", "message"]:
325
+ if message_json.get(key):
326
+ message = message_json[key]
327
+ break
328
+
329
+ return message
330
+
331
+
306
332
  def check_status(request, path, client=None):
307
333
  """
308
334
  Raise an exception related to status code, if the status code does not
@@ -329,8 +355,7 @@ def check_status(request, path, client=None):
329
355
  elif status_code == 403:
330
356
  raise NotAllowedException(path)
331
357
  elif status_code == 400:
332
- text = request.json().get("message", "No additional information")
333
- raise ParameterException(path, text)
358
+ raise ParameterException(path, get_message_from_response(request))
334
359
  elif status_code == 405:
335
360
  raise MethodNotAllowedException(path)
336
361
  elif status_code == 413:
@@ -359,14 +384,15 @@ def check_status(request, path, client=None):
359
384
  raise
360
385
  elif status_code in [500, 502]:
361
386
  try:
387
+ print("A server error occured!\n")
362
388
  stacktrace = request.json().get(
363
389
  "stacktrace", "No stacktrace sent by the server"
364
390
  )
365
- message = request.json().get(
366
- "message", "No message sent by the server"
367
- )
368
- print("A server error occured!\n")
369
391
  print("Server stacktrace:\n%s" % stacktrace)
392
+ message = get_message_from_response(
393
+ response=request,
394
+ default_message="No message sent by the server",
395
+ )
370
396
  print("Error message:\n%s\n" % message)
371
397
  except Exception:
372
398
  print(request.text)
@@ -474,8 +500,11 @@ def upload(path, file_path, data={}, extra_files=[], client=default_client):
474
500
  except JSONDecodeError:
475
501
  print(response.text)
476
502
  raise
477
- if "message" in result:
478
- raise UploadFailedException(result["message"])
503
+
504
+ result_message = get_message_from_response(response, default_message="")
505
+ if result_message:
506
+ raise UploadFailedException(result_message)
507
+
479
508
  return result
480
509
 
481
510
 
@@ -7,7 +7,25 @@ if sys.version_info[0] == 2:
7
7
  from .exception import AuthFailedException
8
8
  from .client import default_client, get_event_host
9
9
  from gazu.client import make_auth_header
10
+ from engineio.base_client import signal_handler
10
11
  import socketio
12
+ import os
13
+ import inspect
14
+ import signal
15
+ import socketio
16
+
17
+ if os.name == "nt":
18
+ from win32api import SetConsoleCtrlHandler
19
+
20
+ def WindowsSignalHandler(event):
21
+ if event == 0:
22
+ try:
23
+ signal_handler(signal.SIGINT, inspect.currentframe())
24
+ except:
25
+ # SetConsoleCtrlHandler handle cannot raise exceptions
26
+ pass
27
+
28
+ SetConsoleCtrlHandler(WindowsSignalHandler, 1)
11
29
 
12
30
 
13
31
  class EventsNamespace(socketio.ClientNamespace):
@@ -85,14 +85,18 @@ def update_scene(scene, client=default):
85
85
  return raw.put("data/entities/%s" % scene["id"], scene, client=client)
86
86
 
87
87
 
88
- def new_scene_asset_instance(scene, asset, description="", client=default):
88
+ def new_scene_asset_instance(scene, asset, description=None, client=default):
89
89
  """
90
90
  Creates a new asset instance on given scene. The instance number is
91
91
  automatically generated (increment highest number).
92
92
  """
93
93
  scene = normalize_model_parameter(scene)
94
94
  asset = normalize_model_parameter(asset)
95
- data = {"asset_id": asset["id"], "description": description}
95
+ data = {"asset_id": asset["id"]}
96
+
97
+ if description is not None:
98
+ data["description"] = description
99
+
96
100
  return raw.post(
97
101
  "data/scenes/%s/asset-instances" % scene["id"], data, client=client
98
102
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gazu
3
- Version: 0.10.16
3
+ Version: 0.10.18
4
4
  Summary: Gazu is a client for Zou, the API to store the data of your CG production.
5
5
  Home-page: https://gazu.cg-wire.com/
6
6
  Author: CG Wire
@@ -28,6 +28,7 @@ License-File: LICENSE
28
28
  Requires-Dist: python-socketio[client]<6,>=5.11.0; python_version != "2.7"
29
29
  Requires-Dist: requests>=2.25.1
30
30
  Requires-Dist: Deprecated==1.2.14
31
+ Requires-Dist: pywin32>=308; sys_platform == "win32" and python_version != "2.7"
31
32
  Provides-Extra: dev
32
33
  Requires-Dist: wheel; extra == "dev"
33
34
  Provides-Extra: test
@@ -4,6 +4,9 @@ Deprecated==1.2.14
4
4
  [:python_version != "2.7"]
5
5
  python-socketio[client]<6,>=5.11.0
6
6
 
7
+ [:sys_platform == "win32" and python_version != "2.7"]
8
+ pywin32>=308
9
+
7
10
  [dev]
8
11
  wheel
9
12
 
@@ -33,6 +33,7 @@ install_requires =
33
33
  python-socketio[client]>=5.11.0,<6; python_version != '2.7'
34
34
  requests>=2.25.1
35
35
  Deprecated==1.2.14
36
+ pywin32>=308; sys_platform == 'win32' and python_version != '2.7'
36
37
 
37
38
  [options.packages.find]
38
39
  include = gazu*
@@ -1,5 +1,7 @@
1
1
  import datetime
2
2
  import json
3
+ import random
4
+ import string
3
5
 
4
6
  import unittest
5
7
  import requests_mock
@@ -281,20 +283,36 @@ class BaseFuncTestCase(ClientTestCase):
281
283
  "./tests/fixtures/v1.png",
282
284
  data={"test": True},
283
285
  )
286
+
287
+ error_value = "".join(
288
+ [
289
+ random.choice(
290
+ string.ascii_uppercase + string.ascii_lowercase
291
+ )
292
+ for _ in range(10)
293
+ ]
294
+ )
295
+
284
296
  with requests_mock.Mocker() as mock:
285
- mock_route(
286
- mock,
287
- "POST",
288
- "data/new-file",
289
- text={"message": "Error"},
290
- )
291
- with self.assertRaises(gazu.client.UploadFailedException):
292
- raw.upload(
297
+ for field in ["message", "error"]:
298
+ mock_route(
299
+ mock,
300
+ "POST",
293
301
  "data/new-file",
294
- "./tests/fixtures/v1.png",
295
- data={"test": True},
302
+ text={field: error_value},
296
303
  )
297
304
 
305
+ with self.assertRaises(
306
+ gazu.client.UploadFailedException
307
+ ) as context:
308
+ raw.upload(
309
+ "data/new-file",
310
+ "./tests/fixtures/v1.png",
311
+ data={"test": True},
312
+ )
313
+
314
+ self.assertTrue(str(context.exception) == error_value)
315
+
298
316
  def test_upload_multiple_files(self):
299
317
  with open("./tests/fixtures/v1.png", "rb") as test_file:
300
318
  with requests_mock.Mocker() as mock:
@@ -39,6 +39,26 @@ class FilesTestCase(unittest.TestCase):
39
39
  )
40
40
  self.assertEqual(working_file["id"], 1)
41
41
 
42
+ mock.post(
43
+ gazu.client.get_full_url(path),
44
+ text=json.dumps(
45
+ {"error": "The given working file already exists."}
46
+ ),
47
+ status_code=400,
48
+ )
49
+
50
+ with self.assertRaises(gazu.client.ParameterException) as context:
51
+ gazu.files.new_working_file(
52
+ task,
53
+ person={"id": "person-01"},
54
+ software={"id": "software-1"},
55
+ )
56
+
57
+ self.assertTrue(
58
+ str(context.exception)
59
+ == "The given working file already exists."
60
+ )
61
+
42
62
  def test_new_entity_output_file(self):
43
63
  entity = {"id": "asset-01"}
44
64
  output_type = {"id": "output-type-01"}
@@ -1 +0,0 @@
1
- __version__ = "0.10.16"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes