gazu 0.10.14__tar.gz → 0.10.15__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.14 → gazu-0.10.15}/PKG-INFO +1 -1
  2. gazu-0.10.15/gazu/__version__.py +1 -0
  3. {gazu-0.10.14 → gazu-0.10.15}/gazu/casting.py +36 -0
  4. {gazu-0.10.14 → gazu-0.10.15}/gazu/exception.py +12 -0
  5. {gazu-0.10.14 → gazu-0.10.15}/gazu/playlist.py +112 -0
  6. {gazu-0.10.14 → gazu-0.10.15}/gazu/sync.py +18 -5
  7. {gazu-0.10.14 → gazu-0.10.15}/gazu/task.py +32 -12
  8. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/PKG-INFO +1 -1
  9. {gazu-0.10.14 → gazu-0.10.15}/tests/test_casting.py +28 -0
  10. {gazu-0.10.14 → gazu-0.10.15}/tests/test_playlist.py +45 -0
  11. gazu-0.10.14/gazu/__version__.py +0 -1
  12. {gazu-0.10.14 → gazu-0.10.15}/LICENSE +0 -0
  13. {gazu-0.10.14 → gazu-0.10.15}/README.rst +0 -0
  14. {gazu-0.10.14 → gazu-0.10.15}/gazu/__init__.py +0 -0
  15. {gazu-0.10.14 → gazu-0.10.15}/gazu/asset.py +0 -0
  16. {gazu-0.10.14 → gazu-0.10.15}/gazu/cache.py +0 -0
  17. {gazu-0.10.14 → gazu-0.10.15}/gazu/client.py +0 -0
  18. {gazu-0.10.14 → gazu-0.10.15}/gazu/concept.py +0 -0
  19. {gazu-0.10.14 → gazu-0.10.15}/gazu/context.py +0 -0
  20. {gazu-0.10.14 → gazu-0.10.15}/gazu/edit.py +0 -0
  21. {gazu-0.10.14 → gazu-0.10.15}/gazu/encoder.py +0 -0
  22. {gazu-0.10.14 → gazu-0.10.15}/gazu/entity.py +0 -0
  23. {gazu-0.10.14 → gazu-0.10.15}/gazu/events.py +0 -0
  24. {gazu-0.10.14 → gazu-0.10.15}/gazu/files.py +0 -0
  25. {gazu-0.10.14 → gazu-0.10.15}/gazu/helpers.py +0 -0
  26. {gazu-0.10.14 → gazu-0.10.15}/gazu/person.py +0 -0
  27. {gazu-0.10.14 → gazu-0.10.15}/gazu/project.py +0 -0
  28. {gazu-0.10.14 → gazu-0.10.15}/gazu/scene.py +0 -0
  29. {gazu-0.10.14 → gazu-0.10.15}/gazu/shot.py +0 -0
  30. {gazu-0.10.14 → gazu-0.10.15}/gazu/sorting.py +0 -0
  31. {gazu-0.10.14 → gazu-0.10.15}/gazu/user.py +0 -0
  32. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/SOURCES.txt +0 -0
  33. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/dependency_links.txt +0 -0
  34. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/not-zip-safe +0 -0
  35. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/requires.txt +0 -0
  36. {gazu-0.10.14 → gazu-0.10.15}/gazu.egg-info/top_level.txt +0 -0
  37. {gazu-0.10.14 → gazu-0.10.15}/pyproject.toml +0 -0
  38. {gazu-0.10.14 → gazu-0.10.15}/setup.cfg +0 -0
  39. {gazu-0.10.14 → gazu-0.10.15}/setup.py +0 -0
  40. {gazu-0.10.14 → gazu-0.10.15}/tests/test_asset.py +0 -0
  41. {gazu-0.10.14 → gazu-0.10.15}/tests/test_cache.py +0 -0
  42. {gazu-0.10.14 → gazu-0.10.15}/tests/test_client.py +0 -0
  43. {gazu-0.10.14 → gazu-0.10.15}/tests/test_concept.py +0 -0
  44. {gazu-0.10.14 → gazu-0.10.15}/tests/test_context.py +0 -0
  45. {gazu-0.10.14 → gazu-0.10.15}/tests/test_edit.py +0 -0
  46. {gazu-0.10.14 → gazu-0.10.15}/tests/test_entity.py +0 -0
  47. {gazu-0.10.14 → gazu-0.10.15}/tests/test_files.py +0 -0
  48. {gazu-0.10.14 → gazu-0.10.15}/tests/test_helpers.py +0 -0
  49. {gazu-0.10.14 → gazu-0.10.15}/tests/test_person.py +0 -0
  50. {gazu-0.10.14 → gazu-0.10.15}/tests/test_project.py +0 -0
  51. {gazu-0.10.14 → gazu-0.10.15}/tests/test_scene.py +0 -0
  52. {gazu-0.10.14 → gazu-0.10.15}/tests/test_shot.py +0 -0
  53. {gazu-0.10.14 → gazu-0.10.15}/tests/test_sync.py +0 -0
  54. {gazu-0.10.14 → gazu-0.10.15}/tests/test_task.py +0 -0
  55. {gazu-0.10.14 → gazu-0.10.15}/tests/test_user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gazu
3
- Version: 0.10.14
3
+ Version: 0.10.15
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
@@ -0,0 +1 @@
1
+ __version__ = "0.10.15"
@@ -45,6 +45,25 @@ def update_asset_casting(project, asset, casting, client=default):
45
45
  return raw.put(path, casting, client=client)
46
46
 
47
47
 
48
+ def update_episode_casting(project, episode, casting, client=default):
49
+ """
50
+ Change casting of given episode with given casting (list of asset ids displayed
51
+ into the episode).
52
+
53
+ Args:
54
+ episode (str / dict): The episode dict or the episode ID.
55
+ casting (dict): The casting description.
56
+ Ex: `casting = [{"asset_id": "asset-1", "nb_occurences": 3}]`
57
+
58
+ Returns:
59
+ dict: Related episode.
60
+ """
61
+ episode = normalize_model_parameter(episode)
62
+ project = normalize_model_parameter(project)
63
+ path = "data/projects/%s/entities/%s/casting" % (project["id"], episode["id"])
64
+ return raw.put(path, casting, client=client)
65
+
66
+
48
67
  def get_asset_type_casting(project, asset_type, client=default):
49
68
  """
50
69
  Return casting for given asset_type.
@@ -117,6 +136,23 @@ def get_asset_casting(asset, client=default):
117
136
  return raw.get(path, client=client)
118
137
 
119
138
 
139
+ def get_episode_casting(episode, client=default):
140
+ """
141
+ Return casting for given episode.
142
+ `[{"episode_id": "episode-1", "nb_occurences": 3}]}`
143
+ Args:
144
+ episode (dict): The episode dict
145
+
146
+ Returns:
147
+ dict: Casting for given episode.
148
+ """
149
+ path = "/data/projects/%s/entities/%s/casting" % (
150
+ episode["project_id"],
151
+ episode["id"],
152
+ )
153
+ return raw.get(path, client=client)
154
+
155
+
120
156
  def get_asset_cast_in(asset, client=default):
121
157
  """
122
158
  Return entity list where given asset is casted.
@@ -75,3 +75,15 @@ class TaskMustBeADictException(Exception):
75
75
  """
76
76
  Error raised when a task should be a dict.
77
77
  """
78
+
79
+
80
+ class FileDoesntExistException(Exception):
81
+ """
82
+ Error raised when a file should be existed when we submit a preview.
83
+ """
84
+
85
+
86
+ class ProjectDoesntExistException(Exception):
87
+ """
88
+ Error raised when a project isn't available.
89
+ """
@@ -151,3 +151,115 @@ def update_playlist(playlist, client=default):
151
151
  return raw.put(
152
152
  "data/playlists/%s" % playlist["id"], playlist, client=client
153
153
  )
154
+
155
+
156
+ def get_entity_preview_files(entity, client=default):
157
+ """
158
+ Get all preview files grouped by task type for a given entity.
159
+
160
+ Args:
161
+ entity (str / dict): The entity to retrieve files from or its ID.
162
+
163
+ Returns:
164
+ dict: A dict where keys are task type IDs and value array of revisions.
165
+ """
166
+ entity = normalize_model_parameter(entity)
167
+ return raw.get(
168
+ "data/playlists/entities/%s/preview-files" % entity["id"],
169
+ client=client
170
+ )
171
+
172
+
173
+ def add_entity_to_playlist(
174
+ playlist,
175
+ entity,
176
+ preview_file=None,
177
+ persist=True,
178
+ client=default
179
+ ):
180
+ """
181
+ Add an entity to the playlist, use the last uploaded preview as revision
182
+ to review.
183
+
184
+ Args:
185
+ playlist (dict): Playlist object to modify.
186
+ entity (str / dict): The entity to add or its ID.
187
+ preview_file (str / dict): Set it to force a give revision to review.
188
+ persist (bool): Set it to True to save the result to the API.
189
+
190
+ Returns:
191
+ dict: Updated playlist.
192
+ """
193
+ entity = normalize_model_parameter(entity)
194
+
195
+ if preview_file is None:
196
+ preview_files = get_entity_preview_files(entity)
197
+ for task_type_id in preview_files.keys():
198
+ task_type_files = preview_files[task_type_id]
199
+ first_file = task_type_files[0]
200
+ if preview_file is None or \
201
+ preview_file["created_at"] < first_file["created_at"]:
202
+ preview_file = first_file
203
+
204
+ preview_file = normalize_model_parameter(preview_file)
205
+ playlist["shots"].append({
206
+ "entity_id": entity["id"],
207
+ "preview_file_id": preview_file["id"]
208
+ })
209
+ if persist:
210
+ update_playlist(playlist, client=client)
211
+ return playlist
212
+
213
+
214
+ def remove_entity_from_playlist(
215
+ playlist,
216
+ entity,
217
+ persist=True,
218
+ client=default
219
+ ):
220
+ """
221
+ Remove all occurences of a given entity from a playlist.
222
+
223
+ Args:
224
+ playlist (dict): Playlist object to modify
225
+ entity (str / dict): the entity to remove or its ID
226
+
227
+ Returns:
228
+ dict: Updated playlist.
229
+ """
230
+ entity = normalize_model_parameter(entity)
231
+ playlist["shots"] = [
232
+ entry
233
+ for entry in playlist["shots"]
234
+ if entry["entity_id"] != entity["id"]
235
+ ]
236
+ if persist:
237
+ update_playlist(playlist, client=client)
238
+ return playlist
239
+
240
+
241
+ def update_entity_preview(
242
+ playlist,
243
+ entity,
244
+ preview_file,
245
+ persist=True,
246
+ client=default
247
+ ):
248
+ """
249
+ Remove all occurences of a given entity from a playlist.
250
+
251
+ Args:
252
+ playlist (dict): Playlist object to modify
253
+ entity (str / dict): the entity to add or its ID
254
+
255
+ Returns:
256
+ dict: Updated playlist.
257
+ """
258
+ entity = normalize_model_parameter(entity)
259
+ preview_file = normalize_model_parameter(preview_file)
260
+ for entry in playlist["shots"]:
261
+ if entry["entity_id"] == entity["id"]:
262
+ entry["preview_file_id"] = preview_file["id"]
263
+ if persist:
264
+ update_playlist(playlist, client=client)
265
+ return playlist
@@ -56,6 +56,7 @@ def import_entities(entities, client=default):
56
56
  """
57
57
  Import entities from another instance to target instance (keep id and audit
58
58
  dates).
59
+
59
60
  Args:
60
61
  entities (list): Entities to import.
61
62
 
@@ -69,6 +70,7 @@ def import_tasks(tasks, client=default):
69
70
  """
70
71
  Import tasks from another instance to target instance (keep id and audit
71
72
  dates).
73
+
72
74
  Args:
73
75
  tasks (list): Tasks to import.
74
76
 
@@ -82,6 +84,7 @@ def import_entity_links(links, client=default):
82
84
  """
83
85
  Import enitity links from another instance to target instance (keep id and
84
86
  audit dates).
87
+
85
88
  Args:
86
89
  links (list): Entity links to import.
87
90
 
@@ -292,7 +295,8 @@ def get_sync_person_id_map(source_client, target_client):
292
295
  def push_assets(project_source, project_target, client_source, client_target):
293
296
  """
294
297
  Copy assets from source to target and preserve audit fields (`id`,
295
- `created_at`, and `updated_at`)
298
+ `created_at`, and `updated_at`).
299
+
296
300
  Args:
297
301
  project_source (dict): The project to get assets from
298
302
  project_target (dict): The project to push assets to
@@ -321,6 +325,7 @@ def push_episodes(
321
325
  """
322
326
  Copy episodes from source to target and preserve audit fields (`id`,
323
327
  `created_at`, and `updated_at`)
328
+
324
329
  Args:
325
330
  project_source (dict): The project to get episodes from
326
331
  project_target (dict): The project to push episodes to
@@ -344,6 +349,7 @@ def push_sequences(
344
349
  """
345
350
  Copy sequences from source to target and preserve audit fields (`id`,
346
351
  `created_at`, and `updated_at`)
352
+
347
353
  Args:
348
354
  project_source (dict): The project to get sequences from
349
355
  project_target (dict): The project to push sequences to
@@ -364,7 +370,8 @@ def push_sequences(
364
370
  def push_shots(project_source, project_target, client_source, client_target):
365
371
  """
366
372
  Copy shots from source to target and preserve audit fields (`id`,
367
- `created_at`, and `updated_at`)
373
+ `created_at`, and `updated_at`).
374
+
368
375
  Args:
369
376
  project_source (dict): The project to get shots from
370
377
  project_target (dict): The project to push shots to
@@ -386,8 +393,9 @@ def push_entity_links(
386
393
  project_source, project_target, client_source, client_target
387
394
  ):
388
395
  """
389
- Copy assets from source to target and preserve audit fields (`id`,
390
- `created_at`, and `updated_at`)
396
+ Copy entity links (breakdown, concepts) from source to target and preserve
397
+ audit fields (`id`, `created_at`, and `updated_at`).
398
+
391
399
  Args:
392
400
  project_source (dict): The project to get assets from
393
401
  project_target (dict): The project to push assets to
@@ -408,7 +416,8 @@ def push_project_entities(
408
416
  ):
409
417
  """
410
418
  Copy assets, episodes, sequences, shots and entity links from source to
411
- target and preserve audit fields (`id`, `created_at`, and `updated_at`)
419
+ target and preserve audit fields (`id`, `created_at`, and `updated_at`).
420
+
412
421
  Args:
413
422
  project_source (dict): The project to get assets from
414
423
  project_target (dict): The project to push assets to
@@ -445,6 +454,7 @@ def push_tasks(
445
454
  Copy tasks from source to target and preserve audit fields (`id`,
446
455
  `created_at`, and `updated_at`)
447
456
  Attachments and previews are created too.
457
+
448
458
  Args:
449
459
  project_source (dict): The project to get assets from
450
460
  project_target (dict): The project to push assets to
@@ -479,6 +489,7 @@ def push_tasks_comments(project_source, client_source, client_target):
479
489
  Create a new comment into target api for each comment in source project
480
490
  but preserve only `created_at` field.
481
491
  Attachments and previews are created too.
492
+
482
493
  Args:
483
494
  project_source (dict): The project to get assets from
484
495
  project_target (dict): The project to push assets to
@@ -508,6 +519,7 @@ def push_task_comments(
508
519
  Create a new comment into target api for each comment in source task
509
520
  but preserve only `created_at` field.
510
521
  Attachments and previews are created too.
522
+
511
523
  Args:
512
524
  project_source (dict): The project to get assets from
513
525
  project_target (dict): The project to push assets to
@@ -547,6 +559,7 @@ def push_task_comment(
547
559
  Create a new comment into target api for each comment in source task
548
560
  but preserve only `created_at` field.
549
561
  Attachments and previews are created too.
562
+
550
563
  Args:
551
564
  project_source (dict): The project to get assets from
552
565
  project_target (dict): The project to push assets to
@@ -257,25 +257,31 @@ def all_tasks_for_task_status(project, task_type, task_status, client=default):
257
257
 
258
258
 
259
259
  @cache
260
- def all_tasks_for_task_type(project, task_type, client=default):
260
+ def all_tasks_for_task_type(
261
+ project,
262
+ task_type,
263
+ episode=None,
264
+ client=default
265
+ ):
261
266
  """
262
267
  Args:
263
268
  project (str / dict): The project dict or the project ID.
264
269
  task_type (str / dict): The task type dict or ID.
270
+ episode_id (str / dict): The episode dict or ID.
265
271
 
266
272
  Returns:
267
273
  list: Tasks for given project and task type.
268
274
  """
269
275
  project = normalize_model_parameter(project)
270
276
  task_type = normalize_model_parameter(task_type)
271
- return raw.fetch_all(
272
- "tasks",
273
- {
274
- "project_id": project["id"],
275
- "task_type_id": task_type["id"],
276
- },
277
- client=client,
278
- )
277
+ params = {
278
+ "project_id": project["id"],
279
+ "task_type_id": task_type["id"],
280
+ }
281
+ if episode is not None:
282
+ episode = normalize_model_parameter(episode)
283
+ params["episode_id"] = episode["id"]
284
+ return raw.fetch_all("tasks", params, client=client)
279
285
 
280
286
 
281
287
  @cache
@@ -1260,17 +1266,31 @@ def get_task_url(task, client=default):
1260
1266
  )
1261
1267
 
1262
1268
 
1263
- def all_tasks_for_project(project, client=default):
1269
+ def all_tasks_for_project(
1270
+ project,
1271
+ task_type=None,
1272
+ episode=None,
1273
+ client=default
1274
+ ):
1264
1275
  """
1265
1276
  Args:
1266
- project (str / dict): The project
1277
+ project (str / dict): The project (or its ID) to get tasks from.
1278
+ task_type (str / dict): The task type (or its ID) to filter tasks.
1279
+ episode (str / dict): The episode (or its ID) to filter tasks.
1267
1280
 
1268
1281
  Returns:
1269
1282
  dict: Tasks related to given project.
1270
1283
  """
1271
1284
  project = normalize_model_parameter(project)
1272
1285
  path = "/data/projects/%s/tasks" % project["id"]
1273
- return raw.get(path, client=client)
1286
+ params = {}
1287
+ if task_type is not None:
1288
+ task_type = normalize_model_parameter(task_type)
1289
+ params["task_type_id"] = task_type["id"]
1290
+ if episode is not None:
1291
+ episode = normalize_model_parameter(episode)
1292
+ params["episode_id"] = episode["id"]
1293
+ return raw.get(path, params=params, client=client)
1274
1294
 
1275
1295
 
1276
1296
  def update_comment(comment, client=default):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gazu
3
- Version: 0.10.14
3
+ Version: 0.10.15
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
@@ -37,6 +37,19 @@ class CastingTestCase(unittest.TestCase):
37
37
  )
38
38
  self.assertEqual(casting[0]["asset_id"], fakeid("asset-1"))
39
39
 
40
+ def test_update_episode_casting(self):
41
+ casting = [{"asset_id": fakeid("asset-1"), "nb_occurences": 3}]
42
+ path = "data/projects/%s/entities/%s/casting" % (
43
+ fakeid("project-01"),
44
+ fakeid("episode-01"),
45
+ )
46
+ with requests_mock.mock() as mock:
47
+ mock.put(gazu.client.get_full_url(path), text=json.dumps(casting))
48
+ episode = {"id": fakeid("episode-01")}
49
+ project = {"id": fakeid("project-01")}
50
+ casting = gazu.casting.update_episode_casting(project, episode, casting)
51
+ self.assertEqual(casting[0]["asset_id"], fakeid("asset-1"))
52
+
40
53
  def test_get_asset_type_casting(self):
41
54
  casting = {
42
55
  fakeid("asset-2"): [
@@ -92,6 +105,21 @@ class CastingTestCase(unittest.TestCase):
92
105
  casting = gazu.casting.get_shot_casting(shot)
93
106
  self.assertEqual(casting[0]["asset_id"], fakeid("asset-1"))
94
107
 
108
+ def test_get_episode_casting(self):
109
+ casting = [{"asset_id": fakeid("asset-1"), "nb_occurences": 3}]
110
+ path = "data/projects/%s/entities/%s/casting" % (
111
+ fakeid("project-01"),
112
+ fakeid("episode-01"),
113
+ )
114
+ with requests_mock.mock() as mock:
115
+ mock.get(gazu.client.get_full_url(path), text=json.dumps(casting))
116
+ episode = {
117
+ "id": fakeid("episode-01"),
118
+ "project_id": fakeid("project-01"),
119
+ }
120
+ casting = gazu.casting.get_episode_casting(episode)
121
+ self.assertEqual(casting[0]["asset_id"], fakeid("asset-1"))
122
+
95
123
  def test_get_asset_casting(self):
96
124
  casting = [{"asset_id": fakeid("asset-1"), "nb_occurences": 3}]
97
125
  path = "data/projects/%s/entities/%s/casting" % (
@@ -166,3 +166,48 @@ class TaskTestCase(unittest.TestCase):
166
166
  playlist = {"id": fakeid("playlist-1"), "name": "name_changed"}
167
167
  playlist = gazu.playlist.update_playlist(playlist)
168
168
  self.assertEqual(playlist["id"], fakeid("playlist-1"))
169
+
170
+ def test_add_entity_to_playlist(self):
171
+ with requests_mock.mock() as mock:
172
+ mock.put(
173
+ gazu.client.get_full_url(
174
+ "data/playlists/%s" % fakeid("playlist-1")
175
+ ),
176
+ text=json.dumps(
177
+ {"id": fakeid("playlist-1"), "name": "name_changed"}
178
+ ),
179
+ )
180
+ mock.get(
181
+ gazu.client.get_full_url(
182
+ "data/playlists/entities/%s/preview-files" % fakeid("shot-1")
183
+ ),
184
+ text=json.dumps(
185
+ {fakeid("task-type-1"): [{"id": fakeid("preview-1")}]}
186
+ ),
187
+ )
188
+ playlist = {
189
+ "id": fakeid("playlist-1"),
190
+ "name": "name_changed",
191
+ "shots": []
192
+ }
193
+ shot = {
194
+ "id": fakeid("shot-1"),
195
+ "name": "SH01"
196
+ }
197
+ playlist = gazu.playlist.add_entity_to_playlist(playlist, shot)
198
+ self.assertEqual(playlist["id"], fakeid("playlist-1"))
199
+ self.assertEqual(playlist["shots"], [{
200
+ "entity_id": fakeid("shot-1"),
201
+ "preview_file_id": fakeid("preview-1")
202
+ }])
203
+ playlist = gazu.playlist.update_entity_preview(
204
+ playlist,
205
+ shot,
206
+ fakeid("preview-2")
207
+ )
208
+ self.assertEqual(playlist["shots"], [{
209
+ "entity_id": fakeid("shot-1"),
210
+ "preview_file_id": fakeid("preview-2")
211
+ }])
212
+ playlist = gazu.playlist.remove_entity_from_playlist(playlist, shot)
213
+ self.assertEqual(playlist["shots"], [])
@@ -1 +0,0 @@
1
- __version__ = "0.10.14"
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