zou 0.20.0__py3-none-any.whl → 0.20.1__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.0"
1
+ __version__ = "0.20.1"
@@ -8,7 +8,7 @@ from flask_restful import Resource
8
8
  from zou import __version__
9
9
 
10
10
  from zou.app import app, config
11
- from zou.app.utils import permissions, shell, date_helpers
11
+ from zou.app.utils import permissions, shell, date_helpers, redis
12
12
  from zou.app.services import projects_service, stats_service, persons_service
13
13
 
14
14
  from flask_jwt_extended import jwt_required
@@ -62,15 +62,7 @@ class BaseStatusResource(Resource):
62
62
 
63
63
  is_jq_up = True
64
64
  try:
65
- host = config.KEY_VALUE_STORE["host"]
66
- port = config.KEY_VALUE_STORE["port"]
67
- db = config.KV_JOB_DB_INDEX
68
- password = config.KEY_VALUE_STORE["password"]
69
- if password:
70
- url = "redis://:%s@%s:%s/%s" % (password, host, port, db)
71
- else:
72
- url = "redis://%s:%s/%s" % (host, port, db)
73
- args = ["rq", "info", "--url", url]
65
+ args = ["rq", "info", "--url", redis.get_redis_url()]
74
66
  out = shell.run_command(args)
75
67
  is_jq_up = b"0 workers" not in out
76
68
  except Exception:
@@ -2,6 +2,7 @@ from flask import Blueprint
2
2
  from zou.app.utils.api import configure_api_from_blueprint
3
3
 
4
4
  from zou.app.blueprints.previews.resources import (
5
+ AddCommentsPreviewsResource,
5
6
  AttachmentThumbnailResource,
6
7
  CreatePreviewFilePictureResource,
7
8
  PreviewFileLowMovieResource,
@@ -37,6 +38,10 @@ routes = [
37
38
  "/pictures/preview-files/<instance_id>",
38
39
  CreatePreviewFilePictureResource,
39
40
  ),
41
+ (
42
+ "/actions/tasks/<task_id>/add-comments-previews",
43
+ AddCommentsPreviewsResource,
44
+ ),
40
45
  (
41
46
  "/movies/originals/preview-files/<instance_id>.mp4",
42
47
  PreviewFileMovieResource,
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import orjson as json
2
3
 
3
4
  from flask import abort, request, current_app
4
5
  from flask import send_file as flask_send_file
@@ -207,107 +208,11 @@ def send_storage_file(
207
208
  raise FileNotFound
208
209
 
209
210
 
210
- class CreatePreviewFilePictureResource(Resource, ArgsMixin):
211
+ class BaseNewPreviewFilePicture:
211
212
  """
212
- Main resource to add a preview. It stores the preview file and generates
213
- three picture files matching preview when it's possible: a square thumbnail,
214
- a rectangle thumbnail and a midsize file.
213
+ Base class to add previews.
215
214
  """
216
215
 
217
- @jwt_required()
218
- def post(self, instance_id):
219
- """
220
- Main resource to add a preview.
221
- ---
222
- tags:
223
- - Previews
224
- description: "It stores the preview file and generates three picture files matching preview when it's possible: a square thumbnail, a rectangle thumbnail and a midsize file."
225
- consumes:
226
- - multipart/form-data
227
- - image/png
228
- - application/pdf
229
- parameters:
230
- - in: path
231
- name: instance_id
232
- required: True
233
- type: string
234
- format: UUID
235
- x-example: a24a6ea4-ce75-4665-a070-57453082c25
236
- - in: formData
237
- name: file
238
- required: True
239
- type: file
240
- responses:
241
- 200:
242
- description: Preview added
243
- """
244
- if not self.is_exist(instance_id):
245
- abort(404)
246
-
247
- if not self.is_allowed(instance_id):
248
- abort(403)
249
-
250
- uploaded_file = request.files["file"]
251
-
252
- file_name_parts = uploaded_file.filename.split(".")
253
- extension = file_name_parts.pop().lower()
254
- original_file_name = ".".join(file_name_parts)
255
-
256
- if extension in ALLOWED_PICTURE_EXTENSION:
257
- metadada = self.save_picture_preview(instance_id, uploaded_file)
258
- preview_file = preview_files_service.update_preview_file(
259
- instance_id,
260
- {
261
- "extension": "png",
262
- "original_name": original_file_name,
263
- "width": metadada["width"],
264
- "height": metadada["height"],
265
- "file_size": metadada["file_size"],
266
- "status": "ready",
267
- },
268
- )
269
- tasks_service.update_preview_file_info(preview_file)
270
- self.emit_app_preview_event(instance_id)
271
- return preview_file, 201
272
-
273
- elif extension in ALLOWED_MOVIE_EXTENSION:
274
- try:
275
- normalize = self.get_bool_parameter("normalize", "true")
276
- self.save_movie_preview(instance_id, uploaded_file, normalize)
277
- except Exception as e:
278
- current_app.logger.error(e, exc_info=1)
279
- current_app.logger.error("Normalization failed.")
280
- deletion_service.remove_preview_file_by_id(
281
- instance_id, force=True
282
- )
283
- abort(400, "Normalization failed.")
284
- preview_file = preview_files_service.update_preview_file(
285
- instance_id,
286
- {"extension": "mp4", "original_name": original_file_name},
287
- )
288
- self.emit_app_preview_event(instance_id)
289
- return preview_file, 201
290
-
291
- elif extension in ALLOWED_FILE_EXTENSION:
292
- self.save_file_preview(instance_id, uploaded_file, extension)
293
- preview_file = preview_files_service.update_preview_file(
294
- instance_id,
295
- {
296
- "extension": extension,
297
- "original_name": original_file_name,
298
- "status": "ready",
299
- },
300
- )
301
- self.emit_app_preview_event(instance_id)
302
- return preview_file, 201
303
-
304
- else:
305
- current_app.logger.info(
306
- "Wrong file format, extension: %s", extension
307
- )
308
- deletion_service.remove_preview_file_by_id(instance_id)
309
- abort(400, "Wrong file format, extension: %s" % extension)
310
-
311
216
  def save_picture_preview(self, instance_id, uploaded_file):
312
217
  """
313
218
  Get uploaded picture, build thumbnails then save everything in the file
@@ -396,6 +301,115 @@ class CreatePreviewFilePictureResource(Resource, ArgsMixin):
396
301
  project_id=task["project_id"],
397
302
  )
398
303
 
304
+ def process_uploaded_file(
305
+ self, instance_id, uploaded_file, abort_on_failed=False
306
+ ):
307
+ file_name_parts = uploaded_file.filename.split(".")
308
+ extension = file_name_parts.pop().lower()
309
+ original_file_name = ".".join(file_name_parts)
310
+ preview_file = None
311
+ if extension in ALLOWED_PICTURE_EXTENSION:
312
+ metadada = self.save_picture_preview(instance_id, uploaded_file)
313
+ preview_file = preview_files_service.update_preview_file(
314
+ instance_id,
315
+ {
316
+ "extension": "png",
317
+ "original_name": original_file_name,
318
+ "width": metadada["width"],
319
+ "height": metadada["height"],
320
+ "file_size": metadada["file_size"],
321
+ "status": "ready",
322
+ },
323
+ )
324
+ tasks_service.update_preview_file_info(preview_file)
325
+ elif extension in ALLOWED_MOVIE_EXTENSION:
326
+ try:
327
+ normalize = self.get_bool_parameter("normalize", "true")
328
+ self.save_movie_preview(instance_id, uploaded_file, normalize)
329
+ except Exception as e:
330
+ current_app.logger.error(e, exc_info=1)
331
+ current_app.logger.error("Normalization failed.")
332
+ deletion_service.remove_preview_file_by_id(
333
+ instance_id, force=True
334
+ )
335
+ if abort_on_failed:
336
+ abort(400, "Normalization failed.")
337
+ preview_file = preview_files_service.update_preview_file(
338
+ instance_id,
339
+ {"extension": "mp4", "original_name": original_file_name},
340
+ )
341
+ elif extension in ALLOWED_FILE_EXTENSION:
342
+ self.save_file_preview(instance_id, uploaded_file, extension)
343
+ preview_file = preview_files_service.update_preview_file(
344
+ instance_id,
345
+ {
346
+ "extension": extension,
347
+ "original_name": original_file_name,
348
+ "status": "ready",
349
+ },
350
+ )
351
+
352
+ if preview_file is None:
353
+ current_app.logger.info(
354
+ "Wrong file format, extension: %s", extension
355
+ )
356
+ deletion_service.remove_preview_file_by_id(instance_id)
357
+ if abort_on_failed:
358
+ abort(400, "Wrong file format, extension: %s" % extension)
359
+ else:
360
+ self.emit_app_preview_event(instance_id)
361
+ return preview_file
362
+
363
+
364
+ class CreatePreviewFilePictureResource(
365
+ BaseNewPreviewFilePicture, Resource, ArgsMixin
366
+ ):
367
+ """
368
+ Main resource to add a preview. It stores the preview file and generates
369
+ three picture files matching preview when it's possible: a square thumbnail,
370
+ a rectangle thumbnail and a midsize file.
371
+ """
372
+
373
+ @jwt_required()
374
+ def post(self, instance_id):
375
+ """
376
+ Main resource to add a preview.
377
+ ---
378
+ tags:
379
+ - Previews
380
+ description: "It stores the preview file and generates three picture files matching preview when it's possible: a square thumbnail, a rectangle thumbnail and a midsize file."
381
+ consumes:
382
+ - multipart/form-data
383
+ - image/png
384
+ - application/pdf
385
+ parameters:
386
+ - in: path
387
+ name: instance_id
388
+ required: True
389
+ type: string
390
+ format: UUID
391
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
392
+ - in: formData
393
+ name: file
394
+ required: True
395
+ type: file
396
+ responses:
397
+ 200:
398
+ description: Preview added
399
+ """
400
+ if not self.is_exist(instance_id):
401
+ abort(404)
402
+
403
+ if not self.is_allowed(instance_id):
404
+ abort(403)
405
+
406
+ return (
407
+ self.process_uploaded_file(
408
+ instance_id, request.files["file"], abort_on_failed=True
409
+ ),
410
+ 201,
411
+ )
412
+
399
413
  def is_allowed(self, preview_file_id):
400
414
  """
401
415
  Return true if user is allowed to add a preview.
@@ -422,6 +436,122 @@ class CreatePreviewFilePictureResource(Resource, ArgsMixin):
422
436
  return files_service.get_preview_file(preview_file_id) is not None
423
437
 
424
438
 
439
+ class AddCommentsPreviewsResource(
440
+ BaseNewPreviewFilePicture, Resource, ArgsMixin
441
+ ):
442
+ """
443
+ Creates new comments for given task. Each comments requires a text, a
444
+ task_status and a person as arguments.
445
+ """
446
+
447
+ @jwt_required()
448
+ def post(self, task_id):
449
+ """
450
+ Creates new comments for given task. Each comments requires a text, a
451
+ task_status and a person as arguments.
452
+ ---
453
+ tags:
454
+ - Comments
455
+ description: Creates new comments for given task. Each comments requires
456
+ a text, a task_status and a person as arguments.
457
+ parameters:
458
+ - in: path
459
+ name: task_id
460
+ required: True
461
+ type: string
462
+ format: UUID
463
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
464
+ - in: body
465
+ name: Comment
466
+ description: person ID, name, comment, revision and change status of task
467
+ schema:
468
+ type: object
469
+ required:
470
+ - comments
471
+ properties:
472
+ comments:
473
+ type: string
474
+ responses:
475
+ 201:
476
+ description: New comments created
477
+ """
478
+ if request.is_json:
479
+ args = self.get_args(
480
+ [
481
+ {
482
+ "name": "comments",
483
+ "required": True,
484
+ "default": [],
485
+ "type": dict,
486
+ "action": "append",
487
+ "help": "List of comments to add",
488
+ }
489
+ ],
490
+ )
491
+ else:
492
+ args = self.get_args(
493
+ [
494
+ {
495
+ "name": "comments",
496
+ "required": True,
497
+ "default": "[]",
498
+ "help": "List of comments to add",
499
+ }
500
+ ],
501
+ )
502
+ args["comments"] = json.loads(args["comments"])
503
+
504
+ task = tasks_service.get_task(task_id)
505
+ user_service.check_project_access(task["project_id"])
506
+ user_service.check_entity_access(task["entity_id"])
507
+
508
+ new_comments = []
509
+ for i, comment in enumerate(args["comments"]):
510
+ user_service.check_task_status_access(comment["task_status_id"])
511
+
512
+ if not permissions.has_manager_permissions():
513
+ comment["person_id"] = None
514
+ comment["created_at"] = None
515
+
516
+ new_comment = comments_service.create_comment(
517
+ comment.get("person_id", None),
518
+ task_id,
519
+ comment["task_status_id"],
520
+ comment["text"],
521
+ comment.get("checklist", []),
522
+ {
523
+ k: v
524
+ for (k, v) in request.files.items()
525
+ if f"attachment_file-{i}" in k
526
+ },
527
+ comment.get("created_at", None),
528
+ comment.get("links", []),
529
+ )
530
+
531
+ new_comment["preview_files"] = []
532
+ for uploaded_preview_file in {
533
+ k: v
534
+ for (k, v) in request.files.items()
535
+ if f"preview_file-{i}" in k
536
+ }.values():
537
+ new_preview_file = tasks_service.add_preview_file_to_comment(
538
+ new_comment["id"],
539
+ new_comment["person_id"],
540
+ task_id,
541
+ )
542
+ new_preview_file = self.process_uploaded_file(
543
+ new_preview_file["id"],
544
+ uploaded_preview_file,
545
+ abort_on_failed=False,
546
+ )
547
+ if new_preview_file:
548
+ new_comment["preview_files"].append(new_preview_file)
549
+
550
+ new_comments.append(new_comment)
551
+
552
+ return new_comments, 201
553
+
554
+
425
555
  class BasePreviewFileResource(Resource):
426
556
  """
427
557
  Base class to download a preview file.
@@ -94,8 +94,7 @@ routes = [
94
94
  AddPreviewResource,
95
95
  ),
96
96
  (
97
- "/actions/tasks/<task_id>/comments/<comment_id>/preview-files/"
98
- "<preview_file_id>",
97
+ "/actions/tasks/<task_id>/comments/<comment_id>/preview-files/<preview_file_id>",
99
98
  AddExtraPreviewResource,
100
99
  ),
101
100
  ("/actions/tasks/<task_id>/to-review", ToReviewResource),
@@ -73,9 +73,6 @@ class AddPreviewResource(Resource, ArgsMixin):
73
73
  user_service.check_project_access(task["project_id"])
74
74
  user_service.check_entity_access(task["entity_id"])
75
75
 
76
- tasks_service.clear_comment_cache(comment_id)
77
- comment = tasks_service.get_comment(comment_id)
78
- tasks_service.get_task_status(comment["task_status_id"])
79
76
  person = persons_service.get_current_user()
80
77
  preview_file = tasks_service.add_preview_file_to_comment(
81
78
  comment_id, person["id"], task_id, args["revision"]
@@ -74,9 +74,9 @@ def create_comment(
74
74
  task_id,
75
75
  task_status_id,
76
76
  text,
77
- checklist,
78
- files,
79
- created_at,
77
+ checklist=[],
78
+ files={},
79
+ created_at="",
80
80
  links=[],
81
81
  ):
82
82
  """
@@ -3,15 +3,7 @@ import redis
3
3
  from flask_socketio import SocketIO
4
4
 
5
5
  from zou.app import config
6
-
7
- host = config.KEY_VALUE_STORE["host"]
8
- port = config.KEY_VALUE_STORE["port"]
9
- redis_db = config.KV_EVENTS_DB_INDEX
10
- password = config.KEY_VALUE_STORE["password"]
11
- if password:
12
- redis_url = "redis://:%s@%s:%s/%s" % (password, host, port, redis_db)
13
- else:
14
- redis_url = "redis://%s:%s/%s" % (host, port, redis_db)
6
+ from zou.app.utils.redis import get_redis_url
15
7
 
16
8
  socketio = None
17
9
 
@@ -31,15 +23,15 @@ def init():
31
23
 
32
24
  try:
33
25
  publisher_store = redis.StrictRedis(
34
- host=host,
35
- port=port,
36
- db=redis_db,
37
- password=password,
26
+ host=config.KEY_VALUE_STORE["host"],
27
+ port=config.KEY_VALUE_STORE["port"],
28
+ db=config.KV_EVENTS_DB_INDEX,
29
+ password=config.KEY_VALUE_STORE["password"],
38
30
  decode_responses=True,
39
31
  )
40
32
  publisher_store.get("test")
41
33
  socketio = SocketIO(
42
- message_queue=redis_url,
34
+ message_queue=get_redis_url(),
43
35
  cors_allowed_origins=[],
44
36
  cors_credentials=False,
45
37
  )
zou/app/utils/redis.py ADDED
@@ -0,0 +1,11 @@
1
+ from zou.app import config
2
+
3
+
4
+ def get_redis_url():
5
+ redis_host = config.KEY_VALUE_STORE["host"]
6
+ redis_port = config.KEY_VALUE_STORE["port"]
7
+ db_index = config.KV_EVENTS_DB_INDEX
8
+ redis_password = config.KEY_VALUE_STORE["password"] or ""
9
+ if redis_password:
10
+ redis_password += "@"
11
+ return f"redis://{redis_password}{redis_host}:{redis_port}/{db_index}"
zou/event_stream.py CHANGED
@@ -2,7 +2,7 @@ from gevent import monkey
2
2
 
3
3
  monkey.patch_all()
4
4
 
5
- from flask import Flask, jsonify
5
+ from flask import jsonify
6
6
  from flask_jwt_extended import (
7
7
  get_jwt_identity,
8
8
  jwt_required,
@@ -10,19 +10,15 @@ from flask_jwt_extended import (
10
10
  JWTManager,
11
11
  )
12
12
  from flask_socketio import SocketIO, disconnect, join_room, emit
13
- from flask_sqlalchemy import SQLAlchemy
14
13
 
15
- from zou.app import config
14
+ from zou.app import config, app
16
15
  from zou.app.stores import auth_tokens_store
17
- from zou.app.utils.monitoring import init_monitoring
18
- from zou.app.utils.flask import ORJSONProvider
19
16
  from zou.app.services import persons_service
17
+ from zou.app.utils.redis import get_redis_url
20
18
 
21
19
  server_stats = {"nb_connections": 0}
22
20
  rooms_data = {}
23
21
 
24
- # Review room helpers
25
-
26
22
 
27
23
  def _get_empty_room(current_frame=0):
28
24
  return {
@@ -79,28 +75,6 @@ def _update_room_playing_status(data, room):
79
75
  return room
80
76
 
81
77
 
82
- # Database helpers
83
-
84
-
85
- def get_redis_url():
86
- redis_host = config.KEY_VALUE_STORE["host"]
87
- redis_port = config.KEY_VALUE_STORE["port"]
88
- db_index = config.KV_EVENTS_DB_INDEX
89
- redis_password = config.KEY_VALUE_STORE["password"]
90
- if redis_password:
91
- return "redis://:%s@%s:%s/%s" % (
92
- redis_password,
93
- redis_host,
94
- redis_port,
95
- db_index,
96
- )
97
- else:
98
- return "redis://%s:%s/%s" % (redis_host, redis_port, db_index)
99
-
100
-
101
- # Routes
102
-
103
-
104
78
  def set_info_routes(socketio, app):
105
79
  @app.route("/", methods=["GET"])
106
80
  def index():
@@ -227,12 +201,6 @@ def create_app():
227
201
  socketio = SocketIO(
228
202
  logger=True, cors_allowed_origins=[], cors_credentials=False
229
203
  )
230
- app = Flask(__name__)
231
- app.json = ORJSONProvider(app)
232
- app.config.from_object(config)
233
- init_monitoring(app)
234
- db = SQLAlchemy(app)
235
- app.extensions["sqlalchemy"].db = db
236
204
  set_info_routes(socketio, app)
237
205
  set_application_routes(socketio, app)
238
206
  set_playlist_room_routes(socketio, app)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zou
3
- Version: 0.20.0
3
+ Version: 0.20.1
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
@@ -56,15 +56,15 @@ Requires-Dist: numpy==2.2.1; python_version >= "3.10"
56
56
  Requires-Dist: opencv-python==4.10.0.84
57
57
  Requires-Dist: OpenTimelineIO==0.17.0
58
58
  Requires-Dist: OpenTimelineIO-Plugins==0.17.0
59
- Requires-Dist: orjson==3.10.12
60
- Requires-Dist: pillow==11.0.0
59
+ Requires-Dist: orjson==3.10.13
60
+ Requires-Dist: pillow==11.1.0
61
61
  Requires-Dist: psutil==6.1.1
62
62
  Requires-Dist: psycopg[binary]==3.2.3
63
63
  Requires-Dist: pyotp==2.9.0
64
64
  Requires-Dist: pysaml2==7.5.0
65
65
  Requires-Dist: python-nomad==2.0.1
66
66
  Requires-Dist: python-slugify==8.0.4
67
- Requires-Dist: python-socketio==5.12.0
67
+ Requires-Dist: python-socketio==5.12.1
68
68
  Requires-Dist: pytz==2024.2
69
69
  Requires-Dist: redis==5.2.1
70
70
  Requires-Dist: requests==2.32.3
@@ -1,8 +1,7 @@
1
- zou/__init__.py,sha256=NGIecTe1EEM7UeBjKSJ4vCWuGDWF1ZX4PckW2Eguxps,23
1
+ zou/__init__.py,sha256=vLeo9ejlCoqrCMhLGa4A6lZVsLnza_kfQ2IJBDs4X90,23
2
2
  zou/cli.py,sha256=H18Wg-wqQOsv4F5_bZRDlxskjO-TRwaV1NmQMTH9mdg,18869
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
- zou/event_stream.py,sha256=_tue9Ry3aqCniZpKGhWJaY1Eo_fd6zOAfnzPvh_mJzU,8489
5
- zou/job_settings.py,sha256=_aqBhujt2Q8sXRWIbgbDf-LUdXRdBimdtTc-fZbiXoY,202
4
+ zou/event_stream.py,sha256=jqjjU8ZDkQB_6-O3ORj1b1J-NiNMpjMBr3-USD85M5M,7681
6
5
  zou/app/__init__.py,sha256=7pRqdA79X-UI_kYt8Sz6lIdleNStBxHnXISr-tePVe8,6962
7
6
  zou/app/api.py,sha256=JTB_IMVO8EOoyqx9KdRkiIix0chOLi0yGDY-verUJXA,5127
8
7
  zou/app/config.py,sha256=kYbcTVFgcl2sGtf-cpOOVu3_fVh2P1fLcceLjCvsIfc,6700
@@ -83,15 +82,15 @@ zou/app/blueprints/export/csv/time_spents.py,sha256=yYPtilOxfQD5mBwyh9h-PbTQBpab
83
82
  zou/app/blueprints/files/__init__.py,sha256=7Wty30JW2OXIn-tBFXOWWmPuHnsnxPpH3jNtHvvr9tY,3987
84
83
  zou/app/blueprints/files/resources.py,sha256=8SIV8kaqv3dxyL8nyqG3QiZmk5ZYIvUxw6k1ic-jhBs,69786
85
84
  zou/app/blueprints/index/__init__.py,sha256=Dh3oQiirpg8RCkfVOuk3irIjSvUvuRf0jPxE6oGubz0,828
86
- zou/app/blueprints/index/resources.py,sha256=M_wsZDEAqSGPlUrO4dyKAA4USgwfNyU7jBBfKOJzYFo,8852
85
+ zou/app/blueprints/index/resources.py,sha256=ILcEplt1MGWVuSuV_HyNt90--plqK1N45ZbZWI30rGo,8502
87
86
  zou/app/blueprints/news/__init__.py,sha256=HxBXjC15dVbotNAZ0CLf02iwUjxJr20kgf8_kT_9nwM,505
88
87
  zou/app/blueprints/news/resources.py,sha256=HdLq2NgfKyN2d3hIATBhH3dlk4c50I4dhhvEhhB_NY4,7334
89
88
  zou/app/blueprints/persons/__init__.py,sha256=0cnHHw3K_8OEMm0qOi3wKVomSAg9IJSnVjAXabMeHks,3893
90
89
  zou/app/blueprints/persons/resources.py,sha256=PfK6epzRn_kbqN6g9qYiH9XWStFlccTVCYyKxs72Hu8,42764
91
90
  zou/app/blueprints/playlists/__init__.py,sha256=vuEk1F3hFHsmuKWhdepMoLyOzmNKDn1YrjjfcaIz0lQ,1596
92
91
  zou/app/blueprints/playlists/resources.py,sha256=alRlMHypUFErXLsEYxpFK84cdjFJ3YWwamZtW0KcwLY,17211
93
- zou/app/blueprints/previews/__init__.py,sha256=qGohO6LRNZKXBAegINcUXuZlrtxobJKQg84-rQ1L3AU,4202
94
- zou/app/blueprints/previews/resources.py,sha256=BK6G4f92yemlDgKyTCKtN1xJ5R_89bunj1reDRMZ--Y,48098
92
+ zou/app/blueprints/previews/__init__.py,sha256=wz7k1H7VFhpcMhtvjFqfbtjMRZHBcP9qfIYpZPuzVyQ,4343
93
+ zou/app/blueprints/previews/resources.py,sha256=vXkgQTmOaJBn8YN9aiyKsTb50eSKWpaAEvOUAWUdCA0,52312
95
94
  zou/app/blueprints/projects/__init__.py,sha256=Pn3fA5bpNFEPBzxTKJ2foV6osZFflXXSM2l2uZh3ktM,3927
96
95
  zou/app/blueprints/projects/resources.py,sha256=E91Vj9EzId2pxiL50JRfrThiyif1PmzWS1oPeMThzQI,31544
97
96
  zou/app/blueprints/search/__init__.py,sha256=QCjQIY_85l_orhdEiqav_GifjReuwsjZggN3V0GeUVY,356
@@ -126,8 +125,8 @@ zou/app/blueprints/source/shotgun/steps.py,sha256=-JR_fYa4sKS-qflWvUQB6617uQvepI
126
125
  zou/app/blueprints/source/shotgun/tasks.py,sha256=XXBRe9QhhS-kuZeV3HitOnpf7mmWVxfpmvl1uo5wq7A,4631
127
126
  zou/app/blueprints/source/shotgun/team.py,sha256=GF7y2BwDeFJCiidtG68icfCi-uV1-b96YKiH8KR54iE,1819
128
127
  zou/app/blueprints/source/shotgun/versions.py,sha256=8Mb35e5p3FLbbiu6AZb9tJErDKz2pPRBdIYu80Ayj7w,2292
129
- zou/app/blueprints/tasks/__init__.py,sha256=pNUqVEVX1KVu1IzRRJNsziPkhWKXqgyvQsNp7LbmIxo,4342
130
- zou/app/blueprints/tasks/resources.py,sha256=GFYT48NBiIn5QodoMifk1iMb9o2cNQO0HUwYOU3AaVM,56030
128
+ zou/app/blueprints/tasks/__init__.py,sha256=udtTZJVViawRAPu8dO_OoyVzQTheLYWTHeTnrC-2RDA,4331
129
+ zou/app/blueprints/tasks/resources.py,sha256=pzLcbTk0UnM7ZJ4h4kAEElzS92fcvrT6KeFXyL6qEY4,55855
131
130
  zou/app/blueprints/user/__init__.py,sha256=H9zCHcVobC6jq6dTToXKAjnZmDA0a9gChHiIP3BcZsc,4586
132
131
  zou/app/blueprints/user/resources.py,sha256=loCigQvPCoRw6nVu_9TIY7pjUByJgk6vutFPSo0MwzI,39891
133
132
  zou/app/file_trees/default.json,sha256=ryUrEmQYE8B_WkzCoQLgmem3N9yNwMIWx9G8p3HfG9o,2310
@@ -185,7 +184,7 @@ zou/app/services/backup_service.py,sha256=_ZtZp6wkcVYnHxBosziwLGdrTvsUttXGphiydq
185
184
  zou/app/services/base_service.py,sha256=OZd0STFh-DyBBdwsmA7DMMnrwv4C8wJUbShvZ1isndU,1383
186
185
  zou/app/services/breakdown_service.py,sha256=-bH1KUq9-No_OKnQtWK4XEU1w7uDPJnzWFMrKNkS1K0,27593
187
186
  zou/app/services/chats_service.py,sha256=pqnT-RCltdf9Dp4t-2NtOSawGk0jyNhVPTgERZ_nYvk,8297
188
- zou/app/services/comments_service.py,sha256=3O54dozhw3x4VkYBoLoQPant-A3H1lHBURWluLO9TBE,18590
187
+ zou/app/services/comments_service.py,sha256=RglVtc7tLUju0cpdIZAv2Xvxr-7iGDp3IPg1T0BHhI4,18599
189
188
  zou/app/services/concepts_service.py,sha256=sXzMPQ5Rav-c_36CBxdDBjKNq0-gaLWFY9QZGy3jjv4,11252
190
189
  zou/app/services/custom_actions_service.py,sha256=fWISEOOdthadrxeHuacEel5Xj6msn0yWXJQDG1gzvsY,297
191
190
  zou/app/services/deletion_service.py,sha256=GdPWmw60_EmWxJohvqQ9KRcION7_PIdQgbl7nr2g2mY,17429
@@ -217,7 +216,7 @@ zou/app/services/user_service.py,sha256=csEwaX2VW-CTY4mexD0yTaNb2i0cN2LECeBnzjSy
217
216
  zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
217
  zou/app/stores/auth_tokens_store.py,sha256=-qOJPybLHvnMOq3PWk073OW9HJwOHGhFLZeOIlX1UVw,1290
219
218
  zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
220
- zou/app/stores/publisher_store.py,sha256=-RLHL2VoJEqqPldLczBNpTeJxlAUUJpwRZHYlFN9Hm0,1217
219
+ zou/app/stores/publisher_store.py,sha256=MwntYNpwRvOAiDMm0-0soNw7DR8U4sHipol-eS4iePY,1051
221
220
  zou/app/stores/queue_store.py,sha256=udbZSm3Rfwi-zwSRzVz-0qjdrVYbUWA8WwuIsdQikn8,669
222
221
  zou/app/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
223
222
  zou/app/utils/api.py,sha256=28ys2SMso1wt0q7r-4ohx9Izx-cKHxQhCmxfTvTMeFs,705
@@ -241,6 +240,7 @@ zou/app/utils/logs.py,sha256=lB6kyFmeANxCILUULLqGN8fuq9IY5FcbrVWmLdqWs2U,1404
241
240
  zou/app/utils/monitoring.py,sha256=xOwyfM-7ZKWNtOxmX2WB1fOav5NpY6k8Tmuhli0nMBs,2082
242
241
  zou/app/utils/permissions.py,sha256=Oq91C_lN6aGVCtCVUqQhijMQEjXOiMezbngpjybzzQk,3426
243
242
  zou/app/utils/query.py,sha256=q8ETGPAqnz0Pt9xWoQt5o7FFAVYUKVCJiWpwefIr-iU,4592
243
+ zou/app/utils/redis.py,sha256=im7Q6C5qDVKq2RZbF1vYKPgn0rhzR3Ci-VbAnPAUgcQ,377
244
244
  zou/app/utils/remote_job.py,sha256=QPxcCWEv-NM1Q4IQawAyJAiSORwkMeOlByQb9OCShEw,2522
245
245
  zou/app/utils/saml.py,sha256=m8wt_2RnMEHSrFvqCRGF91U5mwkqC6W-iBcx8N0LAqs,1679
246
246
  zou/app/utils/shell.py,sha256=D30NuOzr1D6jsa9OF69JYXyqYNhtIdnfKSVYW4irbz8,405
@@ -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.20.0.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
417
- zou-0.20.0.dist-info/METADATA,sha256=0NMumLrVJLaAmxKYEm9MSIE7RD3ZzzuPM3NszQa8Q0U,6708
418
- zou-0.20.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
419
- zou-0.20.0.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
420
- zou-0.20.0.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
421
- zou-0.20.0.dist-info/RECORD,,
416
+ zou-0.20.1.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
417
+ zou-0.20.1.dist-info/METADATA,sha256=cfz1OOkN4FuaLJWTQ-r5KOdzF4W1Q7W-O7Z5yPzsFTI,6708
418
+ zou-0.20.1.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
419
+ zou-0.20.1.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
420
+ zou-0.20.1.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
421
+ zou-0.20.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
zou/job_settings.py DELETED
@@ -1,6 +0,0 @@
1
- from zou.app import config
2
-
3
- REDIS_HOST = config.KEY_VALUE_STORE["host"]
4
- REDIS_PORT = config.KEY_VALUE_STORE["port"]
5
- REDIS_DB = config.KV_JOB_DB_INDEX
6
- REDIS_PASSWORD = config.KEY_VALUE_STORE["password"]
File without changes