zou 0.19.68__py3-none-any.whl → 0.19.69__py3-none-any.whl

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.
zou/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.19.68"
1
+ __version__ = "0.19.69"
@@ -435,8 +435,8 @@ class CommentManyTasksResource(Resource):
435
435
  allowed_comments = []
436
436
  for comment in comments:
437
437
  try:
438
- task = tasks_service.get_task_with_relations(
439
- comment["object_id"],
438
+ task = tasks_service.get_task(
439
+ comment["object_id"], relations=True
440
440
  )
441
441
  if (
442
442
  person["role"] == "supervisor"
@@ -13,7 +13,6 @@ from zou.app.mixin import ArgsMixin
13
13
  from zou.app.utils import events, fields, permissions, query
14
14
  from zou.app.services.exception import (
15
15
  WrongParameterException,
16
- WrongParameterException,
17
16
  )
18
17
 
19
18
 
@@ -259,14 +258,6 @@ class BaseModelsResource(Resource, ArgsMixin):
259
258
  current_app.logger.error(str(exception), exc_info=1)
260
259
  return {"message": str(exception)}, 400
261
260
 
262
- except WrongParameterException as exception:
263
- current_app.logger.error(str(exception), exc_info=1)
264
- return (
265
- exception.dict
266
- if exception.dict is not None
267
- else {"message": str(exception)}
268
- ), 400
269
-
270
261
  def emit_create_event(self, instance_dict):
271
262
  return events.emit(
272
263
  "%s:new" % self.model.__tablename__.replace("_", "-"),
@@ -290,6 +281,10 @@ class BaseModelResource(Resource, ArgsMixin):
290
281
  abort(404)
291
282
  return instance
292
283
 
284
+ def get_serialized_instance(self, instance_id, relations=True):
285
+ instance = self.get_model_or_404(instance_id)
286
+ return self.serialize_instance(instance, relations=relations)
287
+
293
288
  def check_read_permissions(self, instance_dict):
294
289
  return permissions.check_admin_permissions()
295
290
 
@@ -338,8 +333,9 @@ class BaseModelResource(Resource, ArgsMixin):
338
333
  """
339
334
  relations = self.get_bool_parameter("relations", "true")
340
335
  try:
341
- instance = self.get_model_or_404(instance_id)
342
- result = self.serialize_instance(instance, relations=relations)
336
+ result = self.get_serialized_instance(
337
+ instance_id, relations=relations
338
+ )
343
339
  self.check_read_permissions(result)
344
340
  result = self.clean_get_result(result)
345
341
 
@@ -430,14 +426,6 @@ class BaseModelResource(Resource, ArgsMixin):
430
426
  current_app.logger.error(str(exception), exc_info=1)
431
427
  return {"message": str(exception)}, 400
432
428
 
433
- except WrongParameterException as exception:
434
- current_app.logger.error(str(exception), exc_info=1)
435
- return (
436
- exception.dict
437
- if exception.dict is not None
438
- else {"message": str(exception)}
439
- ), 400
440
-
441
429
  @jwt_required()
442
430
  def delete(self, instance_id):
443
431
  """
@@ -1,7 +1,5 @@
1
1
  from flask_jwt_extended import jwt_required
2
- from flask import current_app
3
2
 
4
- from sqlalchemy.exc import StatementError
5
3
 
6
4
  from zou.app.models.comment import Comment
7
5
  from zou.app.models.attachment_file import AttachmentFile
@@ -19,10 +17,6 @@ from zou.app.utils import events, permissions
19
17
 
20
18
  from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
21
19
 
22
- from zou.app.services.exception import (
23
- CommentNotFoundException,
24
- )
25
-
26
20
 
27
21
  class CommentsResource(BaseModelsResource):
28
22
  def __init__(self):
@@ -47,25 +41,8 @@ class CommentResource(BaseModelResource):
47
41
  BaseModelResource.__init__(self, Comment)
48
42
  self.protected_fields += ["mentions", "department_mentions"]
49
43
 
50
- @jwt_required()
51
- def get(self, instance_id):
52
- """
53
- Retrieve a model corresponding at given ID and return it as a JSON
54
- object.
55
- """
56
- try:
57
- instance = tasks_service.get_comment_with_relations(instance_id)
58
- self.check_read_permissions(instance)
59
- result = self.clean_get_result(instance)
60
-
61
- except StatementError as exception:
62
- current_app.logger.error(str(exception), exc_info=1)
63
- return {"message": str(exception)}, 400
64
-
65
- except ValueError:
66
- raise CommentNotFoundException
67
-
68
- return result, 200
44
+ def get_serialized_instance(self, instance_id, relations=True):
45
+ return tasks_service.get_comment(instance_id, relations=relations)
69
46
 
70
47
  def clean_get_result(self, result):
71
48
  if permissions.has_client_permissions():
@@ -123,8 +100,8 @@ class CommentResource(BaseModelResource):
123
100
  instance["object_id"], relations=True
124
101
  )
125
102
  task_type = tasks_service.get_task_type(task["task_type_id"])
126
- project = projects_service.get_project_with_relations(
127
- task["project_id"]
103
+ project = projects_service.get_project(
104
+ task["project_id"], relations=True
128
105
  )
129
106
  current_user = persons_service.get_current_user(relations=True)
130
107
  if current_user["id"] not in project["team"]:
@@ -97,6 +97,8 @@ class PersonsResource(BaseModelsResource):
97
97
  raise WrongParameterException(
98
98
  "Expiration date can't be in the past."
99
99
  )
100
+ except WrongParameterException:
101
+ raise
100
102
  except:
101
103
  raise WrongParameterException("Expiration date is not valid.")
102
104
  return data
@@ -178,6 +180,8 @@ class PersonResource(BaseModelResource, ArgsMixin):
178
180
  raise WrongParameterException(
179
181
  "Expiration date can't be in the past."
180
182
  )
183
+ except WrongParameterException:
184
+ raise
181
185
  except:
182
186
  raise WrongParameterException("Expiration date is not valid.")
183
187
  return data
@@ -116,7 +116,10 @@ class TasksResource(BaseModelsResource, ArgsMixin):
116
116
  instance.save()
117
117
  self.emit_create_event(instance.serialize())
118
118
 
119
- return tasks_service.get_task_with_relations(str(instance.id)), 201
119
+ return (
120
+ tasks_service.get_task(str(instance.id), relations=True),
121
+ 201,
122
+ )
120
123
 
121
124
  except TypeError as exception:
122
125
  current_app.logger.error(str(exception), exc_info=1)
@@ -30,7 +30,6 @@ from zou.app.services.exception import (
30
30
  UnactiveUserException,
31
31
  TwoFactorAuthenticationNotEnabledException,
32
32
  PersonInProtectedAccounts,
33
- WrongParameterException,
34
33
  )
35
34
  from zou.app.services.auth_service import (
36
35
  disable_two_factor_authentication_for_person,
@@ -20,7 +20,6 @@ from zou.app.mixin import ArgsMixin
20
20
  from zou.app.utils import fields, query, permissions
21
21
  from zou.app.services.exception import (
22
22
  WrongParameterException,
23
- WrongParameterException,
24
23
  )
25
24
 
26
25
 
zou/app/config.py CHANGED
@@ -158,6 +158,7 @@ CRISP_TOKEN = os.getenv("CRISP_TOKEN", "")
158
158
  IS_SELF_HOSTED = envtobool("IS_SELF_HOSTED", True)
159
159
 
160
160
  DEFAULT_TIMEZONE = os.getenv("DEFAULT_TIMEZONE", "Europe/Paris")
161
+ DEFAULT_LOCALE = os.getenv("DEFAULT_LOCALE", "en_US")
161
162
 
162
163
  USER_LIMIT = int(os.getenv("USER_LIMIT", "100"))
163
164
  MIN_PASSWORD_LENGTH = int(os.getenv("MIN_PASSWORD_LENGTH", 8))
zou/app/models/person.py CHANGED
@@ -94,7 +94,7 @@ class Person(db.Model, BaseMixin, SerializerMixin):
94
94
  TimezoneType(backend="pytz"),
95
95
  default=pytz_timezone(config.DEFAULT_TIMEZONE),
96
96
  )
97
- locale = db.Column(LocaleType, default=Locale("en", "US"))
97
+ locale = db.Column(LocaleType, default=Locale(config.DEFAULT_LOCALE))
98
98
  data = db.Column(JSONB)
99
99
  role = db.Column(ChoiceType(ROLE_TYPES), default="user", nullable=False)
100
100
  has_avatar = db.Column(db.Boolean(), default=False)
@@ -40,7 +40,7 @@ from zou.app.services.exception import (
40
40
 
41
41
  def clear_asset_cache(asset_id):
42
42
  cache.cache.delete_memoized(get_asset, asset_id)
43
- cache.cache.delete_memoized(get_asset_with_relations, asset_id)
43
+ cache.cache.delete_memoized(get_asset, asset_id, True)
44
44
  cache.cache.delete_memoized(get_full_asset, asset_id)
45
45
 
46
46
 
@@ -416,19 +416,13 @@ def get_asset_raw(entity_id):
416
416
 
417
417
 
418
418
  @cache.memoize_function(120)
419
- def get_asset(entity_id):
419
+ def get_asset(entity_id, relations=False):
420
420
  """
421
421
  Return a given asset as a dict.
422
422
  """
423
- return get_asset_raw(entity_id).serialize(obj_type="Asset")
424
-
425
-
426
- @cache.memoize_function(120)
427
- def get_asset_with_relations(entity_id):
428
- """
429
- Return a given asset as a dict.
430
- """
431
- return get_asset_raw(entity_id).serialize(obj_type="Asset", relations=True)
423
+ return get_asset_raw(entity_id).serialize(
424
+ obj_type="Asset", relations=relations
425
+ )
432
426
 
433
427
 
434
428
  def get_asset_by_shotgun_id(shotgun_id):
@@ -458,7 +452,7 @@ def get_full_asset(asset_id):
458
452
  """
459
453
  assets = get_assets_and_tasks({"id": asset_id}, with_episode_ids=True)
460
454
  if len(assets) > 0:
461
- asset = get_asset_with_relations(asset_id)
455
+ asset = get_asset(asset_id, relations=True)
462
456
  asset_type_id = asset["entity_type_id"]
463
457
  asset_type = get_asset_type(asset_type_id)
464
458
  project = Project.get(asset["project_id"])
@@ -414,7 +414,7 @@ def _create_episode_casting_link(entity, asset_id, nb_occurences=1, label=""):
414
414
  link = EntityLink.create(
415
415
  entity_in_id=sequence["parent_id"],
416
416
  entity_out_id=asset_id,
417
- nb_occurences=1,
417
+ nb_occurences=nb_occurences,
418
418
  label=label,
419
419
  )
420
420
  events.emit(
@@ -82,7 +82,7 @@ def create_comment(
82
82
  """
83
83
  Create a new comment and related: news, notifications and events.
84
84
  """
85
- task = tasks_service.get_task_with_relations(task_id)
85
+ task = tasks_service.get_task(task_id, relations=True)
86
86
  task_status = tasks_service.get_task_status(task_status_id)
87
87
  author = _get_comment_author(person_id)
88
88
  _check_retake_capping(task_status, task)
@@ -33,7 +33,7 @@ from zou.app.services.exception import (
33
33
 
34
34
  def clear_concept_cache(concept_id):
35
35
  cache.cache.delete_memoized(get_concept, concept_id)
36
- cache.cache.delete_memoized(get_concept_with_relations, concept_id)
36
+ cache.cache.delete_memoized(get_concept, concept_id, True)
37
37
  cache.cache.delete_memoized(get_full_concept, concept_id)
38
38
 
39
39
 
@@ -61,23 +61,15 @@ def get_concept_raw(concept_id):
61
61
 
62
62
 
63
63
  @cache.memoize_function(120)
64
- def get_concept_with_relations(concept_id):
64
+ def get_concept(concept_id, relations=False):
65
65
  """
66
66
  Return given concept as a dictionary.
67
67
  """
68
68
  return get_concept_raw(concept_id).serialize(
69
- obj_type="Concept", relations=True
69
+ obj_type="Concept", relations=relations
70
70
  )
71
71
 
72
72
 
73
- @cache.memoize_function(120)
74
- def get_concept(concept_id):
75
- """
76
- Return given concept as a dictionary.
77
- """
78
- return get_concept_raw(concept_id).serialize(obj_type="Concept")
79
-
80
-
81
73
  @cache.memoize_function(120)
82
74
  def get_full_concept(concept_id):
83
75
  """
@@ -86,7 +78,7 @@ def get_full_concept(concept_id):
86
78
  concepts = get_concepts_and_tasks({"id": concept_id})
87
79
  if len(concepts) > 0:
88
80
  concept = concepts[0]
89
- concept.update(get_concept_with_relations(concept_id))
81
+ concept.update(get_concept(concept_id, relations=True))
90
82
  return concept
91
83
  else:
92
84
  raise ConceptNotFoundException
@@ -33,7 +33,7 @@ from zou.app.services.exception import (
33
33
 
34
34
  def clear_edit_cache(edit_id):
35
35
  cache.cache.delete_memoized(get_edit, edit_id)
36
- cache.cache.delete_memoized(get_edit_with_relations, edit_id)
36
+ cache.cache.delete_memoized(get_edit, edit_id, True)
37
37
  cache.cache.delete_memoized(get_full_edit, edit_id)
38
38
 
39
39
 
@@ -241,19 +241,13 @@ def get_edit_raw(edit_id):
241
241
 
242
242
 
243
243
  @cache.memoize_function(120)
244
- def get_edit(edit_id):
244
+ def get_edit(edit_id, relations=False):
245
245
  """
246
246
  Return given edit as a dictionary.
247
247
  """
248
- return get_edit_raw(edit_id).serialize(obj_type="Edit")
249
-
250
-
251
- @cache.memoize_function(120)
252
- def get_edit_with_relations(edit_id):
253
- """
254
- Return given edit as a dictionary.
255
- """
256
- return get_edit_raw(edit_id).serialize(obj_type="Edit", relations=True)
248
+ return get_edit_raw(edit_id).serialize(
249
+ obj_type="Edit", relations=relations
250
+ )
257
251
 
258
252
 
259
253
  @cache.memoize_function(120)
@@ -230,6 +230,8 @@ def create_person(
230
230
  raise WrongParameterException(
231
231
  "Expiration date can't be in the past."
232
232
  )
233
+ except WrongParameterException:
234
+ raise
233
235
  except:
234
236
  raise WrongParameterException("Expiration date is not valid.")
235
237
 
@@ -310,6 +312,8 @@ def update_person(person_id, data, bypass_protected_accounts=False):
310
312
  raise WrongParameterException(
311
313
  "Expiration date can't be in the past."
312
314
  )
315
+ except WrongParameterException:
316
+ raise
313
317
  except:
314
318
  raise WrongParameterException("Expiration date is not valid.")
315
319
 
@@ -89,7 +89,7 @@ def _is_valid_partial_resolution(resolution):
89
89
  return resolution is not None and bool(re.match(r"x\d{3,4}", resolution))
90
90
 
91
91
 
92
- def get_preview_file_fps(project):
92
+ def get_preview_file_fps(project, entity=None):
93
93
  """
94
94
  Return fps set at project level or default fps if the dimensions are not
95
95
  set.
@@ -97,6 +97,12 @@ def get_preview_file_fps(project):
97
97
  fps = "25.00"
98
98
  if project.get("fps", None) is not None:
99
99
  fps = project["fps"].replace(",", ".")
100
+
101
+ if entity is not None:
102
+ entity_data = entity.get("data", {}) or {}
103
+ if entity_data.get("fps", None) is not None:
104
+ fps = entity_data["fps"].replace(",", ".")
105
+
100
106
  return "%.3f" % float(fps)
101
107
 
102
108
 
@@ -193,7 +199,7 @@ def prepare_and_store_movie(
193
199
  preview_file = set_preview_file_as_broken(preview_file_id)
194
200
  return preview_file
195
201
 
196
- fps = get_preview_file_fps(project)
202
+ fps = get_preview_file_fps(project, entity)
197
203
  (width, height) = get_preview_file_dimensions(project, entity)
198
204
 
199
205
  if normalize:
@@ -619,7 +625,9 @@ def extract_frame_from_preview_file(preview_file, frame_number):
619
625
  else:
620
626
  raise PreviewFileNotFoundException
621
627
 
622
- fps = get_preview_file_fps(project)
628
+ fps = get_preview_file_fps(
629
+ project, get_entity_from_preview_file(preview_file["id"])
630
+ )
623
631
  extracted_frame_path = movie.extract_frame_from_movie(
624
632
  preview_file_path, frame_number, fps
625
633
  )
@@ -650,7 +658,7 @@ def extract_tile_from_preview_file(preview_file):
650
658
  extracted_tile_path = movie.generate_tile(preview_file_path)
651
659
  return extracted_tile_path
652
660
  else:
653
- return WrongParameterException("Preview file is not a movie")
661
+ raise WrongParameterException("Preview file is not a movie")
654
662
 
655
663
 
656
664
  def reset_movie_files_metadata():
@@ -38,7 +38,7 @@ from sqlalchemy import or_
38
38
 
39
39
  def clear_project_cache(project_id):
40
40
  cache.cache.delete_memoized(get_project, project_id)
41
- cache.cache.delete_memoized(get_project_with_relations, project_id)
41
+ cache.cache.delete_memoized(get_project, project_id, True)
42
42
  cache.cache.delete_memoized(get_project_by_name)
43
43
  cache.cache.delete_memoized(open_projects)
44
44
 
@@ -259,21 +259,12 @@ def get_project_raw(project_id):
259
259
 
260
260
 
261
261
  @cache.memoize_function(240)
262
- def get_project(project_id):
262
+ def get_project(project_id, relations=False):
263
263
  """
264
264
  Get project matching given id, as a dict. Raises an exception if project is
265
265
  not found.
266
266
  """
267
- return get_project_raw(project_id).serialize()
268
-
269
-
270
- @cache.memoize_function(240)
271
- def get_project_with_relations(project_id):
272
- """
273
- Get project matching given id, as a dict. Raises an exception if project is
274
- not found.
275
- """
276
- return get_project_raw(project_id).serialize(relations=True)
267
+ return get_project_raw(project_id).serialize(relations=relations)
277
268
 
278
269
 
279
270
  @cache.memoize_function(120)
@@ -487,7 +478,7 @@ def add_metadata_descriptor(
487
478
  field_name=slugify.slugify(name, separator="_"),
488
479
  )
489
480
  except Exception:
490
- raise WrongParameterException
481
+ raise WrongParameterException("Metadata descriptor already exists.")
491
482
  events.emit(
492
483
  "metadata-descriptor:new",
493
484
  {"metadata_descriptor_id": str(descriptor.id)},
@@ -50,7 +50,7 @@ from zou.app.services.exception import (
50
50
 
51
51
  def clear_shot_cache(shot_id):
52
52
  cache.cache.delete_memoized(get_shot, shot_id)
53
- cache.cache.delete_memoized(get_shot_with_relations, shot_id)
53
+ cache.cache.delete_memoized(get_shot, shot_id, True)
54
54
  cache.cache.delete_memoized(get_full_shot, shot_id)
55
55
 
56
56
 
@@ -402,19 +402,13 @@ def get_shot_raw(shot_id):
402
402
 
403
403
 
404
404
  @cache.memoize_function(120)
405
- def get_shot(shot_id):
405
+ def get_shot(shot_id, relations=False):
406
406
  """
407
407
  Return given shot as a dictionary.
408
408
  """
409
- return get_shot_raw(shot_id).serialize(obj_type="Shot")
410
-
411
-
412
- @cache.memoize_function(120)
413
- def get_shot_with_relations(shot_id):
414
- """
415
- Return given shot as a dictionary.
416
- """
417
- return get_shot_raw(shot_id).serialize(obj_type="Shot", relations=True)
409
+ return get_shot_raw(shot_id).serialize(
410
+ obj_type="Shot", relations=relations
411
+ )
418
412
 
419
413
 
420
414
  @cache.memoize_function(120)
@@ -426,7 +420,7 @@ def get_full_shot(shot_id):
426
420
  shots = get_shots_and_tasks({"id": shot_id})
427
421
  if len(shots) > 0:
428
422
  shot = shots[0]
429
- shot.update(get_shot_with_relations(shot_id))
423
+ shot.update(get_shot(shot_id, relations=True))
430
424
  return shot
431
425
  else:
432
426
  raise ShotNotFoundException
@@ -91,13 +91,12 @@ def clear_studio_cache(studio_id):
91
91
  def clear_task_cache(task_id):
92
92
  cache.cache.delete_memoized(get_task, task_id)
93
93
  cache.cache.delete_memoized(get_task, task_id, True)
94
- cache.cache.delete_memoized(get_task_with_relations, task_id)
95
94
 
96
95
 
97
96
  @cache.memoize_function(120)
98
97
  def clear_comment_cache(comment_id):
99
98
  cache.cache.delete_memoized(get_comment, comment_id)
100
- cache.cache.delete_memoized(get_comment_with_relations, comment_id)
99
+ cache.cache.delete_memoized(get_comment, comment_id, True)
101
100
 
102
101
 
103
102
  @cache.memoize_function(120)
@@ -250,14 +249,6 @@ def get_task(task_id, relations=False):
250
249
  return get_task_raw(task_id).serialize(relations=relations)
251
250
 
252
251
 
253
- @cache.memoize_function(120)
254
- def get_task_with_relations(task_id):
255
- """
256
- Get task matching given id as a dictionary.
257
- """
258
- return get_task_raw(task_id).serialize(relations=True)
259
-
260
-
261
252
  def get_task_by_shotgun_id(shotgun_id):
262
253
  """
263
254
  Get task matching given shotgun id as a dictionary.
@@ -396,7 +387,7 @@ def _convert_rows_to_detailed_tasks(rows, relations=False):
396
387
  entity_name,
397
388
  ) = entry
398
389
 
399
- task = get_task_with_relations(str(task_object.id))
390
+ task = get_task(str(task_object.id), relations=relations)
400
391
  task["project_name"] = project_name
401
392
  task["task_type_name"] = task_type_name
402
393
  task["task_status_name"] = task_status_name
@@ -774,21 +765,11 @@ def get_comment_raw(comment_id):
774
765
 
775
766
 
776
767
  @cache.memoize_function(120)
777
- def get_comment(comment_id):
768
+ def get_comment(comment_id, relations=False):
778
769
  """
779
770
  Return comment matching give id as a dict.
780
771
  """
781
- comment = get_comment_raw(comment_id)
782
- return comment.serialize()
783
-
784
-
785
- @cache.memoize_function(120)
786
- def get_comment_with_relations(comment_id):
787
- """
788
- Return comment matching give id as a dict with joins information.
789
- """
790
- comment = get_comment_raw(comment_id)
791
- return comment.serialize(relations=True)
772
+ return get_comment_raw(comment_id).serialize(relations=relations)
792
773
 
793
774
 
794
775
  def get_comment_by_preview_file_id(preview_file_id):
@@ -985,7 +966,7 @@ def get_person_tasks(person_id, projects, is_done=None):
985
966
  except EpisodeNotFoundException:
986
967
  episode_name = "MP"
987
968
 
988
- task_dict = get_task_with_relations(str(task.id))
969
+ task_dict = get_task(str(task.id), relations=True)
989
970
  if entity_type_name == "Sequence" and entity_parent_id is not None:
990
971
  episode_id = entity_parent_id
991
972
  episode = shots_service.get_episode(episode_id)
@@ -1117,7 +1098,7 @@ def get_person_tasks_to_check(project_ids=None, department_ids=None):
1117
1098
  if episode_id is None:
1118
1099
  episode_id = entity_source_id
1119
1100
 
1120
- task_dict = get_task_with_relations(str(task.id))
1101
+ task_dict = get_task(str(task.id), relations=True)
1121
1102
  if entity_type_name == "Sequence" and entity_parent_id is not None:
1122
1103
  episode_id = entity_parent_id
1123
1104
  episode = shots_service.get_episode(episode_id)
@@ -1729,7 +1710,7 @@ def get_tasks_for_project(
1729
1710
 
1730
1711
 
1731
1712
  def get_full_task(task_id, user_id):
1732
- task = get_task_with_relations(task_id)
1713
+ task = get_task(task_id, relations=True)
1733
1714
  task_type = get_task_type(task["task_type_id"])
1734
1715
  project = projects_service.get_project(task["project_id"])
1735
1716
  task_status = get_task_status(task["task_status_id"])
@@ -2054,7 +2035,7 @@ def get_open_tasks(
2054
2035
  except EpisodeNotFoundException:
2055
2036
  episode_name = "MP"
2056
2037
 
2057
- task_dict = get_task_with_relations(str(task.id))
2038
+ task_dict = get_task(str(task.id), relations=True)
2058
2039
  if entity_type_name == "Sequence" and entity_parent_id is not None:
2059
2040
  episode_id = entity_parent_id
2060
2041
  episode = shots_service.get_episode(episode_id)
@@ -410,7 +410,7 @@ def check_belong_to_project(project_id):
410
410
  if project_id is None:
411
411
  return False
412
412
 
413
- project = projects_service.get_project_with_relations(str(project_id))
413
+ project = projects_service.get_project(str(project_id), relations=True)
414
414
  current_user = persons_service.get_current_user()
415
415
  return current_user["id"] in project["team"]
416
416
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zou
3
- Version: 0.19.68
3
+ Version: 0.19.69
4
4
  Summary: API to store and manage the data of your animation production
5
5
  Home-page: https://zou.cg-wire.com
6
6
  Author: CG Wire
@@ -27,7 +27,7 @@ Requires-Dist: click==8.1.7
27
27
  Requires-Dist: discord.py==2.4.0
28
28
  Requires-Dist: email-validator==2.2.0
29
29
  Requires-Dist: ffmpeg-python==0.2.0
30
- Requires-Dist: fido2==1.1.3
30
+ Requires-Dist: fido2==1.2.0
31
31
  Requires-Dist: flasgger==0.9.7.1
32
32
  Requires-Dist: flask_bcrypt==1.0.1
33
33
  Requires-Dist: flask_caching==2.3.0
@@ -41,7 +41,7 @@ Requires-Dist: flask-jwt-extended==4.7.1
41
41
  Requires-Dist: flask-migrate==4.0.7
42
42
  Requires-Dist: flask-socketio==5.4.1
43
43
  Requires-Dist: flask==3.1.0
44
- Requires-Dist: gazu==0.10.19
44
+ Requires-Dist: gazu==0.10.20
45
45
  Requires-Dist: gevent-websocket==0.10.1
46
46
  Requires-Dist: gevent==24.11.1
47
47
  Requires-Dist: gunicorn==23.0.0
@@ -50,7 +50,7 @@ Requires-Dist: itsdangerous==2.2.0
50
50
  Requires-Dist: Jinja2==3.1.4
51
51
  Requires-Dist: ldap3==2.9.1
52
52
  Requires-Dist: matterhook==0.2
53
- Requires-Dist: meilisearch==0.31.6
53
+ Requires-Dist: meilisearch==0.32.0
54
54
  Requires-Dist: numpy==2.0.1; python_version == "3.9"
55
55
  Requires-Dist: numpy==2.1.3; python_version >= "3.10"
56
56
  Requires-Dist: opencv-python==4.10.0.84
@@ -72,7 +72,7 @@ Requires-Dist: rq==2.0.0
72
72
  Requires-Dist: slackclient==2.9.4
73
73
  Requires-Dist: sqlalchemy_utils==0.41.2
74
74
  Requires-Dist: sqlalchemy==2.0.36
75
- Requires-Dist: ua-parser==0.18.0
75
+ Requires-Dist: ua-parser==1.0.0
76
76
  Requires-Dist: werkzeug==3.1.3
77
77
  Provides-Extra: prod
78
78
  Requires-Dist: gunicorn; extra == "prod"
@@ -1,11 +1,11 @@
1
- zou/__init__.py,sha256=HeoiWHiSUydT3-k-xdKv9o6mWVHnrmaEj0pabjfEUyQ,24
1
+ zou/__init__.py,sha256=8Ij1WPLJLGDYnhtjZjijvveSxezbT7WPButvFUQzE2k,24
2
2
  zou/cli.py,sha256=E7rinikQMEAoSzyV4VH2IrTR4HRDBgqHAcYswEfyFnU,18893
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
4
  zou/event_stream.py,sha256=_tue9Ry3aqCniZpKGhWJaY1Eo_fd6zOAfnzPvh_mJzU,8489
5
5
  zou/job_settings.py,sha256=_aqBhujt2Q8sXRWIbgbDf-LUdXRdBimdtTc-fZbiXoY,202
6
6
  zou/app/__init__.py,sha256=AJEGrLTirr5zZmA8DVSjZedtTuDg6eg9rG4kXMimPnQ,6966
7
7
  zou/app/api.py,sha256=JTB_IMVO8EOoyqx9KdRkiIix0chOLi0yGDY-verUJXA,5127
8
- zou/app/config.py,sha256=CR0wvWVF_T0Sfh-AGTphyXnMr0dm_ZVdXUOH3WUTz2s,6646
8
+ zou/app/config.py,sha256=kYbcTVFgcl2sGtf-cpOOVu3_fVh2P1fLcceLjCvsIfc,6700
9
9
  zou/app/mixin.py,sha256=eYwfS_CUFvNmldaQXrjsN5mK_gX0wYrBFykfx60uUM8,4897
10
10
  zou/app/swagger.py,sha256=Jr7zsMqJi0V4FledODOdu-aqqVE02jMFzhqVxHK0_2c,54158
11
11
  zou/app/blueprints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -18,16 +18,16 @@ zou/app/blueprints/breakdown/resources.py,sha256=JY3j17kv7xPKV9S-XoOxNYivpGHlfZk
18
18
  zou/app/blueprints/chats/__init__.py,sha256=YGmwGvddg3MgSYVIh-hmkX8t2em9_LblxBeJzFqFJD4,558
19
19
  zou/app/blueprints/chats/resources.py,sha256=4yLFermdwOsnBLs9nx8yxuHWLar24uQWQy0XgsUNDD0,5950
20
20
  zou/app/blueprints/comments/__init__.py,sha256=WqpJ7-_dK1cInGTFJAxQ7syZtPCotwq2oO20UEnk1h4,1532
21
- zou/app/blueprints/comments/resources.py,sha256=_WoAnnv2uRLbc_fzg6XCeXF06_KNFS08r84YVN858Mc,19423
21
+ zou/app/blueprints/comments/resources.py,sha256=_8OoEl51UWSW5nciqiy3u9ZHztkGg_iuUJ29RhpASkM,19423
22
22
  zou/app/blueprints/concepts/__init__.py,sha256=sP_P4mfYvfMcgeE6MHZYP3eD0Lz0Lwit5-CFuVnA-Jg,894
23
23
  zou/app/blueprints/concepts/resources.py,sha256=maJNrBAWX0bKbDKtOZc3YFp4nTVtIdkkAA4H9WA9n1Y,10140
24
24
  zou/app/blueprints/crud/__init__.py,sha256=qn7xkEh2EG0mPS_RBmm0GgYr0O1jnmI8ymXZnFWZCz8,8361
25
25
  zou/app/blueprints/crud/asset_instance.py,sha256=va3mw79aPKry2m9PYAmjVePTScigewDjwD1c672f0y0,1335
26
26
  zou/app/blueprints/crud/attachment_file.py,sha256=FJA5nKli-9l4p-Mka-tNRNRFil6dNC7QMN3N2MBBN_w,1346
27
- zou/app/blueprints/crud/base.py,sha256=7simulGJtcH1JaWSQCVenxQGD71LPuPL6V9mdOgpsYw,16211
27
+ zou/app/blueprints/crud/base.py,sha256=zg15pERttH7H_tHTq_eMonlaIFwe4vu9H0oFhyoJLpg,15785
28
28
  zou/app/blueprints/crud/chat.py,sha256=Sq1r0y9ANjS113PUpwgAhnjYsxxLKMCM-a7DJ_icF00,344
29
29
  zou/app/blueprints/crud/chat_message.py,sha256=bEEUoV0sNzu5sntNS6fpLh5NC6wWiycWCXtTE-t4yG4,387
30
- zou/app/blueprints/crud/comments.py,sha256=_FOEs2qNqpOqSmAxu8hI3FWK63ik1Uc7PJS3XU5bTLw,8851
30
+ zou/app/blueprints/crud/comments.py,sha256=jEu2x_n6anSplONyOCTRxqPHrw6cJG7FN4Emj7ZB65k,8228
31
31
  zou/app/blueprints/crud/custom_action.py,sha256=zz8E1IgtaV44BGC7m9t7YSQ9t_fYTtoxl_qRn20XijI,992
32
32
  zou/app/blueprints/crud/day_off.py,sha256=hr_cSBG-r7i_an2AkRmgTPtzbwojaI6el_JDUHgBBx4,2571
33
33
  zou/app/blueprints/crud/department.py,sha256=6UVd4OhloboQAHd6vtDjwdTNgx3tf9XyBAcb4IXnmt0,987
@@ -43,7 +43,7 @@ zou/app/blueprints/crud/notification.py,sha256=A-KNH0IDNCXlE4AddNxvmsD_7a9HqHGo_
43
43
  zou/app/blueprints/crud/organisation.py,sha256=DLK0BabSZU2Y4CAoEg5Zkzutb87rCMiyguEC9WdxmoU,873
44
44
  zou/app/blueprints/crud/output_file.py,sha256=tz0NOoEUobNa8RMjl195S6uNP7PsPM-ajMOYWdHUhhE,3968
45
45
  zou/app/blueprints/crud/output_type.py,sha256=Uu7Q5iv-4SZDnxHkLk0vUE1N4k0bBUivXQUTsc58BU8,2012
46
- zou/app/blueprints/crud/person.py,sha256=TmxvZfu143TnjAaRqp8MBJ1bBQFnCPMBeZ_wyiUs7KY,9295
46
+ zou/app/blueprints/crud/person.py,sha256=k1EcYxD5C5p7tquAvJUpD2873-ITeF2ogMNIYRxWuDo,9427
47
47
  zou/app/blueprints/crud/playlist.py,sha256=he8iXoWnjBVXzkB_y8aGnZ6vQ_7hGSf-ALofLFoqx1U,1890
48
48
  zou/app/blueprints/crud/preview_background_file.py,sha256=TRJlVQ3nGOYVkA6kxIlNrip9bjkUaknVNCIUYw8uJYk,2451
49
49
  zou/app/blueprints/crud/preview_file.py,sha256=j5tw7fW4m6QUMTg99cwQlq3yZ5WKHfRuUwRlssBkMDU,3845
@@ -56,7 +56,7 @@ zou/app/blueprints/crud/software.py,sha256=oKFINQh3DcVTd0Ap_cvgsgvhrIbGPjVBKucwk
56
56
  zou/app/blueprints/crud/status_automation.py,sha256=BY846JKmFMpTZBZ0DlWXpQ-LHwCpOwAWU8qekK89yk0,2361
57
57
  zou/app/blueprints/crud/studio.py,sha256=N0JjQ92ilFuPcFsq2WYBeaeeXHyPDXf_-UtSQpSFN4A,951
58
58
  zou/app/blueprints/crud/subscription.py,sha256=xFV_nvRg2ow6E0JWo4VHgeK_SkKX3K8i80thY3qRCl0,392
59
- zou/app/blueprints/crud/task.py,sha256=SpiDqppAbwSGY-fZDqTUYGAQPIBFj20Qlje1kzgKuXo,5743
59
+ zou/app/blueprints/crud/task.py,sha256=7ZMetDs4Z-ZxO0IjyM4y1kmzQUGyLvf0ga6pxZOrNsA,5793
60
60
  zou/app/blueprints/crud/task_status.py,sha256=roRbBJtyoaNrXv5nkVIPLH6K5vdJjGQtiWFvqlfbo9s,1482
61
61
  zou/app/blueprints/crud/task_type.py,sha256=9DUtBaNZqC0yHmunKX_CaUyo-bHjNTX3B-g4zyU5uKc,1815
62
62
  zou/app/blueprints/crud/time_spent.py,sha256=9tfoKJ77OEDTnpKHshO3UMDz_KCoyLq1CWquInm5DY0,3057
@@ -87,7 +87,7 @@ zou/app/blueprints/index/resources.py,sha256=_JiNodmq3-XCIz4vF0MYkkkg1Wdzh7Fl19K
87
87
  zou/app/blueprints/news/__init__.py,sha256=HxBXjC15dVbotNAZ0CLf02iwUjxJr20kgf8_kT_9nwM,505
88
88
  zou/app/blueprints/news/resources.py,sha256=5sN4iHTD3W2SEi1MhVHpeR1OjeTdW-XarkD8tyINLzU,7362
89
89
  zou/app/blueprints/persons/__init__.py,sha256=0cnHHw3K_8OEMm0qOi3wKVomSAg9IJSnVjAXabMeHks,3893
90
- zou/app/blueprints/persons/resources.py,sha256=0EBI6w63WhjqDSj-COYGk4NO6V1oRyAzfH4f7dXNYoE,42793
90
+ zou/app/blueprints/persons/resources.py,sha256=PfK6epzRn_kbqN6g9qYiH9XWStFlccTVCYyKxs72Hu8,42764
91
91
  zou/app/blueprints/playlists/__init__.py,sha256=vuEk1F3hFHsmuKWhdepMoLyOzmNKDn1YrjjfcaIz0lQ,1596
92
92
  zou/app/blueprints/playlists/resources.py,sha256=alRlMHypUFErXLsEYxpFK84cdjFJ3YWwamZtW0KcwLY,17211
93
93
  zou/app/blueprints/previews/__init__.py,sha256=qGohO6LRNZKXBAegINcUXuZlrtxobJKQg84-rQ1L3AU,4202
@@ -97,7 +97,7 @@ zou/app/blueprints/projects/resources.py,sha256=E91Vj9EzId2pxiL50JRfrThiyif1PmzW
97
97
  zou/app/blueprints/search/__init__.py,sha256=QCjQIY_85l_orhdEiqav_GifjReuwsjZggN3V0GeUVY,356
98
98
  zou/app/blueprints/search/resources.py,sha256=_QgRlUuxCPgY-ip5r2lGFtXNcGSE579JsCSrVf8ajVU,3093
99
99
  zou/app/blueprints/shots/__init__.py,sha256=HfgLneZBYUMa2OGwIgEZTz8zrIEYFRiYmRbreBPYeYw,4076
100
- zou/app/blueprints/shots/resources.py,sha256=_Zkxk_XFwuT_b6vWOx9p3VyMuD2PAo-xKJRATsGjPdQ,49965
100
+ zou/app/blueprints/shots/resources.py,sha256=6YUtyDE-auVwm5DTeD84sB9w2R15KnN9wBY4aIKmz2Q,49936
101
101
  zou/app/blueprints/source/__init__.py,sha256=H7K-4TDs4pc5EJvcYTYMJBHesxyqsE5-xq7J8ckOS2g,6093
102
102
  zou/app/blueprints/source/kitsu.py,sha256=4lWdqxaKDzwx-5POAIHIgZ6ODbDMOOVRxaSb_FOLcCk,5012
103
103
  zou/app/blueprints/source/otio.py,sha256=nTXQEauFinPv2QBXziJW83rSrB_qzIbkFQ_qgxbJynA,13419
@@ -159,7 +159,7 @@ zou/app/models/notification.py,sha256=1ODOymGPeB4oxgX_3WhOgIL_Lsz-JR7miDkBS6W8t_
159
159
  zou/app/models/organisation.py,sha256=jVDsS3C3ani0NYeKKMnsnkGzeeQor9jMU1qkHxkSa9c,1938
160
160
  zou/app/models/output_file.py,sha256=hyLGrpsgrk0aisDXppRQrB7ItCwyuyw-X0ZwVAHabsA,2569
161
161
  zou/app/models/output_type.py,sha256=us_lCUCEvuP4vi_XmmOcEl1J2MtZhMX5ZheBqEFCgWA,381
162
- zou/app/models/person.py,sha256=E6Q3KyE4QDon41Fz9sJSCYdR6obqWHtvv2jBOYYFGik,7500
162
+ zou/app/models/person.py,sha256=E6aTbN6HigVTh9_myMfYK6iqrdUfMRB6XBtowdA-qYQ,7511
163
163
  zou/app/models/playlist.py,sha256=YGgAk84u0_fdIEY02Dal4kfk8APVZvWFwWYV74qvrio,1503
164
164
  zou/app/models/preview_background_file.py,sha256=j8LgRmY7INnlB07hFwwB-8ssQrRC8vsb8VcpsTbt6tA,559
165
165
  zou/app/models/preview_file.py,sha256=Ur45Wau2X3qyKULh04EUcMbnBmaQc8y4IMs5NgELiAQ,3134
@@ -179,17 +179,17 @@ zou/app/models/task_type.py,sha256=IsixVAfz3pyMf0eQw8x-uFNM9OHNkZpsPLEz_VNQ0hA,1
179
179
  zou/app/models/time_spent.py,sha256=n7i3FO9g1eE_zATkItoCgrGVqq3iMSfdlKSveEZPloc,795
180
180
  zou/app/models/working_file.py,sha256=q0LM3s1ziw_9AmmPDCkwyf1-TJkWTBMgo2LdHyVRwxg,1509
181
181
  zou/app/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
- zou/app/services/assets_service.py,sha256=J7o1ewK2bevJNjeXyaGp99PH0G5Yxbm2edxfX90R3W0,23716
182
+ zou/app/services/assets_service.py,sha256=ACD9WW7EJ7lCZsUs2klnByuNYf0prhdKBitGKHVpIgE,23556
183
183
  zou/app/services/auth_service.py,sha256=hQpNb21xlr5EiTrXnzpFb4W4GDtglubqA2z_-YIBfnk,22897
184
184
  zou/app/services/backup_service.py,sha256=_ZtZp6wkcVYnHxBosziwLGdrTvsUttXGphiydq53iy8,4840
185
185
  zou/app/services/base_service.py,sha256=OZd0STFh-DyBBdwsmA7DMMnrwv4C8wJUbShvZ1isndU,1383
186
- zou/app/services/breakdown_service.py,sha256=DJvi5muf3WDcTx9vBVrut6sqarCRUzI2B0Qar4lNHYc,27581
186
+ zou/app/services/breakdown_service.py,sha256=-bH1KUq9-No_OKnQtWK4XEU1w7uDPJnzWFMrKNkS1K0,27593
187
187
  zou/app/services/chats_service.py,sha256=pqnT-RCltdf9Dp4t-2NtOSawGk0jyNhVPTgERZ_nYvk,8297
188
- zou/app/services/comments_service.py,sha256=CUr0CZGkR95OrHDRJnhAZAikBLtWhM-5uLIoxI4gNtA,18589
189
- zou/app/services/concepts_service.py,sha256=KGvk6lF5udj3SWn40X9KE8OAigrLCZUKEz9_CW7EMgQ,11440
188
+ zou/app/services/comments_service.py,sha256=3O54dozhw3x4VkYBoLoQPant-A3H1lHBURWluLO9TBE,18590
189
+ zou/app/services/concepts_service.py,sha256=sXzMPQ5Rav-c_36CBxdDBjKNq0-gaLWFY9QZGy3jjv4,11252
190
190
  zou/app/services/custom_actions_service.py,sha256=fWISEOOdthadrxeHuacEel5Xj6msn0yWXJQDG1gzvsY,297
191
191
  zou/app/services/deletion_service.py,sha256=GdPWmw60_EmWxJohvqQ9KRcION7_PIdQgbl7nr2g2mY,17429
192
- zou/app/services/edits_service.py,sha256=KTk5KUJx1yB-mRka8rQXMgQLIcWq4mNYZfnVhVlKwyQ,12122
192
+ zou/app/services/edits_service.py,sha256=lQck7U9JYRWRqukwTT6ZBWCP0BpoF3XlPPwmEgtUvSM,11965
193
193
  zou/app/services/emails_service.py,sha256=HaSdDzNLU-s_fxoH-YQi-3VFX1YwdYm64kMhJFGa3AM,11923
194
194
  zou/app/services/entities_service.py,sha256=HDl_KqS5aZEUyAkrgsQ11qqYiaFFy0VcD2BrSaOrxJg,16436
195
195
  zou/app/services/events_service.py,sha256=_gU19herxiAo47WRxVNhvl7v-RKhp-8wZ3gAiHKpOzI,2716
@@ -200,20 +200,20 @@ zou/app/services/index_service.py,sha256=1w8rGJ7ArYC13B43hD4JOPtVhaRsbseJVVY-GnU
200
200
  zou/app/services/names_service.py,sha256=TOSrintROmxcAlcFQE0i2E3PBLnw81GAztNselpTn18,2947
201
201
  zou/app/services/news_service.py,sha256=Wq262gOPP4EThXXcpT9o0QW8Z3lDQuPV6It-7IEzA5U,9116
202
202
  zou/app/services/notifications_service.py,sha256=7GDRio_mGaRYV5BHOAdpxBZjA_LLYUfVpbwZqy1n9pI,15685
203
- zou/app/services/persons_service.py,sha256=0CKYrmHDUq34VNNgLSWDKN37EgmD68ZqyrUmm4ABj18,16356
203
+ zou/app/services/persons_service.py,sha256=pdyEyIGojuk_gl67sxX7SXoTwPZQbLqHHmj53iourPg,16472
204
204
  zou/app/services/playlists_service.py,sha256=pAlPHET4jNdST5jsmJrFUkf1SVhfSoML9zdNpZ_88l4,32439
205
- zou/app/services/preview_files_service.py,sha256=M1kXryARUKwCDXsr0hOfUUyGn75y-qXIVIwlMOKWWHs,35609
206
- zou/app/services/projects_service.py,sha256=_J8hIHy3MX5MsdEMRIKNfbyewwhxtMEcc_ymeHBsF38,21434
205
+ zou/app/services/preview_files_service.py,sha256=LEBZbLBJOLDLB7syKql5B8a_p1HFHToMi7nKaUxOCb8,35881
206
+ zou/app/services/projects_service.py,sha256=2m-w_HaWR06gy8jL8gO-sToHhGdeCakG4hTKKYsLJKk,21249
207
207
  zou/app/services/scenes_service.py,sha256=iXN19HU4njPF5VtZXuUrVJ-W23ZQuQNPC3ADXltbWtU,992
208
208
  zou/app/services/schedule_service.py,sha256=E99HKYsXgnK2sw58fw-NNHXWBgVJiA60upztjkNSCaM,6989
209
- zou/app/services/shots_service.py,sha256=dJGG6_8P8_RwqT7r2kv776xXzgNPyJ-RqLyFQuwgAnY,52196
209
+ zou/app/services/shots_service.py,sha256=lJViWy9IbB1YOZB9HyyGAyMc1HW9y5qPEA1EefANTek,52040
210
210
  zou/app/services/stats_service.py,sha256=cAlc92i9d6eYtsuwe3hYHYwdytg8KEMi1-TADfysJwM,11733
211
211
  zou/app/services/status_automations_service.py,sha256=tVio7Sj7inhvKS4UOyRhcdpwr_KNP96hT1o0X7XcGF4,715
212
212
  zou/app/services/sync_service.py,sha256=EunfXlma_IIb7011A_xLQLVQGAi-MteKgm2Y2NAxvMs,41586
213
- zou/app/services/tasks_service.py,sha256=IoogHBoZhbJegnl5SYGgOaBp2YVqrL22Gccjfp8dPn8,69335
213
+ zou/app/services/tasks_service.py,sha256=bhm13XcROOnEhlDa3xhFyIzf6bQmrLrOepUW2av7BDU,68844
214
214
  zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6pQ-ytRbmGA,1029
215
215
  zou/app/services/time_spents_service.py,sha256=H9X-60s6oqtY9rtU-K2jKwUSljfkdGlf_9wMr3iVfIA,15158
216
- zou/app/services/user_service.py,sha256=sIl9PE2hX2EfKiRV8YqL3ZrHNulzeL9y960LF4BuZbs,50528
216
+ zou/app/services/user_service.py,sha256=yRWztH9ub-_wTOekKm1By3RBTVI5QiBFZq0DKSze8sQ,50529
217
217
  zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
218
  zou/app/stores/auth_tokens_store.py,sha256=-qOJPybLHvnMOq3PWk073OW9HJwOHGhFLZeOIlX1UVw,1290
219
219
  zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
@@ -413,9 +413,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
413
413
  zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
414
414
  zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
415
415
  zou/utils/movie.py,sha256=d67fIL9dVBKt-E_qCGXRbNNdbJaJR5sHvZeX3hf8ldE,16559
416
- zou-0.19.68.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
417
- zou-0.19.68.dist-info/METADATA,sha256=KcDj-VP0E8-knTHPIuYFUELR0GW-uX58lSxva26OyIU,6710
418
- zou-0.19.68.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
419
- zou-0.19.68.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
420
- zou-0.19.68.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
421
- zou-0.19.68.dist-info/RECORD,,
416
+ zou-0.19.69.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
417
+ zou-0.19.69.dist-info/METADATA,sha256=GU1IQpKI98mO9vSrRvgdssUlE51lW7xK-GfmB95Ux68,6709
418
+ zou-0.19.69.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
419
+ zou-0.19.69.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
420
+ zou-0.19.69.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
421
+ zou-0.19.69.dist-info/RECORD,,
File without changes
File without changes