zou 0.20.47__py3-none-any.whl → 0.20.49__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.20.47"
1
+ __version__ = "0.20.49"
@@ -6,6 +6,7 @@ from sqlalchemy.exc import IntegrityError, StatementError
6
6
  from zou.app.models.preview_file import PreviewFile
7
7
  from zou.app.models.task import Task
8
8
  from zou.app.models.project import Project
9
+ from zou.app.models.project_status import ProjectStatus
9
10
  from zou.app.services import (
10
11
  user_service,
11
12
  tasks_service,
@@ -21,19 +22,22 @@ class PreviewFilesResource(BaseModelsResource):
21
22
  BaseModelsResource.__init__(self, PreviewFile)
22
23
 
23
24
  def add_project_permission_filter(self, query):
24
- if permissions.has_vendor_permissions():
25
- query = (
26
- query.join(Task)
27
- .filter(user_service.build_assignee_filter())
28
- .filter(user_service.build_open_project_filter())
29
- )
30
- elif not permissions.has_admin_permissions():
25
+ if not permissions.has_admin_permissions():
31
26
  query = (
32
27
  query.join(Task)
33
28
  .join(Project)
34
- .filter(user_service.build_related_projects_filter())
29
+ .join(
30
+ ProjectStatus,
31
+ Project.project_status_id == ProjectStatus.id,
32
+ )
35
33
  .filter(user_service.build_open_project_filter())
36
34
  )
35
+ if permissions.has_vendor_permissions():
36
+ query = query.filter(user_service.build_assignee_filter())
37
+ else:
38
+ query = query.filter(
39
+ user_service.build_related_projects_filter()
40
+ )
37
41
 
38
42
  return query
39
43
 
@@ -1509,20 +1509,20 @@ class ProductionMonthTimeSpentsResource(Resource, ArgsMixin):
1509
1509
  - Projects
1510
1510
  parameters:
1511
1511
  - in: path
1512
- name: project_id
1513
- required: True
1514
- type: string
1515
- format: UUID
1516
- x-example: a24a6ea4-ce75-4665-a070-57453082c25
1512
+ name: project_id
1513
+ required: True
1514
+ type: string
1515
+ format: UUID
1516
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1517
1517
  responses:
1518
- 200:
1519
- description: Aggregated time spents for given person and month
1520
- 400:
1521
- description: Wrong ID format
1518
+ 200:
1519
+ description: Aggregated time spents for given person and month
1520
+ 400:
1521
+ description: Wrong ID format
1522
1522
  """
1523
1523
  permissions.check_admin_permissions()
1524
1524
  self.check_id_parameter(project_id)
1525
1525
  user = persons_service.get_current_user()
1526
1526
  return time_spents_service.get_project_month_time_spents(
1527
1527
  project_id, user["timezone"]
1528
- )
1528
+ )
@@ -313,7 +313,7 @@ def remove_tasks(project_id, task_ids):
313
313
  filter is there to facilitate right management.
314
314
  """
315
315
  task_ids = [task_id for task_id in task_ids if fields.is_valid_id(task_id)]
316
- tasks = Task.query.filter(Project.id == project_id).filter(
316
+ tasks = Task.query.filter(Task.project_id == project_id).filter(
317
317
  Task.id.in_(task_ids)
318
318
  )
319
319
  for task in tasks:
@@ -140,6 +140,21 @@ def update_entity_preview(entity_id, preview_file_id):
140
140
  return entity.serialize()
141
141
 
142
142
 
143
+ def get_for_entity_from_task(task):
144
+ """
145
+ Return the entity type name for given task. All asset types are returned
146
+ as "Asset".
147
+ """
148
+ entity = get_entity(task["entity_id"])
149
+ entity_type = get_entity_type(entity["entity_type_id"])
150
+ for_entity = entity_type["name"]
151
+ if for_entity.lower() not in [
152
+ "shot", "sequence", "episode", "edit", "concept"
153
+ ]:
154
+ for_entity = "Asset"
155
+ return for_entity
156
+
157
+
143
158
  def get_entities_for_project(
144
159
  project_id,
145
160
  entity_type_id,
@@ -820,9 +820,19 @@ def generate_temp_playlist(task_ids, sort=True):
820
820
  persist anything. The goal is to build a temporary playlist used to see
821
821
  a quick preview of several shots.
822
822
  """
823
+ if len(task_ids) == 0:
824
+ return []
825
+
826
+ task_id = task_ids[0]
827
+ task = tasks_service.get_task(task_id)
828
+ for_entity = entities_service.get_for_entity_from_task(task)
829
+ task_type_links = projects_service.get_task_type_links(
830
+ task["project_id"], for_entity
831
+ )
823
832
  entities = []
833
+
824
834
  for task_id in task_ids:
825
- entity = generate_playlisted_entity_from_task(task_id)
835
+ entity = generate_playlisted_entity_from_task(task_id, task_type_links)
826
836
  entities.append(entity)
827
837
  if len(entities) > 0:
828
838
  if not sort:
@@ -846,15 +856,13 @@ def generate_temp_playlist(task_ids, sort=True):
846
856
  return []
847
857
 
848
858
 
849
- def generate_playlisted_entity_from_task(task_id):
859
+ def generate_playlisted_entity_from_task(task_id, task_type_links):
850
860
  """
851
861
  Generate the data structure of a playlisted shot for a given task. It
852
862
  doesn't persist anything.
853
863
  """
854
864
  task = tasks_service.get_task(task_id)
855
- task = tasks_service.get_task(task_id)
856
865
  entity = entities_service.get_entity(task["entity_id"])
857
- task = tasks_service.get_task(task_id)
858
866
  if shots_service.is_shot(entity):
859
867
  playlisted_entity = get_base_shot_for_playlist(entity, task_id)
860
868
  elif shots_service.is_sequence(entity):
@@ -866,8 +874,22 @@ def generate_playlisted_entity_from_task(task_id):
866
874
 
867
875
  task_type_id = task["task_type_id"]
868
876
  preview_files = get_preview_files_for_entity(entity["id"])
877
+
878
+ preview_file = None
869
879
  if task_type_id in preview_files and len(preview_files[task_type_id]) > 0:
870
880
  preview_file = preview_files[task_type_id][0]
881
+
882
+ if preview_file is None and len(preview_files.keys()) > 0:
883
+ available_task_types = [
884
+ link["task_type_id"]
885
+ for link in task_type_links
886
+ if link["task_type_id"] in preview_files
887
+ ]
888
+ if len(available_task_types) > 0:
889
+ task_type_id = available_task_types[0]
890
+ preview_file = preview_files[ task_type_id][0]
891
+
892
+ if preview_file is not None:
871
893
  playlisted_entity.update(
872
894
  {
873
895
  "preview_file_id": preview_file["id"],
@@ -877,7 +899,7 @@ def generate_playlisted_entity_from_task(task_id):
877
899
  "preview_file_duration": preview_file["duration"],
878
900
  "preview_file_revision": preview_file["revision"],
879
901
  "preview_file_status": preview_file["status"],
880
- "preview_file_annotations": preview_file["annotations"],
902
+ "preview_file_annotations": preview_file["annotations"] or [],
881
903
  "preview_file_previews": preview_file["previews"],
882
904
  }
883
905
  )
@@ -555,7 +555,7 @@ def get_running_preview_files():
555
555
  entries = (
556
556
  PreviewFile.query.join(Task)
557
557
  .join(Project)
558
- .join(ProjectStatus)
558
+ .join(ProjectStatus, ProjectStatus.id == Project.project_status_id)
559
559
  .filter(ProjectStatus.name.in_(("Active", "open", "Open")))
560
560
  .filter(PreviewFile.status.in_(("broken", "processing")))
561
561
  .add_columns(Task.project_id, Task.task_type_id, Task.entity_id)
@@ -668,7 +668,7 @@ def reset_movie_files_metadata():
668
668
  preview_files = (
669
669
  PreviewFile.query.join(Task)
670
670
  .join(Project)
671
- .join(ProjectStatus)
671
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
672
672
  .filter(ProjectStatus.name.in_(("Active", "open", "Open")))
673
673
  .filter(PreviewFile.status.not_in(("broken", "processing")))
674
674
  .filter(PreviewFile.extension == "mp4")
@@ -711,7 +711,7 @@ def reset_picture_files_metadata():
711
711
  preview_files = (
712
712
  PreviewFile.query.join(Task)
713
713
  .join(Project)
714
- .join(ProjectStatus)
714
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
715
715
  .filter(ProjectStatus.name.in_(("Active", "open", "Open")))
716
716
  .filter(PreviewFile.status.not_in(("broken", "processing")))
717
717
  .filter(PreviewFile.extension == "png")
@@ -765,7 +765,7 @@ def generate_preview_extra(
765
765
  PreviewFile.query.join(Task)
766
766
  .join(Entity)
767
767
  .join(Project)
768
- .join(ProjectStatus)
768
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
769
769
  .filter(ProjectStatus.name.in_(("Active", "open", "Open")))
770
770
  .filter(PreviewFile.status.not_in(("broken", "processing")))
771
771
  .filter(PreviewFile.extension.in_(("mp4", "png")))
@@ -49,7 +49,9 @@ def open_projects(name=None):
49
49
  Return all open projects. Allow to filter projects by name.
50
50
  """
51
51
  query = (
52
- Project.query.join(ProjectStatus)
52
+ Project.query.join(
53
+ ProjectStatus, Project.project_status_id == ProjectStatus.id
54
+ )
53
55
  .outerjoin(MetadataDescriptor)
54
56
  .filter(ProjectStatus.name.in_(("Active", "open", "Open")))
55
57
  .order_by(Project.name)
@@ -163,7 +165,9 @@ def get_projects():
163
165
  Return all projects. Allow to filter projects by name.
164
166
  """
165
167
  query = (
166
- Project.query.join(ProjectStatus)
168
+ Project.query.join(
169
+ ProjectStatus, Project.project_status_id == ProjectStatus.id
170
+ )
167
171
  .add_columns(ProjectStatus.name)
168
172
  .order_by(Project.name)
169
173
  )
@@ -696,6 +700,20 @@ def get_task_type_priority_map(project_id, for_entity="Asset"):
696
700
  }
697
701
 
698
702
 
703
+ def get_task_type_links(project_id, for_entity="Asset"):
704
+ """
705
+ Return a lisk of links for given project and entity type.
706
+ """
707
+ task_type_links = (
708
+ ProjectTaskTypeLink.query
709
+ .join(TaskType)
710
+ .filter(ProjectTaskTypeLink.project_id == project_id)
711
+ .filter(TaskType.for_entity == for_entity)
712
+ .order_by(ProjectTaskTypeLink.priority.desc())
713
+ ).all()
714
+ return ProjectTaskTypeLink.serialize_list(task_type_links)
715
+
716
+
699
717
  def get_department_team(project_id, department_id):
700
718
  persons = (
701
719
  Person.query.join(
@@ -545,8 +545,7 @@ def get_project_month_time_spents(project_id, timezone=None):
545
545
  """
546
546
  data = {}
547
547
  query = (
548
- TimeSpent.query
549
- .join(Task)
548
+ TimeSpent.query.join(Task)
550
549
  .join(TaskType, TaskType.id == Task.task_type_id)
551
550
  .join(Department, Department.id == TaskType.department_id)
552
551
  .filter(Task.project_id == project_id)
@@ -559,15 +558,17 @@ def get_project_month_time_spents(project_id, timezone=None):
559
558
  time_spent.date, timezone
560
559
  )[0:7]
561
560
  if department_id not in data:
562
- data[department_id] = { "total": 0 }
561
+ data[department_id] = {"total": 0}
563
562
  if time_spent.person_id not in data[department_id]:
564
- data[department_id][time_spent.person_id] = { "total": 0 }
563
+ data[department_id][time_spent.person_id] = {"total": 0}
565
564
  if date_key not in data[department_id][time_spent.person_id]:
566
565
  data[department_id][time_spent.person_id][date_key] = 0
567
566
 
568
- data[department_id][time_spent.person_id][date_key] += \
569
- time_spent.duration
567
+ data[department_id][time_spent.person_id][
568
+ date_key
569
+ ] += time_spent.duration
570
570
  data[department_id]["total"] += time_spent.duration
571
- data[department_id][time_spent.person_id]["total"] += \
572
- time_spent.duration
573
- return data
571
+ data[department_id][time_spent.person_id][
572
+ "total"
573
+ ] += time_spent.duration
574
+ return data
@@ -86,7 +86,9 @@ def build_related_projects_filter():
86
86
  is part of the team.
87
87
  """
88
88
  projects = (
89
- Project.query.join(ProjectStatus)
89
+ Project.query.join(
90
+ ProjectStatus, Project.project_status_id == ProjectStatus.id
91
+ )
90
92
  .filter(build_team_filter())
91
93
  .filter(build_open_project_filter())
92
94
  .all()
@@ -105,7 +107,7 @@ def related_projects():
105
107
  """
106
108
  projects = (
107
109
  Project.query.join(Task)
108
- .join(ProjectStatus)
110
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
109
111
  .filter(build_team_filter())
110
112
  .filter(build_open_project_filter())
111
113
  .all()
@@ -158,7 +160,7 @@ def get_tasks_for_entity(entity_id):
158
160
  """
159
161
  query = (
160
162
  Task.query.join(Project)
161
- .join(ProjectStatus)
163
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
162
164
  .filter(Task.entity_id == entity_id)
163
165
  .filter(build_assignee_filter())
164
166
  .filter(build_open_project_filter())
@@ -175,7 +177,7 @@ def get_task_types_for_entity(entity_id):
175
177
  query = (
176
178
  TaskType.query.join(Task)
177
179
  .join(Project)
178
- .join(ProjectStatus)
180
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
179
181
  .filter(Task.entity_id == entity_id)
180
182
  .filter(build_assignee_filter())
181
183
  .filter(build_open_project_filter())
@@ -193,7 +195,7 @@ def get_assets_for_asset_type(project_id, asset_type_id):
193
195
  Entity.query.join(EntityType)
194
196
  .join(Project)
195
197
  .join(Task, Task.entity_id == Entity.id)
196
- .join(ProjectStatus)
198
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
197
199
  .filter(EntityType.id == asset_type_id)
198
200
  .filter(Project.id == project_id)
199
201
  .filter(build_assignee_filter())
@@ -212,7 +214,7 @@ def get_asset_types_for_project(project_id):
212
214
  EntityType.query.join(Entity, Entity.entity_type_id == EntityType.id)
213
215
  .join(Task, Task.entity_id == Entity.id)
214
216
  .join(Project)
215
- .join(ProjectStatus)
217
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
216
218
  .filter(Project.id == project_id)
217
219
  .filter(build_assignee_filter())
218
220
  .filter(build_open_project_filter())
@@ -236,7 +238,7 @@ def get_sequences_for_project(project_id):
236
238
  .join(Task, Task.entity_id == Shot.id)
237
239
  .join(EntityType, EntityType.id == Entity.entity_type_id)
238
240
  .join(Project, Project.id == Entity.project_id)
239
- .join(ProjectStatus)
241
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
240
242
  .filter(Shot.entity_type_id == shot_type["id"])
241
243
  .filter(Entity.entity_type_id == sequence_type["id"])
242
244
  .filter(Project.id == project_id)
@@ -263,7 +265,7 @@ def get_project_episodes(project_id):
263
265
  .join(Shot, Shot.parent_id == Sequence.id)
264
266
  .join(Task, Task.entity_id == Shot.id)
265
267
  .join(Project, Project.id == Entity.project_id)
266
- .join(ProjectStatus)
268
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
267
269
  .filter(Shot.entity_type_id == shot_type["id"])
268
270
  .filter(Sequence.entity_type_id == sequence_type["id"])
269
271
  .filter(Entity.entity_type_id == episode_type["id"])
@@ -283,7 +285,7 @@ def get_shots_for_sequence(sequence_id):
283
285
  query = (
284
286
  Entity.query.join(Task)
285
287
  .join(Project)
286
- .join(ProjectStatus)
288
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
287
289
  .join(EntityType)
288
290
  .filter(Entity.entity_type_id == shot_type["id"])
289
291
  .filter(Entity.parent_id == sequence_id)
@@ -303,7 +305,7 @@ def get_scenes_for_sequence(sequence_id):
303
305
  query = (
304
306
  Entity.query.join(Task)
305
307
  .join(Project)
306
- .join(ProjectStatus)
308
+ .join(ProjectStatus, Project.project_status_id == ProjectStatus.id)
307
309
  .join(EntityType)
308
310
  .filter(Entity.entity_type_id == scene_type["id"])
309
311
  .filter(Entity.parent_id == sequence_id)
@@ -318,9 +320,9 @@ def get_open_projects(name=None):
318
320
  """
319
321
  Get all open projects for which current user is part of the team.
320
322
  """
321
- query = Project.query.join(ProjectStatus).filter(
322
- build_open_project_filter()
323
- )
323
+ query = Project.query.join(
324
+ ProjectStatus, Project.project_status_id == ProjectStatus.id
325
+ ).filter(build_open_project_filter())
324
326
 
325
327
  if name is not None:
326
328
  query = query.filter(Project.name == name)
@@ -353,7 +355,9 @@ def get_projects(name=None):
353
355
  """
354
356
  Get all projects for which current user has a task assigned.
355
357
  """
356
- query = Project.query.join(ProjectStatus).filter(build_team_filter())
358
+ query = Project.query.join(
359
+ ProjectStatus, Project.project_status_id == ProjectStatus.id
360
+ ).filter(build_team_filter())
357
361
 
358
362
  if name is not None:
359
363
  query = query.filter(Project.name == name)
zou/app/utils/fido.py CHANGED
@@ -1,5 +1,3 @@
1
- import fido2.features
2
-
3
1
  from fido2.webauthn import (
4
2
  PublicKeyCredentialRpEntity,
5
3
  )
@@ -8,8 +6,6 @@ from urllib.parse import urlparse
8
6
 
9
7
  from zou.app import config
10
8
 
11
- fido2.features.webauthn_json_mapping.enabled = True
12
-
13
9
 
14
10
  def get_fido_server():
15
11
  return Fido2Server(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zou
3
- Version: 0.20.47
3
+ Version: 0.20.49
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
@@ -11,7 +11,6 @@ Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Environment :: Web Environment
12
12
  Classifier: Framework :: Flask
13
13
  Classifier: Intended Audience :: Developers
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
@@ -19,14 +18,14 @@ Classifier: Programming Language :: Python :: 3.13
19
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
19
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
20
  Classifier: Topic :: Multimedia :: Graphics
22
- Requires-Python: >=3.9, <3.14
21
+ Requires-Python: >=3.10, <3.14
23
22
  License-File: LICENSE
24
23
  Requires-Dist: babel==2.17.0
25
- Requires-Dist: click==8.1.8
24
+ Requires-Dist: click==8.2.1
26
25
  Requires-Dist: discord.py==2.5.2
27
26
  Requires-Dist: email-validator==2.2.0
28
27
  Requires-Dist: ffmpeg-python==0.2.0
29
- Requires-Dist: fido2==1.2.0
28
+ Requires-Dist: fido2==2.0.0
30
29
  Requires-Dist: flasgger==0.9.7.1
31
30
  Requires-Dist: flask_bcrypt==1.0.1
32
31
  Requires-Dist: flask_caching==2.3.1
@@ -35,7 +34,7 @@ Requires-Dist: flask_mail==0.10.0
35
34
  Requires-Dist: flask_principal==0.4.0
36
35
  Requires-Dist: flask_restful==0.3.10
37
36
  Requires-Dist: flask_sqlalchemy==3.1.1
38
- Requires-Dist: flask-fs2[s3,swift]==0.7.29
37
+ Requires-Dist: flask-fs2[s3,swift]==0.7.30
39
38
  Requires-Dist: flask-jwt-extended==4.7.1
40
39
  Requires-Dist: flask-migrate==4.1.0
41
40
  Requires-Dist: flask-socketio==5.5.1
@@ -50,8 +49,7 @@ Requires-Dist: Jinja2==3.1.6
50
49
  Requires-Dist: ldap3==2.9.1
51
50
  Requires-Dist: matterhook==0.2
52
51
  Requires-Dist: meilisearch==0.34.1
53
- Requires-Dist: numpy==2.0.1; python_version == "3.9"
54
- Requires-Dist: numpy==2.2.6; python_version >= "3.10"
52
+ Requires-Dist: numpy==2.2.6
55
53
  Requires-Dist: opencv-python==4.11.0.86
56
54
  Requires-Dist: OpenTimelineIO==0.17.0
57
55
  Requires-Dist: OpenTimelineIO-Plugins==0.17.0
@@ -1,4 +1,4 @@
1
- zou/__init__.py,sha256=d3ifraY4SFtace5KlJP00nLQYi316cHYzwCge7c-x3s,24
1
+ zou/__init__.py,sha256=8zjL4DM-xDptth0AESJ4xE-_uFVqjb3qAzKsSTTBUCc,24
2
2
  zou/cli.py,sha256=8YdBqJKEulAZ_1ohTdmpt_lf8EMjDmYiH8l0jVNlfG0,22397
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
4
  zou/event_stream.py,sha256=yTU1Z3r55SiYm8Y5twtJIo5kTnhbBK-XKc8apdgvzNw,8291
@@ -49,7 +49,7 @@ zou/app/blueprints/crud/person.py,sha256=Ot1lTdMRm7BWaOuuTGGm-vrT9SlTlLueOJKR8aE
49
49
  zou/app/blueprints/crud/playlist.py,sha256=he8iXoWnjBVXzkB_y8aGnZ6vQ_7hGSf-ALofLFoqx1U,1890
50
50
  zou/app/blueprints/crud/plugin.py,sha256=azDWurAX8KUD4FXwhCpo8q0qRUVG8TG4Dg8oib1aOzc,356
51
51
  zou/app/blueprints/crud/preview_background_file.py,sha256=TRJlVQ3nGOYVkA6kxIlNrip9bjkUaknVNCIUYw8uJYk,2451
52
- zou/app/blueprints/crud/preview_file.py,sha256=0-1Zv62xDY5JM54P1iac1mPm-tC4NsbAEgbQZaPYLBw,3899
52
+ zou/app/blueprints/crud/preview_file.py,sha256=c-WTDdSbeXmlQalW0s0bTTgixD-tvfV0KiKg1Lc0e6c,4047
53
53
  zou/app/blueprints/crud/project.py,sha256=g8kWGzgWyVk7s6Y-41DRAGjIegxS36W4SbP1FMJTQDM,8428
54
54
  zou/app/blueprints/crud/project_status.py,sha256=XIiIsAfaD5sLZA6wT3UL4FZQpnoOcqPzYfFIWrp9Svs,540
55
55
  zou/app/blueprints/crud/salary_scale.py,sha256=CLvY6DJhSaOZnSqzyLwrEmqRb7Hru2qDC4iB0bKM168,2436
@@ -97,7 +97,7 @@ zou/app/blueprints/playlists/resources.py,sha256=mF3gmlWpe9YKyyKVRUXYtvTCk7OguWI
97
97
  zou/app/blueprints/previews/__init__.py,sha256=ihC6OQ9AUjnZ2JeMnjRh_tKGO0UmAjOwhZnOivc3BnQ,4460
98
98
  zou/app/blueprints/previews/resources.py,sha256=uyjfW3vyE2a1PPXO8MsHP8-3jhuVKHt3oi2pYsq-ZIw,53376
99
99
  zou/app/blueprints/projects/__init__.py,sha256=KhzIn5HvemfvsP5yJBMImdsEuTA_P806kRpoNbAdfIs,4643
100
- zou/app/blueprints/projects/resources.py,sha256=7WAJU0Y7-IzDvsybsPk826yGEQZA84nbGy0xfn-_d8g,44955
100
+ zou/app/blueprints/projects/resources.py,sha256=Z0UfzCzP9n8YBIH4_2cFaP9tIHCn-jQI7NqtQouCTiY,44938
101
101
  zou/app/blueprints/search/__init__.py,sha256=QCjQIY_85l_orhdEiqav_GifjReuwsjZggN3V0GeUVY,356
102
102
  zou/app/blueprints/search/resources.py,sha256=_QgRlUuxCPgY-ip5r2lGFtXNcGSE579JsCSrVf8ajVU,3093
103
103
  zou/app/blueprints/shots/__init__.py,sha256=EcG9qmAchlucqg1M6-RqWGfuKpa5Kq6RgyLZNSsjUr4,4225
@@ -197,10 +197,10 @@ zou/app/services/chats_service.py,sha256=pqnT-RCltdf9Dp4t-2NtOSawGk0jyNhVPTgERZ_
197
197
  zou/app/services/comments_service.py,sha256=C2XL11EAnd2ZC1A8RJ-NRgQ0QeinUkqCjggm97ZXuEE,18789
198
198
  zou/app/services/concepts_service.py,sha256=sXzMPQ5Rav-c_36CBxdDBjKNq0-gaLWFY9QZGy3jjv4,11252
199
199
  zou/app/services/custom_actions_service.py,sha256=fWISEOOdthadrxeHuacEel5Xj6msn0yWXJQDG1gzvsY,297
200
- zou/app/services/deletion_service.py,sha256=GdPWmw60_EmWxJohvqQ9KRcION7_PIdQgbl7nr2g2mY,17429
200
+ zou/app/services/deletion_service.py,sha256=jZzNzyfmKJK1Sro9PUV0v9cVh6QQ2qh-0bQ4Ajuk77I,17434
201
201
  zou/app/services/edits_service.py,sha256=P3-eBoHSikYjtuHeulTv_WuILEe502sU4qFObfokcQY,12114
202
202
  zou/app/services/emails_service.py,sha256=i9EP3zw02ZteVt9OZTvkfaoU19_T4kLhRmrhIvYw2SQ,11965
203
- zou/app/services/entities_service.py,sha256=c-AnoHkro_Bw-6156m85qg96VpdI6Ox-sv0xL1d_TTU,16903
203
+ zou/app/services/entities_service.py,sha256=SbLET7DmyrGzUe-R5T3sEWHW61jDtckHXINj3BgEJy8,17340
204
204
  zou/app/services/events_service.py,sha256=Ew-bY5hqrWLmpbVj1_xd3E2S3JtyAGzdgw2XjudTZjc,2700
205
205
  zou/app/services/exception.py,sha256=miD3RCXUgGezLvm2hqZfNqGEdodybu1TTLifPKgb5-E,4349
206
206
  zou/app/services/file_tree_service.py,sha256=8JNBDgnXtV-AmSJ3gnUGB4oSwLjPgi1WYyL0Kc98JRE,33875
@@ -210,10 +210,10 @@ zou/app/services/names_service.py,sha256=TOSrintROmxcAlcFQE0i2E3PBLnw81GAztNselp
210
210
  zou/app/services/news_service.py,sha256=eOXkvLhOcgncI2NrgiJEccV28oxZX5CsZVqaE-l4kWQ,9084
211
211
  zou/app/services/notifications_service.py,sha256=7GDRio_mGaRYV5BHOAdpxBZjA_LLYUfVpbwZqy1n9pI,15685
212
212
  zou/app/services/persons_service.py,sha256=HjV-su80Y2BO9l5zoBKHMNF0mDGtkWqPhEOs3nQ3nlI,16566
213
- zou/app/services/playlists_service.py,sha256=OCq6CD9XSzH99Eipie8gyEBo8BAGQp2wEMbYKqHS9vw,32496
213
+ zou/app/services/playlists_service.py,sha256=Z0EDxKCH9Widi3-Bx8svpQaRtreXKizzrL9wZq-YXjs,33182
214
214
  zou/app/services/plugins_service.py,sha256=dbU-2f7t3eo6VISQBsASM8Or4Y8ha6Vt8ZHgtizdOi0,1917
215
- zou/app/services/preview_files_service.py,sha256=Yk-vwzHuKTzNkEZfl9DhQRdDuRU006uwZxJ-RKajEkI,35842
216
- zou/app/services/projects_service.py,sha256=aIbYaFomy7OX2Pxvkf9w5qauDvkjuc9ummSGNYIpQMY,21249
215
+ zou/app/services/preview_files_service.py,sha256=673xVNvyK2LoMqWZ6b-g6n1krXOPFVFUh2wonDNLyck,36030
216
+ zou/app/services/projects_service.py,sha256=ayJBDbw9kuxuU5a2SQVnVquB3Ja0f0VPsG_AqpK27dc,21849
217
217
  zou/app/services/scenes_service.py,sha256=iXN19HU4njPF5VtZXuUrVJ-W23ZQuQNPC3ADXltbWtU,992
218
218
  zou/app/services/schedule_service.py,sha256=E99HKYsXgnK2sw58fw-NNHXWBgVJiA60upztjkNSCaM,6989
219
219
  zou/app/services/shots_service.py,sha256=MfBvw0hhVwi_KSQVnM-V4O3LnNkJB2imJWF6n9J6xfc,54747
@@ -222,8 +222,8 @@ zou/app/services/status_automations_service.py,sha256=tVio7Sj7inhvKS4UOyRhcdpwr_
222
222
  zou/app/services/sync_service.py,sha256=iWxx1kOGEXympHmSBBQWtDZWNtumdxp8kppee0OefMo,41811
223
223
  zou/app/services/tasks_service.py,sha256=D-u-8W3rIg00Nqp7MuG1WSOcPANE4XXliKpVwm5NbVU,69815
224
224
  zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6pQ-ytRbmGA,1029
225
- zou/app/services/time_spents_service.py,sha256=sjyDqQKDpnmDm-lPLCd2FxYBE6pOVZEgommwZcAjGk8,16498
226
- zou/app/services/user_service.py,sha256=rvo_e_JkPdTqIOE3FETXlUXnuS8n0lLyovTpwApyt8I,51470
225
+ zou/app/services/time_spents_service.py,sha256=8sYnepgeo4yohNFRNiEedqFfL2vuJ78GZSHOpRmp52Q,16502
226
+ zou/app/services/user_service.py,sha256=wdi2b2kvct5b_Qi9XdrNEhz9JL4WoI9EpT-8_UOSXnE,52070
227
227
  zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  zou/app/stores/auth_tokens_store.py,sha256=-qOJPybLHvnMOq3PWk073OW9HJwOHGhFLZeOIlX1UVw,1290
229
229
  zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
@@ -242,7 +242,7 @@ zou/app/utils/dbhelpers.py,sha256=RSJuoxLexGJyME16GQCs-euFLBR0u-XAFdJ1KMSv5M8,11
242
242
  zou/app/utils/emails.py,sha256=hc4HWvVYsG1xoP3sR0Zig0sB0k0y7bNxuNxxBreN5Yg,1436
243
243
  zou/app/utils/env.py,sha256=haveriMt1rDeLOosAPMm0IblF_QpMViEsjg7BJqD-rw,711
244
244
  zou/app/utils/events.py,sha256=a_W70v0Oi4QJwJzCLVUQ8RTwjlWo-VzAT_hQZCz2HQU,3024
245
- zou/app/utils/fido.py,sha256=qhUWZdDCvgWqydYS4DN1SVkNwdAQkRSV9zs0Xw9O15E,536
245
+ zou/app/utils/fido.py,sha256=Tlv5V4mDIbWiz93-gLh6i5p4PXBJWTLR3djR4ysT-PA,460
246
246
  zou/app/utils/fields.py,sha256=GTG6249Dz5pJUI1pcDPilzZqGkyPkAEyLpT3Gu2CfB0,3707
247
247
  zou/app/utils/flask.py,sha256=t0sC6yEDyzn-vCsijWzI9lpNWoxAYWfui25QtjQi_64,1822
248
248
  zou/app/utils/fs.py,sha256=EIRfKJXtHubVVi8FlDd9s9TcUok91LvRgU0l_B3Fq3w,3356
@@ -446,9 +446,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
446
446
  zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
447
447
  zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
448
448
  zou/utils/movie.py,sha256=d67fIL9dVBKt-E_qCGXRbNNdbJaJR5sHvZeX3hf8ldE,16559
449
- zou-0.20.47.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
450
- zou-0.20.47.dist-info/METADATA,sha256=vpHO5UNC_iBIrLrSzzgqIC1RTFE5bqLgp513rmkAyc8,6826
451
- zou-0.20.47.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
452
- zou-0.20.47.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
453
- zou-0.20.47.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
454
- zou-0.20.47.dist-info/RECORD,,
449
+ zou-0.20.49.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
450
+ zou-0.20.49.dist-info/METADATA,sha256=giVTPauxUdlQUREGmM9HJMxvV8HXQoj6bgGalOYinPE,6698
451
+ zou-0.20.49.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
452
+ zou-0.20.49.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
453
+ zou-0.20.49.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
454
+ zou-0.20.49.dist-info/RECORD,,
File without changes