gazu 0.10.13__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.13 → gazu-0.10.15}/PKG-INFO +3 -2
  2. gazu-0.10.15/gazu/__version__.py +1 -0
  3. {gazu-0.10.13 → gazu-0.10.15}/gazu/casting.py +36 -0
  4. {gazu-0.10.13 → gazu-0.10.15}/gazu/exception.py +12 -22
  5. {gazu-0.10.13 → gazu-0.10.15}/gazu/person.py +49 -0
  6. {gazu-0.10.13 → gazu-0.10.15}/gazu/playlist.py +112 -0
  7. {gazu-0.10.13 → gazu-0.10.15}/gazu/shot.py +3 -1
  8. {gazu-0.10.13 → gazu-0.10.15}/gazu/sync.py +18 -5
  9. {gazu-0.10.13 → gazu-0.10.15}/gazu/task.py +37 -14
  10. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/PKG-INFO +3 -2
  11. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/requires.txt +2 -1
  12. {gazu-0.10.13 → gazu-0.10.15}/setup.cfg +2 -1
  13. {gazu-0.10.13 → gazu-0.10.15}/tests/test_casting.py +28 -0
  14. {gazu-0.10.13 → gazu-0.10.15}/tests/test_client.py +1 -2
  15. {gazu-0.10.13 → gazu-0.10.15}/tests/test_context.py +1 -1
  16. {gazu-0.10.13 → gazu-0.10.15}/tests/test_edit.py +0 -2
  17. {gazu-0.10.13 → gazu-0.10.15}/tests/test_person.py +33 -0
  18. {gazu-0.10.13 → gazu-0.10.15}/tests/test_playlist.py +45 -0
  19. {gazu-0.10.13 → gazu-0.10.15}/tests/test_project.py +0 -1
  20. {gazu-0.10.13 → gazu-0.10.15}/tests/test_task.py +3 -7
  21. gazu-0.10.13/gazu/__version__.py +0 -1
  22. {gazu-0.10.13 → gazu-0.10.15}/LICENSE +0 -0
  23. {gazu-0.10.13 → gazu-0.10.15}/README.rst +0 -0
  24. {gazu-0.10.13 → gazu-0.10.15}/gazu/__init__.py +0 -0
  25. {gazu-0.10.13 → gazu-0.10.15}/gazu/asset.py +0 -0
  26. {gazu-0.10.13 → gazu-0.10.15}/gazu/cache.py +0 -0
  27. {gazu-0.10.13 → gazu-0.10.15}/gazu/client.py +0 -0
  28. {gazu-0.10.13 → gazu-0.10.15}/gazu/concept.py +0 -0
  29. {gazu-0.10.13 → gazu-0.10.15}/gazu/context.py +0 -0
  30. {gazu-0.10.13 → gazu-0.10.15}/gazu/edit.py +0 -0
  31. {gazu-0.10.13 → gazu-0.10.15}/gazu/encoder.py +0 -0
  32. {gazu-0.10.13 → gazu-0.10.15}/gazu/entity.py +0 -0
  33. {gazu-0.10.13 → gazu-0.10.15}/gazu/events.py +0 -0
  34. {gazu-0.10.13 → gazu-0.10.15}/gazu/files.py +0 -0
  35. {gazu-0.10.13 → gazu-0.10.15}/gazu/helpers.py +0 -0
  36. {gazu-0.10.13 → gazu-0.10.15}/gazu/project.py +0 -0
  37. {gazu-0.10.13 → gazu-0.10.15}/gazu/scene.py +0 -0
  38. {gazu-0.10.13 → gazu-0.10.15}/gazu/sorting.py +0 -0
  39. {gazu-0.10.13 → gazu-0.10.15}/gazu/user.py +0 -0
  40. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/SOURCES.txt +0 -0
  41. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/dependency_links.txt +0 -0
  42. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/not-zip-safe +0 -0
  43. {gazu-0.10.13 → gazu-0.10.15}/gazu.egg-info/top_level.txt +0 -0
  44. {gazu-0.10.13 → gazu-0.10.15}/pyproject.toml +0 -0
  45. {gazu-0.10.13 → gazu-0.10.15}/setup.py +0 -0
  46. {gazu-0.10.13 → gazu-0.10.15}/tests/test_asset.py +0 -0
  47. {gazu-0.10.13 → gazu-0.10.15}/tests/test_cache.py +0 -0
  48. {gazu-0.10.13 → gazu-0.10.15}/tests/test_concept.py +0 -0
  49. {gazu-0.10.13 → gazu-0.10.15}/tests/test_entity.py +0 -0
  50. {gazu-0.10.13 → gazu-0.10.15}/tests/test_files.py +0 -0
  51. {gazu-0.10.13 → gazu-0.10.15}/tests/test_helpers.py +0 -0
  52. {gazu-0.10.13 → gazu-0.10.15}/tests/test_scene.py +0 -0
  53. {gazu-0.10.13 → gazu-0.10.15}/tests/test_shot.py +0 -0
  54. {gazu-0.10.13 → gazu-0.10.15}/tests/test_sync.py +0 -0
  55. {gazu-0.10.13 → 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.13
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
@@ -35,7 +35,8 @@ Requires-Dist: pytest; extra == "test"
35
35
  Requires-Dist: pytest-cov; extra == "test"
36
36
  Requires-Dist: requests_mock; extra == "test"
37
37
  Provides-Extra: lint
38
- Requires-Dist: black==24.4.2; python_version >= "3.8" and extra == "lint"
38
+ Requires-Dist: autoflake==2.3.1; python_version >= "3.8" and extra == "lint"
39
+ Requires-Dist: black==24.8.0; python_version >= "3.8" and extra == "lint"
39
40
  Requires-Dist: pre-commit==3.8.0; python_version >= "3.9" and extra == "lint"
40
41
 
41
42
  .. figure:: https://zou.cg-wire.com/kitsu.png
@@ -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.
@@ -3,64 +3,48 @@ class HostException(Exception):
3
3
  Error raised when host is not valid.
4
4
  """
5
5
 
6
- pass
7
-
8
6
 
9
7
  class AuthFailedException(Exception):
10
8
  """
11
9
  Error raised when user credentials are wrong.
12
10
  """
13
11
 
14
- pass
15
-
16
12
 
17
13
  class NotAuthenticatedException(Exception):
18
14
  """
19
15
  Error raised when a 401 error (not authenticated) is sent by the API.
20
16
  """
21
17
 
22
- pass
23
-
24
18
 
25
19
  class NotAllowedException(Exception):
26
20
  """
27
21
  Error raised when a 403 error (not authorized) is sent by the API.
28
22
  """
29
23
 
30
- pass
31
-
32
24
 
33
25
  class MethodNotAllowedException(Exception):
34
26
  """
35
27
  Error raised when a 405 error (method not handled) is sent by the API.
36
28
  """
37
29
 
38
- pass
39
-
40
30
 
41
31
  class RouteNotFoundException(Exception):
42
32
  """
43
33
  Error raised when a 404 error (not found) is sent by the API.
44
34
  """
45
35
 
46
- pass
47
-
48
36
 
49
37
  class ServerErrorException(Exception):
50
38
  """
51
39
  Error raised when a 500 error (server error) is sent by the API.
52
40
  """
53
41
 
54
- pass
55
-
56
42
 
57
43
  class ParameterException(Exception):
58
44
  """
59
45
  Error raised when a 400 error (argument error) is sent by the API.
60
46
  """
61
47
 
62
- pass
63
-
64
48
 
65
49
  class UploadFailedException(Exception):
66
50
  """
@@ -68,24 +52,18 @@ class UploadFailedException(Exception):
68
52
  where processing that occurs on the remote server fails.
69
53
  """
70
54
 
71
- pass
72
-
73
55
 
74
56
  class TooBigFileException(Exception):
75
57
  """
76
58
  Error raised when a 413 error (payload too big error) is sent by the API.
77
59
  """
78
60
 
79
- pass
80
-
81
61
 
82
62
  class TaskStatusNotFoundException(Exception):
83
63
  """
84
64
  Error raised when a task status is not found.
85
65
  """
86
66
 
87
- pass
88
-
89
67
 
90
68
  class DownloadFileException(Exception):
91
69
  """
@@ -97,3 +75,15 @@ class TaskMustBeADictException(Exception):
97
75
  """
98
76
  Error raised when a task should be a dict.
99
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
+ """
@@ -78,6 +78,34 @@ def get_all_month_time_spents(id, date, client=default):
78
78
  )
79
79
 
80
80
 
81
+ @cache
82
+ def get_department_by_name(name, client=default):
83
+ """
84
+ Args:
85
+ name (str): Department name.
86
+
87
+ Returns:
88
+ dict: Department corresponding to given name.
89
+ """
90
+ return raw.fetch_first(
91
+ "departments",
92
+ {"name": name},
93
+ client=client,
94
+ )
95
+
96
+
97
+ @cache
98
+ def get_department(department_id, client=default):
99
+ """
100
+ Args:
101
+ department_id (str): An uuid identifying a department.
102
+
103
+ Returns:
104
+ dict: Department corresponding to given department_id.
105
+ """
106
+ return raw.fetch_one("departments", department_id, client=client)
107
+
108
+
81
109
  @cache
82
110
  def get_person(id, relations=False, client=default):
83
111
  """
@@ -182,6 +210,27 @@ def get_organisation(client=default):
182
210
  return raw.get("auth/authenticated", client=client)["organisation"]
183
211
 
184
212
 
213
+ def new_department(name, color="", archived=False, client=default):
214
+ """
215
+ Create a new departement based on given parameters.
216
+
217
+ Args:
218
+ name (str): the name of the departement.
219
+ color (str): the color of the departement.
220
+ archived (bool): Whether the departement is archived or not.
221
+ Returns:
222
+ dict: Created departement.
223
+ """
224
+ department = get_department_by_name(name, client=client)
225
+ if department is None:
226
+ department = raw.post(
227
+ "data/departments",
228
+ {"name": name, "color": color, "archived": archived},
229
+ client=client,
230
+ )
231
+ return department
232
+
233
+
185
234
  def new_person(
186
235
  first_name,
187
236
  last_name,
@@ -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
@@ -404,7 +404,9 @@ def update_shot_data(shot, data={}, client=default):
404
404
  """
405
405
  shot = normalize_model_parameter(shot)
406
406
  current_shot = get_shot(shot["id"], client=client)
407
- current_data = current_shot["data"] if current_shot["data"] is not None else {}
407
+ current_data = (
408
+ current_shot["data"] if current_shot["data"] is not None else {}
409
+ )
408
410
  updated_shot = {"id": current_shot["id"], "data": current_data}
409
411
  updated_shot["data"].update(data)
410
412
  return update_shot(updated_shot, client=client)
@@ -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
@@ -1174,8 +1180,11 @@ def new_task_type(name, color="#000000", for_entity="Asset", client=default):
1174
1180
  Returns:
1175
1181
  dict: The created task type
1176
1182
  """
1177
- data = {"name": name, "color": color, "for_entity": for_entity}
1178
- return raw.post("data/task-types", data, client=client)
1183
+ task_type = get_task_type_by_name(name, for_entity)
1184
+ if task_type is None:
1185
+ data = {"name": name, "color": color, "for_entity": for_entity}
1186
+ task_type = raw.post("data/task-types", data, client=client)
1187
+ return task_type
1179
1188
 
1180
1189
 
1181
1190
  def new_task_status(name, short_name, color, client=default):
@@ -1257,17 +1266,31 @@ def get_task_url(task, client=default):
1257
1266
  )
1258
1267
 
1259
1268
 
1260
- 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
+ ):
1261
1275
  """
1262
1276
  Args:
1263
- 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.
1264
1280
 
1265
1281
  Returns:
1266
1282
  dict: Tasks related to given project.
1267
1283
  """
1268
1284
  project = normalize_model_parameter(project)
1269
1285
  path = "/data/projects/%s/tasks" % project["id"]
1270
- 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)
1271
1294
 
1272
1295
 
1273
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.13
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
@@ -35,7 +35,8 @@ Requires-Dist: pytest; extra == "test"
35
35
  Requires-Dist: pytest-cov; extra == "test"
36
36
  Requires-Dist: requests_mock; extra == "test"
37
37
  Provides-Extra: lint
38
- Requires-Dist: black==24.4.2; python_version >= "3.8" and extra == "lint"
38
+ Requires-Dist: autoflake==2.3.1; python_version >= "3.8" and extra == "lint"
39
+ Requires-Dist: black==24.8.0; python_version >= "3.8" and extra == "lint"
39
40
  Requires-Dist: pre-commit==3.8.0; python_version >= "3.9" and extra == "lint"
40
41
 
41
42
  .. figure:: https://zou.cg-wire.com/kitsu.png
@@ -10,7 +10,8 @@ wheel
10
10
  [lint]
11
11
 
12
12
  [lint:python_version >= "3.8"]
13
- black==24.4.2
13
+ autoflake==2.3.1
14
+ black==24.8.0
14
15
 
15
16
  [lint:python_version >= "3.9"]
16
17
  pre-commit==3.8.0
@@ -45,7 +45,8 @@ test =
45
45
  pytest-cov
46
46
  requests_mock
47
47
  lint =
48
- black==24.4.2; python_version >= '3.8'
48
+ autoflake==2.3.1; python_version >= '3.8'
49
+ black==24.8.0; python_version >= '3.8'
49
50
  pre-commit==3.8.0; python_version >= '3.9'
50
51
 
51
52
  [bdist_wheel]
@@ -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" % (
@@ -1,13 +1,12 @@
1
1
  import datetime
2
2
  import json
3
- import sys
4
3
 
5
4
  import unittest
6
5
  import requests_mock
7
6
  import gazu
8
7
  from gazu.__version__ import __version__
9
8
 
10
- from gazu import client as raw, set_event_host
9
+ from gazu import client as raw
11
10
  from gazu.exception import (
12
11
  RouteNotFoundException,
13
12
  AuthFailedException,
@@ -7,7 +7,7 @@ import gazu.scene
7
7
  import gazu.shot
8
8
  import gazu.project
9
9
  import requests_mock
10
- from utils import mock_route, fakeid
10
+ from utils import mock_route
11
11
 
12
12
 
13
13
  class CastingTestCase(unittest.TestCase):
@@ -1,7 +1,5 @@
1
1
  import unittest
2
- import json
3
2
  import requests_mock
4
- import os
5
3
 
6
4
  import gazu.client
7
5
  import gazu.edit
@@ -53,6 +53,39 @@ class PersonTestCase(unittest.TestCase):
53
53
  person = gazu.person.get_person_by_full_name("", "John", "Doe")
54
54
  self.assertEqual(person["id"], "person-1")
55
55
 
56
+ def test_get_department_by_name(self):
57
+ with requests_mock.mock() as mock:
58
+ mock_route(
59
+ mock,
60
+ "GET",
61
+ "data/departments?name=department-1",
62
+ text=[{"name": "department-1"}],
63
+ )
64
+ department = gazu.person.get_department_by_name("department-1")
65
+ self.assertEqual(department["name"], "department-1")
66
+
67
+ def test_get_department(self):
68
+ with requests_mock.mock() as mock:
69
+ mock_route(
70
+ mock,
71
+ "GET",
72
+ "data/departments/%s" % fakeid("department-1"),
73
+ text={"name": "department-1"},
74
+ )
75
+ department = gazu.person.get_department(fakeid("department-1"))
76
+ self.assertEqual(department["name"], "department-1")
77
+
78
+ def test_new_department(self):
79
+ with requests_mock.mock() as mock:
80
+ result = {"name": "department-1"}
81
+ mock_route(
82
+ mock, "GET", "data/departments?name=department-1", text=[]
83
+ )
84
+ mock_route(mock, "POST", "data/departments", text=result)
85
+ self.assertEqual(
86
+ gazu.person.new_department("department-1"), result
87
+ )
88
+
56
89
  def test_get_person_by_desktop_login(self):
57
90
  with requests_mock.mock() as mock:
58
91
  mock.get(
@@ -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,4 +1,3 @@
1
- from gazu.helpers import normalize_model_parameter
2
1
  import unittest
3
2
  import requests_mock
4
3
  import gazu.client
@@ -1,4 +1,3 @@
1
- from re import T
2
1
  import unittest
3
2
  import json
4
3
  import requests_mock
@@ -508,13 +507,10 @@ class TaskTestCase(unittest.TestCase):
508
507
  self.assertIn("person-01", task["assignees"])
509
508
 
510
509
  def test_new_task_type(self):
511
- task_type_name = "task-type-name"
512
510
  with requests_mock.mock() as mock:
513
- task_type = {"id": "task-type-01", "name": task_type_name}
514
- mock.post(
515
- gazu.client.get_full_url("data/task-types"),
516
- text=json.dumps(task_type),
517
- )
511
+ task_type = {"id": "task-type-01", "name": "task-type-name"}
512
+ mock_route(mock, "GET", "data/task-types", text=[])
513
+ mock_route(mock, "POST", "data/task-types", text=task_type)
518
514
  self.assertEqual(gazu.task.new_task_type(task_type), task_type)
519
515
 
520
516
  def test_new_task_status(self):
@@ -1 +0,0 @@
1
- __version__ = "0.10.13"
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