zou 0.19.43__py3-none-any.whl → 0.19.45__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.43"
1
+ __version__ = "0.19.45"
@@ -1,5 +1,4 @@
1
1
  from zou.app.models.organisation import Organisation
2
- from zou.app.utils import fields
3
2
  from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource
4
3
 
5
4
 
@@ -7,9 +6,6 @@ class OrganisationsResource(BaseModelsResource):
7
6
  def __init__(self):
8
7
  BaseModelsResource.__init__(self, Organisation)
9
8
 
10
- def get(self):
11
- return fields.serialize_list(Organisation.query.all())
12
-
13
9
  def check_read_permissions(self):
14
10
  return True
15
11
 
@@ -338,8 +338,6 @@ class CreatePreviewFilePictureResource(Resource, ArgsMixin):
338
338
  preview_files_service.prepare_and_store_movie(
339
339
  preview_file_id, uploaded_movie_path, normalize=normalize
340
340
  )
341
- preview_file = files_service.get_preview_file(preview_file_id)
342
- tasks_service.update_preview_file_info(preview_file)
343
341
  return preview_file_id
344
342
 
345
343
  def save_file_preview(self, instance_id, uploaded_file, extension):
@@ -672,6 +670,10 @@ class PreviewFileDownloadResource(PreviewFileResource):
672
670
  return send_standard_file(
673
671
  instance_id, extension, mimetype, as_attachment=True
674
672
  )
673
+ if extension == "mp4":
674
+ return send_picture_file(
675
+ "original", instance_id, as_attachment=True
676
+ )
675
677
  else:
676
678
  return send_standard_file(
677
679
  instance_id, extension, as_attachment=True
@@ -42,6 +42,7 @@ from zou.app.blueprints.shots.resources import (
42
42
  EpisodeAssetTasksResource,
43
43
  SequenceShotTasksResource,
44
44
  ProjectQuotasResource,
45
+ SetShotsFramesResource,
45
46
  )
46
47
 
47
48
  routes = [
@@ -94,6 +95,10 @@ routes = [
94
95
  "/data/projects/<project_id>/quotas/<task_type_id>",
95
96
  ProjectQuotasResource,
96
97
  ),
98
+ (
99
+ "/actions/projects/<project_id>/task-types/<task_type_id>/set-shot-nb-frames",
100
+ SetShotsFramesResource,
101
+ )
97
102
  ]
98
103
 
99
104
 
@@ -18,6 +18,7 @@ from zou.app.services import (
18
18
 
19
19
  from zou.app.mixin import ArgsMixin
20
20
  from zou.app.utils import fields, query, permissions
21
+ from zou.app.services.exception import WrongParameterException
21
22
 
22
23
 
23
24
  class ShotResource(Resource, ArgsMixin):
@@ -1526,3 +1527,51 @@ class ProjectQuotasResource(Resource, ArgsMixin):
1526
1527
  return shots_service.get_raw_quotas(
1527
1528
  project_id, task_type_id, args["studio_id"]
1528
1529
  )
1530
+
1531
+
1532
+
1533
+ class SetShotsFramesResource(Resource, ArgsMixin):
1534
+ @jwt_required()
1535
+ def post(self, project_id, task_type_id):
1536
+ """
1537
+ Set frames for given shots.
1538
+ ---
1539
+ tags:
1540
+ - Shots
1541
+ parameters:
1542
+ - in: formData
1543
+ name: shots
1544
+ required: True
1545
+ type: array
1546
+ items:
1547
+ type: object
1548
+ properties:
1549
+ shot_id:
1550
+ type: string
1551
+ format: UUID
1552
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
1553
+ nb_frames:
1554
+ type: integer
1555
+ x-example: 24
1556
+ responses:
1557
+ 200:
1558
+ description: Frames set for given shots
1559
+ """
1560
+ user_service.check_manager_project_access(project_id)
1561
+ if not fields.is_valid_id(task_type_id) or \
1562
+ not fields.is_valid_id(project_id):
1563
+ raise WrongParameterException("Invalid project or task type id")
1564
+
1565
+ episode_id = self.get_episode_id()
1566
+ if not episode_id in ["", None] and \
1567
+ not fields.is_valid_id(episode_id):
1568
+ raise WrongParameterException("Invalid episode id")
1569
+
1570
+ if episode_id == "":
1571
+ episode_id = None
1572
+
1573
+ return shots_service.set_frames_from_task_type_preview_files(
1574
+ project_id,
1575
+ task_type_id,
1576
+ episode_id=episode_id,
1577
+ )
@@ -42,6 +42,7 @@ class AttachmentFile(db.Model, BaseMixin, SerializerMixin):
42
42
  def create_from_import(cls, data):
43
43
  data.pop("type", None)
44
44
  data.pop("comment", None)
45
+ data.pop("chat_message", None)
45
46
  previous_data = cls.get(data["id"])
46
47
  if previous_data is None:
47
48
  return cls.create(**data)
@@ -27,6 +27,8 @@ class EntityType(db.Model, BaseMixin, SerializerMixin):
27
27
  """
28
28
 
29
29
  name = db.Column(db.String(30), unique=True, nullable=False, index=True)
30
+ short_name = db.Column(db.String(20))
31
+ description = db.Column(db.Text())
30
32
  task_types = db.relationship(
31
33
  "TaskType", secondary=task_type_link, lazy="joined"
32
34
  )
@@ -15,6 +15,7 @@ class TaskStatus(db.Model, BaseMixin, SerializerMixin):
15
15
  short_name = db.Column(
16
16
  db.String(10), unique=True, nullable=False, index=True
17
17
  )
18
+ description = db.Column(db.Text())
18
19
  color = db.Column(db.String(7), nullable=False)
19
20
  priority = db.Column(db.Integer, default=1)
20
21
 
@@ -12,6 +12,7 @@ class TaskType(db.Model, BaseMixin, SerializerMixin):
12
12
 
13
13
  name = db.Column(db.String(40), nullable=False)
14
14
  short_name = db.Column(db.String(20))
15
+ description = db.Column(db.Text())
15
16
  color = db.Column(db.String(7), default="#FFFFFF")
16
17
  priority = db.Column(db.Integer, default=1)
17
18
  for_entity = db.Column(db.String(30), default="Asset")
@@ -163,7 +163,10 @@ def set_preview_file_as_ready(preview_file_id):
163
163
 
164
164
 
165
165
  def prepare_and_store_movie(
166
- preview_file_id, uploaded_movie_path, normalize=True
166
+ preview_file_id,
167
+ uploaded_movie_path,
168
+ normalize=True,
169
+ add_source_to_file_store=True,
167
170
  ):
168
171
  """
169
172
  Prepare movie preview, normalize the movie as a .mp4, build the thumbnails
@@ -196,13 +199,14 @@ def prepare_and_store_movie(
196
199
  if normalize:
197
200
  current_app.logger.info("start normalization")
198
201
  try:
202
+ if add_source_to_file_store:
203
+ file_store.add_movie(
204
+ "source", preview_file_id, uploaded_movie_path
205
+ )
199
206
  if (
200
207
  config.ENABLE_JOB_QUEUE_REMOTE
201
208
  and len(config.JOB_QUEUE_NOMAD_NORMALIZE_JOB) > 0
202
209
  ):
203
- file_store.add_movie(
204
- "source", preview_file_id, uploaded_movie_path
205
- )
206
210
  result = _run_remote_normalize_movie(
207
211
  current_app, preview_file_id, fps, width, height
208
212
  )
@@ -20,6 +20,7 @@ from zou.app.models.entity import (
20
20
  )
21
21
  from zou.app.models.person import Person
22
22
  from zou.app.models.project import Project
23
+ from zou.app.models.preview_file import PreviewFile
23
24
  from zou.app.models.schedule_item import ScheduleItem
24
25
  from zou.app.models.subscription import Subscription
25
26
  from zou.app.models.task import Task
@@ -1525,3 +1526,75 @@ def get_all_raw_shots():
1525
1526
  """
1526
1527
  query = Entity.query.filter(Entity.entity_type_id == get_shot_type()["id"])
1527
1528
  return query.all()
1529
+
1530
+
1531
+ def set_frames_from_task_type_preview_files(
1532
+ project_id,
1533
+ task_type_id,
1534
+ episode_id=None,
1535
+ ):
1536
+ from zou.app import db
1537
+
1538
+ shot_type = get_shot_type()
1539
+ Shot = aliased(Entity)
1540
+ Sequence = aliased(Entity)
1541
+
1542
+ if episode_id is not None:
1543
+ subquery = (
1544
+ db.session.query(
1545
+ Shot.id.label("entity_id"),
1546
+ func.max(PreviewFile.created_at).label("max_created_at")
1547
+ )
1548
+ .join(Task, PreviewFile.task_id == Task.id)
1549
+ .join(Shot, Task.entity_id == Shot.id)
1550
+ .join(Sequence, Sequence.id == Shot.parent_id)
1551
+ .filter(Shot.project_id == project_id)
1552
+ .filter(Shot.entity_type_id == shot_type["id"])
1553
+ .filter(Task.task_type_id == task_type_id)
1554
+ .filter(Sequence.parent_id == episode_id)
1555
+ .group_by(Shot.id)
1556
+ .subquery()
1557
+ )
1558
+ else:
1559
+ subquery = (
1560
+ db.session.query(
1561
+ Shot.id.label("entity_id"),
1562
+ func.max(PreviewFile.created_at).label("max_created_at")
1563
+ )
1564
+ .join(Task, PreviewFile.task_id == Task.id)
1565
+ .join(Shot, Task.entity_id == Shot.id)
1566
+ .filter(Shot.project_id == project_id)
1567
+ .filter(Shot.entity_type_id == shot_type["id"])
1568
+ .filter(Task.task_type_id == task_type_id)
1569
+ .group_by(Shot.id)
1570
+ .subquery()
1571
+ )
1572
+
1573
+ query = (
1574
+ db.session.query(
1575
+ Shot,
1576
+ PreviewFile.duration
1577
+ )
1578
+ .join(Task, Task.entity_id == Shot.id)
1579
+ .join(subquery, (Shot.id == subquery.c.entity_id))
1580
+ .join(PreviewFile,
1581
+ (PreviewFile.task_id == Task.id) &
1582
+ (PreviewFile.created_at == subquery.c.max_created_at))
1583
+ .filter(Task.task_type_id == task_type_id)
1584
+ .filter(Shot.project_id == project_id)
1585
+ )
1586
+
1587
+ results = query.all()
1588
+ project = projects_service.get_project(project_id)
1589
+ updates = []
1590
+ for (shot, preview_duration) in results:
1591
+ nb_frames = round(preview_duration * int(project["fps"]))
1592
+ updates.append({
1593
+ "id": shot.id,
1594
+ "nb_frames": nb_frames,
1595
+ })
1596
+ clear_shot_cache(str(shot.id))
1597
+
1598
+ db.session.bulk_update_mappings(Shot, updates)
1599
+ db.session.commit()
1600
+ return updates
@@ -172,15 +172,15 @@ project_events = [
172
172
  ]
173
173
 
174
174
  main_events = [
175
- "person",
176
- "organisation",
177
- "project-status",
178
- "department",
179
175
  "studio",
176
+ "department",
180
177
  "task-type",
181
178
  "task-status",
182
179
  "custom-action",
180
+ "organisation",
181
+ "project-status",
183
182
  "asset-type",
183
+ "person",
184
184
  "project",
185
185
  ]
186
186
 
@@ -408,35 +408,35 @@ def sync_entries(model_name, model, project=None):
408
408
  """
409
409
  instances = []
410
410
 
411
- if model_name in ["organisations", "persons"]:
412
- path = model_name + "?relations=true"
413
- if model_name == "persons":
414
- path += "&with_pass_hash=true"
415
- instances = gazu.client.fetch_all(path)
416
- model.create_from_import_list(instances)
417
- elif project:
411
+ page = 1
412
+ init = True
413
+ results = {"nb_pages": 2}
414
+ params = {
415
+ "relations": "true",
416
+ }
417
+ if model_name == "persons":
418
+ params["with_pass_hash"] = "true"
419
+ if project is not None and model_name in [
420
+ "projects",
421
+ "search-filters",
422
+ "search-filter-groups",
423
+ ]:
418
424
  project = gazu.project.get_project_by_name(project)
419
425
  if model_name == "projects":
420
- instances = [gazu.client.fetch_one(model_name, project.get("id"))]
426
+ params = {"id": project["id"]}
421
427
  elif model_name in ["search-filters", "search-filter-groups"]:
422
- instances = gazu.client.fetch_all(
423
- model_name, params=dict(project_id=project.get("id"))
424
- )
425
- else:
426
- instances = gazu.client.fetch_all(model_name)
427
- model.create_from_import_list(instances)
428
- else:
429
- page = 1
430
- init = True
431
- results = {"nb_pages": 2}
432
- while init or results["nb_pages"] >= page:
433
- results = gazu.client.fetch_all(
434
- "%s?relations=true&page=%d" % (model_name, page)
435
- )
436
- instances += results["data"]
437
- page += 1
438
- init = False
439
- model.create_from_import_list(results["data"])
428
+ params = {"project_id": project["id"]}
429
+ while init or results["nb_pages"] >= page:
430
+ params["page"] = page
431
+ results = gazu.client.fetch_all(model_name, params=params)
432
+ if model_name == "task-status" and results["data"]:
433
+ results["data"] = [
434
+ r for r in results["data"] if not r["for_concept"]
435
+ ]
436
+ instances += results["data"]
437
+ page += 1
438
+ init = False
439
+ model.create_from_import_list(results["data"])
440
440
 
441
441
  logger.info("%s %s synced." % (len(instances), model_name))
442
442
 
zou/app/utils/commands.py CHANGED
@@ -3,11 +3,13 @@
3
3
  import os
4
4
  import datetime
5
5
  import tempfile
6
+ import sys
7
+ import shutil
6
8
 
7
9
 
8
10
  from ldap3 import Server, Connection, ALL, NTLM, SIMPLE
9
11
  from zou.app.utils import thumbnail as thumbnail_utils, auth
10
- from zou.app.stores import auth_tokens_store, file_store
12
+ from zou.app.stores import auth_tokens_store, file_store, queue_store
11
13
  from zou.app.services import (
12
14
  assets_service,
13
15
  backup_service,
@@ -23,6 +25,8 @@ from zou.app.services import (
23
25
  tasks_service,
24
26
  )
25
27
  from zou.app.models.person import Person
28
+ from zou.app.models.preview_file import PreviewFile
29
+ from zou.app.models.task import Task
26
30
  from sqlalchemy.sql.expression import not_
27
31
 
28
32
  from zou.app.services.exception import (
@@ -717,3 +721,88 @@ def create_bot(
717
721
  is_bot=True,
718
722
  )
719
723
  print(bot["access_token"])
724
+
725
+
726
+ def renormalize_movie_preview_files(
727
+ preview_file_id=None, project_id=None, all_broken=None, all_processing=None
728
+ ):
729
+ with app.app_context():
730
+ if preview_file_id is None and not all_broken and not all_processing:
731
+ print("You must specify at least one option.")
732
+ sys.exit(1)
733
+ else:
734
+ query = PreviewFile.query.filter(
735
+ PreviewFile.extension == "mp4"
736
+ ).order_by(PreviewFile.created_at.asc())
737
+
738
+ if preview_file_id is not None:
739
+ query = query.filter(PreviewFile.id == preview_file_id)
740
+
741
+ if project_id is not None:
742
+ query = query.join(Task).filter(
743
+ PreviewFile.project_id == project_id
744
+ )
745
+
746
+ if all_broken and all_processing:
747
+ query = query.filter(
748
+ PreviewFile.status.in_(("broken", "processing"))
749
+ )
750
+ elif all_broken:
751
+ query = query.filter(PreviewFile.status == "broken")
752
+ elif all_processing:
753
+ query = query.filter(PreviewFile.status == "processing")
754
+
755
+ preview_files = query.all()
756
+ len_preview_files = len(preview_files)
757
+ if len_preview_files == 0:
758
+ print("No preview files found.")
759
+ sys.exit(1)
760
+ else:
761
+ for i, preview_file in enumerate(preview_files):
762
+ try:
763
+ preview_file_id = str(preview_file.id)
764
+ print(
765
+ f"Renormalizing preview file {preview_file_id} ({i+1}/{len_preview_files})."
766
+ )
767
+ extension = preview_file.extension
768
+ uploaded_movie_path = os.path.join(
769
+ config.TMP_DIR,
770
+ f"{preview_file_id}.{extension}.tmp",
771
+ )
772
+ if config.FS_BACKEND == "local":
773
+ shutil.copyfile(
774
+ file_store.get_local_movie_path(
775
+ "source", preview_file_id
776
+ ),
777
+ uploaded_movie_path,
778
+ )
779
+ else:
780
+ sync_service.download_file(
781
+ uploaded_movie_path,
782
+ "source",
783
+ file_store.open_movie,
784
+ str(preview_file_id),
785
+ )
786
+ if config.ENABLE_JOB_QUEUE:
787
+ queue_store.job_queue.enqueue(
788
+ preview_files_service.prepare_and_store_movie,
789
+ args=(
790
+ preview_file_id,
791
+ uploaded_movie_path,
792
+ True,
793
+ False,
794
+ ),
795
+ job_timeout=int(config.JOB_QUEUE_TIMEOUT),
796
+ )
797
+ else:
798
+ preview_files_service.prepare_and_store_movie(
799
+ preview_file_id,
800
+ uploaded_movie_path,
801
+ normalize=True,
802
+ add_source_to_file_store=False,
803
+ )
804
+ except Exception as e:
805
+ print(
806
+ f"Renormalization of preview file {preview_file_id} failed: {e}"
807
+ )
808
+ continue
zou/cli.py CHANGED
@@ -456,13 +456,13 @@ def upload_files_to_cloud_storage(days):
456
456
 
457
457
 
458
458
  @cli.command()
459
- @click.option("--projectid")
460
- def clean_tasks_data(projectid):
459
+ @click.option("--project-id")
460
+ def clean_tasks_data(project_id):
461
461
  """
462
462
  Reset task models data (retake count, wip start date and end date)
463
463
  """
464
- if projectid is not None:
465
- commands.reset_tasks_data(projectid)
464
+ if project_id is not None:
465
+ commands.reset_tasks_data(project_id)
466
466
 
467
467
 
468
468
  @cli.command()
@@ -569,7 +569,7 @@ def reset_breakdown_data():
569
569
  @click.option("--email", required=True)
570
570
  @click.option("--name", required=True)
571
571
  @click.option(
572
- "--expiration_date",
572
+ "--expiration-date",
573
573
  required=False,
574
574
  default=None,
575
575
  show_default=True,
@@ -593,5 +593,39 @@ def create_bot(
593
593
  )
594
594
 
595
595
 
596
+ @cli.command()
597
+ @click.option(
598
+ "--preview-file-id",
599
+ required=False,
600
+ default=None,
601
+ show_default=True,
602
+ )
603
+ @click.option(
604
+ "--project-id",
605
+ required=False,
606
+ default=None,
607
+ show_default=True,
608
+ )
609
+ @click.option("--all-broken", is_flag=True, default=False, show_default=True)
610
+ @click.option(
611
+ "--all-processing", is_flag=True, default=False, show_default=True
612
+ )
613
+ def renormalize_movie_preview_files(
614
+ preview_file_id,
615
+ project_id,
616
+ all_broken,
617
+ all_processing,
618
+ ):
619
+ """
620
+ Renormalize all preview files.
621
+ """
622
+ commands.renormalize_movie_preview_files(
623
+ preview_file_id,
624
+ project_id,
625
+ all_broken,
626
+ all_processing,
627
+ )
628
+
629
+
596
630
  if __name__ == "__main__":
597
631
  cli()
@@ -0,0 +1,33 @@
1
+ """Add short_name for Asset Type entity_type
2
+
3
+ Revision ID: 971dbf5a0faf
4
+ Revises: a252a094e977
5
+ Create Date: 2024-06-20 19:51:15.758780
6
+
7
+ """
8
+
9
+ from alembic import op
10
+ import sqlalchemy as sa
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "971dbf5a0faf"
15
+ down_revision = "a252a094e977"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade():
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ op.add_column(
23
+ "entity_type",
24
+ sa.Column("short_name", sa.String(length=20), nullable=True),
25
+ )
26
+
27
+ # ### end Alembic commands ###
28
+
29
+
30
+ def downgrade():
31
+ # ### commands auto generated by Alembic - please adjust! ###
32
+ op.drop_column("entity_type", "short_name")
33
+ # ### end Alembic commands ###
@@ -0,0 +1,40 @@
1
+ """Add descriptions for entities tasks and statuses
2
+
3
+ Revision ID: a252a094e977
4
+ Revises: 1bb55759146f
5
+ Create Date: 2024-06-20 20:37:21.885953
6
+
7
+ """
8
+
9
+ from alembic import op
10
+ import sqlalchemy as sa
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "a252a094e977"
15
+ down_revision = "1bb55759146f"
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade():
21
+ # ### commands auto generated by Alembic - please adjust! ###
22
+ op.add_column(
23
+ "task_type", sa.Column("description", sa.Text(), nullable=True)
24
+ )
25
+ op.add_column(
26
+ "task_status", sa.Column("description", sa.Text(), nullable=True)
27
+ )
28
+ op.add_column(
29
+ "entity_type", sa.Column("description", sa.Text(), nullable=True)
30
+ )
31
+ # ### end Alembic commands ###
32
+
33
+
34
+ def downgrade():
35
+ # ### commands auto generated by Alembic - please adjust! ###
36
+ op.drop_column("task_type", "description")
37
+ op.drop_column("task_status", "description")
38
+ op.drop_column("entity_type", "description")
39
+
40
+ # ### end Alembic commands ###
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zou
3
- Version: 0.19.43
3
+ Version: 0.19.45
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
@@ -51,17 +51,17 @@ Requires-Dist: ldap3 ==2.9.1
51
51
  Requires-Dist: matterhook ==0.2
52
52
  Requires-Dist: meilisearch ==0.31.3
53
53
  Requires-Dist: opencv-python ==4.10.0.84
54
- Requires-Dist: OpenTimelineIO ==0.16.0
55
- Requires-Dist: orjson ==3.10.5
56
- Requires-Dist: pillow ==10.3.0
54
+ Requires-Dist: OpenTimelineIO ==0.17.0
55
+ Requires-Dist: orjson ==3.10.6
56
+ Requires-Dist: pillow ==10.4.0
57
57
  Requires-Dist: psutil ==6.0.0
58
- Requires-Dist: psycopg[binary] ==3.1.19
58
+ Requires-Dist: psycopg[binary] ==3.2.1
59
59
  Requires-Dist: pyotp ==2.9.0
60
60
  Requires-Dist: python-nomad ==2.0.1
61
61
  Requires-Dist: python-slugify ==8.0.4
62
62
  Requires-Dist: python-socketio ==5.11.3
63
63
  Requires-Dist: pytz ==2024.1
64
- Requires-Dist: redis ==5.0.6
64
+ Requires-Dist: redis ==5.0.7
65
65
  Requires-Dist: requests ==2.32.3
66
66
  Requires-Dist: rq ==1.16.2
67
67
  Requires-Dist: slackclient ==2.9.4
@@ -80,12 +80,12 @@ Requires-Dist: pre-commit ==3.7.1 ; (python_version >= "3.9") and extra == 'lint
80
80
  Provides-Extra: monitoring
81
81
  Requires-Dist: prometheus-flask-exporter ==0.23.0 ; extra == 'monitoring'
82
82
  Requires-Dist: pygelf ==0.4.2 ; extra == 'monitoring'
83
- Requires-Dist: sentry-sdk ==2.6.0 ; extra == 'monitoring'
83
+ Requires-Dist: sentry-sdk ==2.8.0 ; extra == 'monitoring'
84
84
  Provides-Extra: prod
85
85
  Requires-Dist: gunicorn ; extra == 'prod'
86
86
  Requires-Dist: gevent ; extra == 'prod'
87
87
  Provides-Extra: test
88
- Requires-Dist: fakeredis ==2.23.2 ; extra == 'test'
88
+ Requires-Dist: fakeredis ==2.23.3 ; extra == 'test'
89
89
  Requires-Dist: mixer ==7.2.2 ; extra == 'test'
90
90
  Requires-Dist: pytest-cov ==5.0.0 ; extra == 'test'
91
91
  Requires-Dist: pytest ==8.2.2 ; extra == 'test'
@@ -1,5 +1,5 @@
1
- zou/__init__.py,sha256=NPomW3nti4xDksBdQpzSXjzxXI8qrycWAo_jHAslssY,24
2
- zou/cli.py,sha256=mnY9MoD0SjY4KFa1qyYS4E5bjEqk1UIZpH0iYeZPGh8,17508
1
+ zou/__init__.py,sha256=Tv6q0iYoqN9oDIxMPDw4V79Q7KHIfjKuzDdzglh8VUA,24
2
+ zou/cli.py,sha256=2cDkbEOqp_m9hzBQf5wpxc_h0WjoH8KtxQQMNuREYlc,18201
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
4
  zou/event_stream.py,sha256=zgob2dZKray2lxPa11hdRNmOg8XRlKDdRcGdF80ylwg,8245
5
5
  zou/job_settings.py,sha256=WB_RkYxmh4ffQHqg63_wsUDiS0zP3yxiwrxK7DhHG0g,150
@@ -40,7 +40,7 @@ zou/app/blueprints/crud/metadata_descriptor.py,sha256=6sNsebjbXnUnlflG4biB0M-C2n
40
40
  zou/app/blueprints/crud/milestone.py,sha256=UIMsyCNS7ZRePjo08yyzubLEo6fcK-RAsVvrfjXoclA,839
41
41
  zou/app/blueprints/crud/news.py,sha256=0baKn4OLEVY7ljWgpJEypo2Pgzhlp8GJxjim78oqLtg,344
42
42
  zou/app/blueprints/crud/notification.py,sha256=A-KNH0IDNCXlE4AddNxvmsD_7a9HqHGo_rI-Z_pdzus,530
43
- zou/app/blueprints/crud/organisation.py,sha256=B2iCk89w2CQgxHrmyFfc93W_6krTxs4IuwiXIbIuZFw,801
43
+ zou/app/blueprints/crud/organisation.py,sha256=JbgTOxmt1rSddRSGzylDeBIgjCqbeQ-a3WYnL8m9-ts,685
44
44
  zou/app/blueprints/crud/output_file.py,sha256=jWSagq4LxwtFQH0XL_LjXaiW9FRn8T4k0tv1EbmPfg0,3954
45
45
  zou/app/blueprints/crud/output_type.py,sha256=eYJXLPkUCRj9-v5mc3rxqEHM3yycmf6rVAoaOfbnAcU,1998
46
46
  zou/app/blueprints/crud/person.py,sha256=7masu1UxnSJT7KZ4zVUvUA7B2_zdY8ZtcEtqEiSIEfc,9201
@@ -91,13 +91,13 @@ zou/app/blueprints/persons/resources.py,sha256=-5J8ZswusYEBTNmX4I7fLFDZVMKyO0qhO
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=CazwYCIg-iGSLcOH2NYcgflH7zipHfCF9MD1fP93mOI,4363
94
- zou/app/blueprints/previews/resources.py,sha256=wteYWoD_Rdp3z7D3TQxk_3sC4KkqighYpm86R6vNa5A,48327
94
+ zou/app/blueprints/previews/resources.py,sha256=GTluK0FV_SG_bG33yOyJLjOsXgsDJjtnHbkm315E9RE,48346
95
95
  zou/app/blueprints/projects/__init__.py,sha256=Pn3fA5bpNFEPBzxTKJ2foV6osZFflXXSM2l2uZh3ktM,3927
96
96
  zou/app/blueprints/projects/resources.py,sha256=v9_TLh3mujL-p7QcGkfSOJnNojzoJA15jhqAHz5kEIc,31552
97
97
  zou/app/blueprints/search/__init__.py,sha256=QCjQIY_85l_orhdEiqav_GifjReuwsjZggN3V0GeUVY,356
98
98
  zou/app/blueprints/search/resources.py,sha256=ni-dX8Xfib_0FonLttoXgntXBR957-xhifPSQHHnOnY,2696
99
- zou/app/blueprints/shots/__init__.py,sha256=xdDL96fXN7_P7RgoBbKEQI9CN4_bKKU8iElJ8RXzQ94,3916
100
- zou/app/blueprints/shots/resources.py,sha256=kw91QsKg5NzXqZn3hpmSebQXJ707hCotgYZz4Pqnb4I,46265
99
+ zou/app/blueprints/shots/__init__.py,sha256=ZFQIwwM0s3QDVble3oa9UxNCTmpJTZ1IXTHSsuBNYB4,4075
100
+ zou/app/blueprints/shots/resources.py,sha256=9cx0uO36oUy2Q1co7qSZv6IyY1swzK2cKCczNwTTZVk,47743
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=WkzpKylVkNlbY_jwf6uV5-HPylrktQznOcbCs_p8TDQ,13391
@@ -136,7 +136,7 @@ zou/app/indexer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
136
  zou/app/indexer/indexing.py,sha256=rzZxtAInXVZ2cZES-6QJw3NJlRpSPpKLxL0eP8l0onI,3479
137
137
  zou/app/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
138
  zou/app/models/asset_instance.py,sha256=ajfyA3qe6IjoNvd3mM8yr7wk9p4R9WO0qTfqT9ijntg,1714
139
- zou/app/models/attachment_file.py,sha256=10eHjXaA0wEvsazKWGyHwdh7N5kO8kYksrp7sP8-Eug,1338
139
+ zou/app/models/attachment_file.py,sha256=d3gldEyKhRyLqGQHBbWVwtmPgtq7oxipxHanZUKWVGI,1377
140
140
  zou/app/models/base.py,sha256=lxAfdT2kx1d3NmuYrj_FZOWE_FpFuX53kEX9KOqdRaE,8677
141
141
  zou/app/models/build_job.py,sha256=aW6KZXkyMP9d3g8fvcOYk9EAoNMw-6IleZdWbaqLLVw,1286
142
142
  zou/app/models/chat.py,sha256=yeKqe6o7RRAExx8xD-7dRXzUPhq_dwZffrbIG4HQp1w,1189
@@ -148,7 +148,7 @@ zou/app/models/day_off.py,sha256=WMZs7oMhUBpMnNyvhgpl1j6egZ5J0drnrF1dH3N5cII,691
148
148
  zou/app/models/department.py,sha256=ZUzZXemrHJOxoEgALCiMqGww1wnEvxTL12k6KmkWoW4,418
149
149
  zou/app/models/desktop_login_log.py,sha256=fdgqEXAQkHw6CtRU_Y-CuboaZA9QWJc9OzklvbdPBJY,546
150
150
  zou/app/models/entity.py,sha256=tbli3LQk7RSlgR1jgUpKQe-s54OFWr0-exRosd19RTQ,8592
151
- zou/app/models/entity_type.py,sha256=F7RcqPlnX4Ru05ralJfWuGNPIpZY-OKKPdieXnoB8BI,1790
151
+ zou/app/models/entity_type.py,sha256=747igCypAv5n-Lf-xl_nVEO3MzyUPQu5qgH_jksnsrY,1871
152
152
  zou/app/models/event.py,sha256=WNZ9mSh5kIIg-W5CDKfohtAE_ObXbmgRB5JMyWRZktA,677
153
153
  zou/app/models/file_status.py,sha256=pdYnI4empolJ2o2yHSEqp5ZTra4zyXiZPx3bE599GLo,351
154
154
  zou/app/models/login_log.py,sha256=Cpyjo01EKHyaKvNaU_4EWOsvOVxzpBOjeEB17z6h25k,654
@@ -174,8 +174,8 @@ zou/app/models/status_automation.py,sha256=95c0lmOetujyGWViLd_qsR4GWPhrmlvi9ZfkC
174
174
  zou/app/models/studio.py,sha256=cXnYFh-8m5Kw05QawYcCr59eeLp25NDI0VIb77oqUOs,384
175
175
  zou/app/models/subscription.py,sha256=0GDQTHUThnydD4VwZg6YW2daC31zsu16j3ik4Im8d6g,1026
176
176
  zou/app/models/task.py,sha256=UDUhR_L1s29Lo2mIak8ihGOhGlx3sASAq_698Jp-Yek,3398
177
- zou/app/models/task_status.py,sha256=BD-oO3CDyU-oaB04UdPPqBwtdT1OnieS43OFtvfBfdg,1188
178
- zou/app/models/task_type.py,sha256=5X3moXXuQbNEbOMg7Pvtf8OJ5Tp7l1K8ttW_NXFEN1M,966
177
+ zou/app/models/task_status.py,sha256=J7mNWIFd9KMWfUOLHjmuxIupjs59iSh8aQ_9LEFXqH4,1227
178
+ zou/app/models/task_type.py,sha256=IsixVAfz3pyMf0eQw8x-uFNM9OHNkZpsPLEz_VNQ0hA,1005
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
@@ -202,14 +202,14 @@ zou/app/services/news_service.py,sha256=ltMVObZiNpSat4qze4z6W5zoy9IdPXiIfsqSr2aw
202
202
  zou/app/services/notifications_service.py,sha256=7GDRio_mGaRYV5BHOAdpxBZjA_LLYUfVpbwZqy1n9pI,15685
203
203
  zou/app/services/persons_service.py,sha256=MukM-mbmrAglQGcvDLoUVdzBXvCSgepUMAaeODIrT2E,16219
204
204
  zou/app/services/playlists_service.py,sha256=pAlPHET4jNdST5jsmJrFUkf1SVhfSoML9zdNpZ_88l4,32439
205
- zou/app/services/preview_files_service.py,sha256=Oona4G4ibP8uRRVbLtmOIjnYArxTcXLiT0xib9ubkLQ,35509
205
+ zou/app/services/preview_files_service.py,sha256=SIZ_SB1bWNRE_Zm7SuEpvFWqVpHKOgfZlCM2BfkgbWE,35598
206
206
  zou/app/services/projects_service.py,sha256=_J8hIHy3MX5MsdEMRIKNfbyewwhxtMEcc_ymeHBsF38,21434
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=3L5lhmwPudQ8R40hYopx4cn8OxEy0HWYQ-2yrRITV9I,47921
209
+ zou/app/services/shots_service.py,sha256=TVOgIeWkTFLG8cVUmH41E15jAq2rl23fYuGVWefWEUQ,50291
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
- zou/app/services/sync_service.py,sha256=gtYRSTK3GzraMEETErW9g_dog9BlXkBg1OZ2VnpC7s4,41754
212
+ zou/app/services/sync_service.py,sha256=EunfXlma_IIb7011A_xLQLVQGAi-MteKgm2Y2NAxvMs,41586
213
213
  zou/app/services/tasks_service.py,sha256=05Vy7cBhHFr7PYBuTNiggw1TydtOhP5ekuBoTZLTLOA,67797
214
214
  zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6pQ-ytRbmGA,1029
215
215
  zou/app/services/time_spents_service.py,sha256=TBLC1O9Dg_UbciG5Nw-dejqX2-5n6q44lACeN6OnUkQ,15206
@@ -225,7 +225,7 @@ zou/app/utils/auth.py,sha256=DZfZSr1Ulge0UK3hfvOWsMo3_d7RVP_llV118u9BtUI,870
225
225
  zou/app/utils/cache.py,sha256=0u5cOefRXoZtdAp3EgW8_Uk_l6G4j02vN8xBJ1Tm2t4,1085
226
226
  zou/app/utils/chats.py,sha256=ORngxQ3IQQF0QcVFJLxJ-RaU4ksQ9-0M8cmPa0pc0Ho,4302
227
227
  zou/app/utils/colors.py,sha256=LaGV17NL_8xY0XSp8snGWz5UMwGnm0KPWXyE5BTMG6w,200
228
- zou/app/utils/commands.py,sha256=KOTBK9U6BH7aPLuG8TzLhiYif9lBdFZ-zA6qAa3eb5c,23447
228
+ zou/app/utils/commands.py,sha256=3TxXFOQxsWBT85DG1dVnuqdMbjFp58XJEtgYxhxbhhs,27304
229
229
  zou/app/utils/csv_utils.py,sha256=difqBp9xp3nHvaOjW6B64A4X3Uyfe_vKGw10i6SJ5_E,1291
230
230
  zou/app/utils/date_helpers.py,sha256=jFxDPCbAasg0I1gsC72AKEbGcx5c4pLqXZkSfZ4wLdQ,4724
231
231
  zou/app/utils/dbhelpers.py,sha256=edWZgt9IAwg-8Y1SPh_c1mYLrnCy-EY_adONNsQd4yo,852
@@ -344,6 +344,7 @@ zou/migrations/versions/92bdfe07e5f5_discord_integration.py,sha256=3WS9npcOeUMNl
344
344
  zou/migrations/versions/956659992419_add_columns_for_person_to_store_fido_.py,sha256=uZxG1rH13t0q4288i1rYpfnFotW2C8rYEncwU4pWmto,1009
345
345
  zou/migrations/versions/96c79d31e648_add_mail_otp_columns_for_person.py,sha256=iNiR5w8BVcL3UVlXRhCTDWlC9ja6vdoojJr0C9S2JMA,875
346
346
  zou/migrations/versions/96f58a4a2a58_person_partial_index_for_email_only_.py,sha256=UpYFAEdi06n15fbI4pvS1_aUWgnzNp4WUOmXRuCWOyc,1189
347
+ zou/migrations/versions/971dbf5a0faf_add_short_name_for_asset_type_entity_.py,sha256=XerQsbTFdT2oe3A752tOIX-dXJfU1IZY1ywLpGft-9E,731
347
348
  zou/migrations/versions/98c90621cf58_add_for_client_flag_to_playlist.py,sha256=8sgLpFpRaTDmxy5dzwR8sQGx3iMQoUH1-IN641AXEUY,721
348
349
  zou/migrations/versions/99825b9cc778_.py,sha256=vleoLh_fCLwNnCmgZkW5x1-lJ09CgjPdH1oUZZhA8CU,3240
349
350
  zou/migrations/versions/9a09467f9b2c_.py,sha256=cjSO3cXzHHhlcaQhShF9WlxmBWIfwLYSyIb9C6B5Dwc,1246
@@ -352,6 +353,7 @@ zou/migrations/versions/9bd17364fc18_.py,sha256=nruaGMczzkWkya_D11QEU3uiU1UVEUIt
352
353
  zou/migrations/versions/9e5b3a9b0cee_add_new_column_metadatadescriptor_data_type_.py,sha256=HT34AjM9yN1IvLrCzx4-YOiocFDnPQ-FJ05icPCBnNo,5517
353
354
  zou/migrations/versions/9f8445f9b42c_add_man_days_fields.py,sha256=muFsM2g_m-L5Zss36roTsjCoSDdhu_e4hVQntiNHyiY,828
354
355
  zou/migrations/versions/a23682ccc1f1_.py,sha256=dVOUWldUZyLuLc6_HrgKUI5XH5-6Vjwai6Ew9kygkHw,1663
356
+ zou/migrations/versions/a252a094e977_add_descriptions_for_entities_tasks_and_.py,sha256=T6V1n09fUAsZNiCYh0zwi2B6ZtCBPOdXDixqdunDI54,1012
355
357
  zou/migrations/versions/a519c710877c_.py,sha256=QeAjUzmXoIWnfEa935NOJLD0VVuS0NSUd9ia9adVmb4,809
356
358
  zou/migrations/versions/a65bdadbae2f_.py,sha256=7fZNzRhhUm47a7uRqI3adl0J4SCvB3KhwDsRFI2t3Cw,2340
357
359
  zou/migrations/versions/a66508788c53_add_nb_assets_ready.py,sha256=ph1xtl0uBhGXjt2qzCKvXDVplxJpNazRzO_LPhyjRTE,694
@@ -405,9 +407,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
405
407
  zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
406
408
  zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
407
409
  zou/utils/movie.py,sha256=u9LCEOvmkxwm-KiZ6jKNdB9LSC6XXUDwJpVx8LkDwJg,16416
408
- zou-0.19.43.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
409
- zou-0.19.43.dist-info/METADATA,sha256=m3gTAfk6BhIGkFW7poEHWdzkYgtQ-1jrkVU3Ag2CUx0,6678
410
- zou-0.19.43.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
411
- zou-0.19.43.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
412
- zou-0.19.43.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
413
- zou-0.19.43.dist-info/RECORD,,
410
+ zou-0.19.45.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
411
+ zou-0.19.45.dist-info/METADATA,sha256=-qqX8Imqao6HziAEsLUxOo0HY66ob65LWyQFmthuY7U,6677
412
+ zou-0.19.45.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
413
+ zou-0.19.45.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
414
+ zou-0.19.45.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
415
+ zou-0.19.45.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.0)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes