zou 0.20.82__py3-none-any.whl → 0.20.84__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.
Files changed (114) hide show
  1. zou/__init__.py +1 -1
  2. zou/app/blueprints/assets/resources.py +1060 -153
  3. zou/app/blueprints/auth/resources.py +368 -238
  4. zou/app/blueprints/breakdown/resources.py +584 -94
  5. zou/app/blueprints/chats/resources.py +176 -37
  6. zou/app/blueprints/comments/resources.py +409 -150
  7. zou/app/blueprints/concepts/resources.py +443 -63
  8. zou/app/blueprints/crud/asset_instance.py +272 -0
  9. zou/app/blueprints/crud/attachment_file.py +263 -0
  10. zou/app/blueprints/crud/base.py +176 -69
  11. zou/app/blueprints/crud/budget.py +278 -0
  12. zou/app/blueprints/crud/budget_entry.py +269 -0
  13. zou/app/blueprints/crud/chat.py +282 -0
  14. zou/app/blueprints/crud/chat_message.py +286 -0
  15. zou/app/blueprints/crud/comments.py +312 -1
  16. zou/app/blueprints/crud/custom_action.py +268 -0
  17. zou/app/blueprints/crud/day_off.py +298 -0
  18. zou/app/blueprints/crud/department.py +268 -0
  19. zou/app/blueprints/crud/entity.py +297 -3
  20. zou/app/blueprints/crud/entity_link.py +303 -0
  21. zou/app/blueprints/crud/entity_type.py +269 -0
  22. zou/app/blueprints/crud/event.py +197 -0
  23. zou/app/blueprints/crud/file_status.py +268 -0
  24. zou/app/blueprints/crud/hardware_item.py +268 -0
  25. zou/app/blueprints/crud/metadata_descriptor.py +312 -0
  26. zou/app/blueprints/crud/milestone.py +302 -1
  27. zou/app/blueprints/crud/news.py +285 -0
  28. zou/app/blueprints/crud/notification.py +287 -0
  29. zou/app/blueprints/crud/organisation.py +269 -0
  30. zou/app/blueprints/crud/output_file.py +34 -10
  31. zou/app/blueprints/crud/output_type.py +30 -10
  32. zou/app/blueprints/crud/person.py +407 -2
  33. zou/app/blueprints/crud/playlist.py +322 -4
  34. zou/app/blueprints/crud/plugin.py +269 -0
  35. zou/app/blueprints/crud/preview_background_file.py +272 -0
  36. zou/app/blueprints/crud/preview_file.py +280 -9
  37. zou/app/blueprints/crud/production_schedule_version.py +569 -0
  38. zou/app/blueprints/crud/project.py +440 -0
  39. zou/app/blueprints/crud/project_status.py +268 -0
  40. zou/app/blueprints/crud/salary_scale.py +185 -5
  41. zou/app/blueprints/crud/schedule_item.py +305 -0
  42. zou/app/blueprints/crud/search_filter.py +302 -0
  43. zou/app/blueprints/crud/search_filter_group.py +270 -0
  44. zou/app/blueprints/crud/software.py +30 -10
  45. zou/app/blueprints/crud/status_automation.py +296 -2
  46. zou/app/blueprints/crud/studio.py +268 -0
  47. zou/app/blueprints/crud/subscription.py +279 -0
  48. zou/app/blueprints/crud/task.py +325 -5
  49. zou/app/blueprints/crud/task_status.py +301 -0
  50. zou/app/blueprints/crud/task_type.py +283 -0
  51. zou/app/blueprints/crud/time_spent.py +327 -0
  52. zou/app/blueprints/crud/working_file.py +273 -10
  53. zou/app/blueprints/departments/resources.py +302 -68
  54. zou/app/blueprints/edits/resources.py +651 -81
  55. zou/app/blueprints/entities/resources.py +104 -39
  56. zou/app/blueprints/events/resources.py +96 -8
  57. zou/app/blueprints/export/csv/assets.py +15 -5
  58. zou/app/blueprints/export/csv/base.py +12 -3
  59. zou/app/blueprints/export/csv/casting.py +32 -5
  60. zou/app/blueprints/export/csv/edits.py +15 -5
  61. zou/app/blueprints/export/csv/persons.py +24 -0
  62. zou/app/blueprints/export/csv/playlists.py +16 -5
  63. zou/app/blueprints/export/csv/projects.py +23 -0
  64. zou/app/blueprints/export/csv/shots.py +15 -5
  65. zou/app/blueprints/export/csv/task_types.py +23 -0
  66. zou/app/blueprints/export/csv/tasks.py +24 -0
  67. zou/app/blueprints/export/csv/time_spents.py +24 -0
  68. zou/app/blueprints/files/resources.py +928 -377
  69. zou/app/blueprints/index/resources.py +49 -42
  70. zou/app/blueprints/news/resources.py +47 -27
  71. zou/app/blueprints/persons/resources.py +644 -271
  72. zou/app/blueprints/playlists/resources.py +154 -72
  73. zou/app/blueprints/previews/resources.py +473 -228
  74. zou/app/blueprints/projects/__init__.py +5 -0
  75. zou/app/blueprints/projects/resources.py +987 -420
  76. zou/app/blueprints/search/resources.py +44 -32
  77. zou/app/blueprints/shots/resources.py +1338 -88
  78. zou/app/blueprints/source/csv/assets.py +44 -6
  79. zou/app/blueprints/source/csv/casting.py +43 -6
  80. zou/app/blueprints/source/csv/edits.py +47 -9
  81. zou/app/blueprints/source/csv/persons.py +43 -4
  82. zou/app/blueprints/source/csv/shots.py +47 -6
  83. zou/app/blueprints/source/csv/task_type_estimations.py +95 -35
  84. zou/app/blueprints/source/kitsu.py +433 -11
  85. zou/app/blueprints/source/otio.py +215 -20
  86. zou/app/blueprints/source/shotgun/assets.py +146 -0
  87. zou/app/blueprints/source/shotgun/base.py +85 -14
  88. zou/app/blueprints/source/shotgun/episode.py +124 -0
  89. zou/app/blueprints/source/shotgun/import_errors.py +105 -14
  90. zou/app/blueprints/source/shotgun/notes.py +132 -0
  91. zou/app/blueprints/source/shotgun/person.py +163 -0
  92. zou/app/blueprints/source/shotgun/project.py +120 -0
  93. zou/app/blueprints/source/shotgun/scene.py +120 -0
  94. zou/app/blueprints/source/shotgun/sequence.py +134 -0
  95. zou/app/blueprints/source/shotgun/shot.py +166 -0
  96. zou/app/blueprints/source/shotgun/status.py +129 -0
  97. zou/app/blueprints/source/shotgun/steps.py +138 -0
  98. zou/app/blueprints/source/shotgun/tasks.py +199 -0
  99. zou/app/blueprints/source/shotgun/team.py +132 -0
  100. zou/app/blueprints/source/shotgun/versions.py +155 -0
  101. zou/app/blueprints/tasks/resources.py +1197 -308
  102. zou/app/blueprints/user/resources.py +1808 -215
  103. zou/app/models/metadata_descriptor.py +1 -0
  104. zou/app/services/persons_service.py +1 -1
  105. zou/app/services/projects_service.py +45 -1
  106. zou/app/services/time_spents_service.py +1 -1
  107. zou/app/swagger.py +100 -27
  108. zou/migrations/versions/a1b2c3d4e5f6_add_position_to_metadata_descriptor.py +32 -0
  109. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/METADATA +18 -18
  110. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/RECORD +114 -113
  111. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/WHEEL +0 -0
  112. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/entry_points.txt +0 -0
  113. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/licenses/LICENSE +0 -0
  114. {zou-0.20.82.dist-info → zou-0.20.84.dist-info}/top_level.txt +0 -0
@@ -58,6 +58,7 @@ class MetadataDescriptor(db.Model, BaseMixin, SerializerMixin):
58
58
  field_name = db.Column(db.String(120), nullable=False)
59
59
  choices = db.Column(JSONB)
60
60
  for_client = db.Column(db.Boolean(), default=False, index=True)
61
+ position = db.Column(db.Integer(), nullable=True)
61
62
  departments = db.relationship(
62
63
  Department,
63
64
  secondary=DepartmentMetadataDescriptorLink.__table__,
@@ -444,7 +444,7 @@ def invite_person(person_id):
444
444
  subject = "You are invited by %s to join their Kitsu platform" % (
445
445
  organisation["name"]
446
446
  )
447
- params = {"email": person["email"], "token": token}
447
+ params = {"email": person["email"], "token": token, "type": "new"}
448
448
  query = urllib.parse.urlencode(params)
449
449
  reset_url = "%s://%s/reset-change-password?%s" % (
450
450
  config.DOMAIN_PROTOCOL,
@@ -107,6 +107,7 @@ def get_projects_with_extra_data(
107
107
  "choices": descriptor.choices,
108
108
  "for_client": descriptor.for_client or False,
109
109
  "entity_type": descriptor.entity_type,
110
+ "position": descriptor.position,
110
111
  "departments": [
111
112
  str(department.id)
112
113
  for department in descriptor.departments
@@ -498,7 +499,7 @@ def get_metadata_descriptors(project_id, for_client=False):
498
499
  """
499
500
  query = MetadataDescriptor.query.filter(
500
501
  MetadataDescriptor.project_id == project_id
501
- ).order_by(MetadataDescriptor.name)
502
+ ).order_by(MetadataDescriptor.position, MetadataDescriptor.name)
502
503
  if for_client:
503
504
  query = query.filter(MetadataDescriptor.for_client == True)
504
505
 
@@ -581,6 +582,46 @@ def update_metadata_descriptor(metadata_descriptor_id, changes):
581
582
  return descriptor.serialize()
582
583
 
583
584
 
585
+ def reorder_metadata_descriptors(project_id, entity_type, descriptor_ids):
586
+ """
587
+ Reorder metadata descriptors for a given project and entity type.
588
+ Updates position field based on the order of descriptor IDs provided.
589
+ Descriptors not in the list are added at the end, ordered by name.
590
+ """
591
+ descriptors = MetadataDescriptor.query.filter(
592
+ MetadataDescriptor.project_id == project_id,
593
+ MetadataDescriptor.entity_type == entity_type,
594
+ ).all()
595
+
596
+ descriptor_map = {str(desc.id): desc for desc in descriptors}
597
+
598
+ for descriptor_id in descriptor_ids:
599
+ if descriptor_id not in descriptor_map:
600
+ raise WrongParameterException(
601
+ f"Descriptor {descriptor_id} not found for project {project_id} and entity type {entity_type}"
602
+ )
603
+
604
+ for position, descriptor_id in enumerate(descriptor_ids, start=1):
605
+ descriptor = descriptor_map[descriptor_id]
606
+ descriptor.update({"position": position})
607
+
608
+ descriptors_not_in_list = [
609
+ desc for desc in descriptors if not str(desc.id) in descriptor_ids
610
+ ]
611
+ descriptors_not_in_list.sort(key=lambda d: d.name)
612
+ start_position = len(descriptor_ids) + 1
613
+ for position_offset, descriptor in enumerate(descriptors_not_in_list):
614
+ descriptor.update({"position": start_position + position_offset})
615
+
616
+ clear_project_cache(project_id)
617
+
618
+ query = MetadataDescriptor.query.filter(
619
+ MetadataDescriptor.project_id == project_id,
620
+ MetadataDescriptor.entity_type == entity_type,
621
+ ).order_by(MetadataDescriptor.position, MetadataDescriptor.name)
622
+ return fields.serialize_models(query.all(), relations=True)
623
+
624
+
584
625
  def remove_metadata_descriptor(metadata_descriptor_id):
585
626
  """
586
627
  Delete metadata descriptor and related informations.
@@ -714,6 +755,9 @@ def get_task_type_links(project_id, for_entity="Asset"):
714
755
 
715
756
 
716
757
  def get_department_team(project_id, department_id):
758
+ """
759
+ Get all persons in a given department for a given project.
760
+ """
717
761
  persons = (
718
762
  Person.query.join(
719
763
  ProjectPersonLink, ProjectPersonLink.person_id == Person.id
@@ -633,7 +633,7 @@ def get_day_offs_between_for_project(
633
633
  for day_off in days_offs:
634
634
  day_off_person_id = str(day_off.person_id)
635
635
  result[day_off_person_id].append(
636
- day_off.serialize()()
636
+ day_off.serialize()
637
637
  if safe or current_user_id == day_off_person_id
638
638
  else day_off.serialize_safe()
639
639
  )
zou/app/swagger.py CHANGED
@@ -29,14 +29,18 @@ An easy to use Python client to access this API is available:
29
29
 
30
30
  ## Authentication<div class="auth">
31
31
 
32
- <p>Before you can use any of the endpoints outline below,
33
- you will have to get a JWT token to authorize your requests.
32
+ <p>Before you can use any of the endpoints outlined below,
33
+ you will need to obtain a JWT token to authorize your requests.
34
34
  </p>
35
35
 
36
36
  <p>
37
- You will find the information to retrieve it in the
37
+ You will find detailed information on how to retrieve authentication tokens in the
38
38
  [Zou documentation](https://zou.cg-wire.com/api/).
39
39
  </p>
40
+
41
+ <p>
42
+ All API requests require authentication via JWT tokens passed in the Authorization header.
43
+ </p>
40
44
  """
41
45
 
42
46
  swagger_template = {
@@ -73,30 +77,99 @@ swagger_template = {
73
77
  },
74
78
  "security": [{"JWT Authorization": []}],
75
79
  "tags": [
76
- {"name": "Authentication"},
77
- {"name": "Assets"},
78
- {"name": "Breakdown"},
79
- {"name": "Chat"},
80
- {"name": "Comments"},
81
- {"name": "Concepts"},
82
- {"name": "Crud"},
83
- {"name": "Departments"},
84
- {"name": "Edits"},
85
- {"name": "Entities"},
86
- {"name": "Events"},
87
- {"name": "Export"},
88
- {"name": "Files"},
89
- {"name": "Import"},
90
- {"name": "Index"},
91
- {"name": "News"},
92
- {"name": "Persons"},
93
- {"name": "Playlists"},
94
- {"name": "Previews"},
95
- {"name": "Projects"},
96
- {"name": "Search"},
97
- {"name": "Shots"},
98
- {"name": "Tasks"},
99
- {"name": "User"},
80
+ {
81
+ "name": "Authentication",
82
+ "description": "User authentication, login, logout, and session management",
83
+ },
84
+ {
85
+ "name": "Assets",
86
+ "description": "Production asset management including 3D models, textures, and media files",
87
+ },
88
+ {
89
+ "name": "Breakdown",
90
+ "description": "Shot breakdown management and asset-to-shot relationships",
91
+ },
92
+ {
93
+ "name": "Chat",
94
+ "description": "Real-time messaging and communication features",
95
+ },
96
+ {
97
+ "name": "Comments",
98
+ "description": "Task comments, feedback, and collaboration tools",
99
+ },
100
+ {
101
+ "name": "Concepts",
102
+ "description": "Concept art and design asset management",
103
+ },
104
+ {
105
+ "name": "Crud",
106
+ "description": "Generic CRUD operations for various data models",
107
+ },
108
+ {
109
+ "name": "Departments",
110
+ "description": "Department management and organizational structure",
111
+ },
112
+ {
113
+ "name": "Edits",
114
+ "description": "Edit management for post-production workflows",
115
+ },
116
+ {
117
+ "name": "Entities",
118
+ "description": "Generic entity management and relationships",
119
+ },
120
+ {
121
+ "name": "Events",
122
+ "description": "Event streaming and real-time notifications",
123
+ },
124
+ {
125
+ "name": "Export",
126
+ "description": "Data export functionality for reports and integrations",
127
+ },
128
+ {
129
+ "name": "Files",
130
+ "description": "File management, uploads, and storage operations",
131
+ },
132
+ {
133
+ "name": "Import",
134
+ "description": "Data import from external sources and file formats",
135
+ },
136
+ {
137
+ "name": "Index",
138
+ "description": "System status, health checks, and configuration",
139
+ },
140
+ {
141
+ "name": "News",
142
+ "description": "Production news feed and activity tracking",
143
+ },
144
+ {"name": "Persons", "description": "User and team member management"},
145
+ {
146
+ "name": "Playlists",
147
+ "description": "Media playlists and review sessions",
148
+ },
149
+ {
150
+ "name": "Previews",
151
+ "description": "Preview generation and thumbnail management",
152
+ },
153
+ {
154
+ "name": "Projects",
155
+ "description": "Project management and production organization",
156
+ },
157
+ {
158
+ "name": "Search",
159
+ "description": "Search functionality across all production data",
160
+ },
161
+ {
162
+ "name": "Shots",
163
+ "description": "Shot management, sequences, and episodes",
164
+ },
165
+ {
166
+ "name": "Tasks",
167
+ "description": "Task management, assignments, and progress tracking",
168
+ },
169
+ {
170
+ "name": "User",
171
+ "description": "User-specific data and personal workspace management",
172
+ },
100
173
  ],
101
174
  "definitions": {
102
175
  " Common fields for all model instances": {
@@ -0,0 +1,32 @@
1
+ """add position to metadata descriptor
2
+
3
+ Revision ID: a1b2c3d4e5f6
4
+ Revises: 5f1620d191af
5
+ Create Date: 2025-11-01 12:00:00.000000
6
+
7
+ """
8
+
9
+ from alembic import op
10
+ import sqlalchemy as sa
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = "a1b2c3d4e5f6"
15
+ down_revision = "5f1620d191af"
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
+ "metadata_descriptor",
24
+ sa.Column("position", sa.Integer(), nullable=True),
25
+ )
26
+ # ### end Alembic commands ###
27
+
28
+
29
+ def downgrade():
30
+ # ### commands auto generated by Alembic - please adjust! ###
31
+ op.drop_column("metadata_descriptor", "position")
32
+ # ### end Alembic commands ###
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zou
3
- Version: 0.20.82
3
+ Version: 0.20.84
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
@@ -22,7 +22,7 @@ Requires-Python: >=3.10, <3.14
22
22
  License-File: LICENSE
23
23
  Requires-Dist: babel==2.17.0
24
24
  Requires-Dist: click==8.3.0
25
- Requires-Dist: discord.py==2.6.3
25
+ Requires-Dist: discord.py==2.6.4
26
26
  Requires-Dist: email-validator==2.3.0
27
27
  Requires-Dist: ffmpeg-python==0.2.0
28
28
  Requires-Dist: fido2==2.0.0
@@ -39,7 +39,7 @@ Requires-Dist: flask-jwt-extended==4.7.1
39
39
  Requires-Dist: flask-migrate==4.1.0
40
40
  Requires-Dist: flask-socketio==5.5.1
41
41
  Requires-Dist: flask==3.1.2
42
- Requires-Dist: gazu==0.10.36
42
+ Requires-Dist: gazu==0.10.37
43
43
  Requires-Dist: gevent-websocket==0.10.1
44
44
  Requires-Dist: gevent==25.9.1
45
45
  Requires-Dist: gunicorn==23.0.0
@@ -48,20 +48,20 @@ Requires-Dist: itsdangerous==2.2.0
48
48
  Requires-Dist: Jinja2==3.1.6
49
49
  Requires-Dist: ldap3==2.9.1
50
50
  Requires-Dist: matterhook==0.2
51
- Requires-Dist: meilisearch==0.37.0
51
+ Requires-Dist: meilisearch==0.37.1
52
52
  Requires-Dist: numpy==2.2.6
53
53
  Requires-Dist: opencv-python==4.12.0.88
54
- Requires-Dist: OpenTimelineIO==0.17.0
55
- Requires-Dist: OpenTimelineIO-Plugins==0.17.0
56
- Requires-Dist: orjson==3.11.3
57
- Requires-Dist: pillow==11.3.0
58
- Requires-Dist: psutil==7.1.0
59
- Requires-Dist: psycopg[binary]==3.2.10
54
+ Requires-Dist: OpenTimelineIO==0.18.1
55
+ Requires-Dist: OpenTimelineIO-Plugins==0.18.1
56
+ Requires-Dist: orjson==3.11.4
57
+ Requires-Dist: pillow==12.0.0
58
+ Requires-Dist: psutil==7.1.3
59
+ Requires-Dist: psycopg[binary]==3.2.12
60
60
  Requires-Dist: pyotp==2.9.0
61
- Requires-Dist: pysaml2==7.5.3
61
+ Requires-Dist: pysaml2==7.5.4
62
62
  Requires-Dist: python-nomad==2.1.0
63
63
  Requires-Dist: python-slugify==8.0.4
64
- Requires-Dist: python-socketio==5.14.1
64
+ Requires-Dist: python-socketio==5.14.3
65
65
  Requires-Dist: pytz==2025.2
66
66
  Requires-Dist: redis==5.2.1
67
67
  Requires-Dist: requests==2.32.5
@@ -70,7 +70,7 @@ Requires-Dist: semver==3.0.4
70
70
  Requires-Dist: slackclient==2.9.4
71
71
  Requires-Dist: spdx-license-list==3.27.0
72
72
  Requires-Dist: sqlalchemy_utils==0.42.0
73
- Requires-Dist: sqlalchemy==2.0.43
73
+ Requires-Dist: sqlalchemy==2.0.44
74
74
  Requires-Dist: tabulate==0.9.0
75
75
  Requires-Dist: tomlkit==0.13.3
76
76
  Requires-Dist: ua-parser==1.0.1
@@ -81,18 +81,18 @@ Requires-Dist: gevent; extra == "prod"
81
81
  Provides-Extra: dev
82
82
  Requires-Dist: wheel; extra == "dev"
83
83
  Provides-Extra: test
84
- Requires-Dist: fakeredis==2.31.3; extra == "test"
84
+ Requires-Dist: fakeredis==2.32.1; extra == "test"
85
85
  Requires-Dist: mixer==7.2.2; extra == "test"
86
86
  Requires-Dist: pytest-cov==7.0.0; extra == "test"
87
- Requires-Dist: pytest==8.4.2; extra == "test"
87
+ Requires-Dist: pytest==9.0.0; extra == "test"
88
88
  Provides-Extra: monitoring
89
89
  Requires-Dist: prometheus-flask-exporter==0.23.2; extra == "monitoring"
90
90
  Requires-Dist: pygelf==0.4.3; extra == "monitoring"
91
- Requires-Dist: sentry-sdk==2.40.0; extra == "monitoring"
91
+ Requires-Dist: sentry-sdk==2.43.0; extra == "monitoring"
92
92
  Provides-Extra: lint
93
93
  Requires-Dist: autoflake==2.3.1; extra == "lint"
94
- Requires-Dist: black==25.9.0; extra == "lint"
95
- Requires-Dist: pre-commit==4.3.0; extra == "lint"
94
+ Requires-Dist: black==25.11.0; extra == "lint"
95
+ Requires-Dist: pre-commit==4.4.0; extra == "lint"
96
96
  Dynamic: license-file
97
97
  Dynamic: requires-python
98
98