zou 0.20.0__py3-none-any.whl → 0.20.2__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 +1 -1
- zou/app/blueprints/index/resources.py +1 -10
- zou/app/blueprints/previews/__init__.py +5 -0
- zou/app/blueprints/previews/resources.py +228 -98
- zou/app/blueprints/tasks/__init__.py +1 -2
- zou/app/blueprints/tasks/resources.py +0 -3
- zou/app/services/comments_service.py +3 -3
- zou/app/stores/publisher_store.py +6 -14
- zou/app/utils/redis.py +11 -0
- zou/event_stream.py +3 -35
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/METADATA +4 -4
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/RECORD +16 -16
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/WHEEL +1 -1
- zou/job_settings.py +0 -6
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/LICENSE +0 -0
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/entry_points.txt +0 -0
- {zou-0.20.0.dist-info → zou-0.20.2.dist-info}/top_level.txt +0 -0
zou/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.20.
|
|
1
|
+
__version__ = "0.20.2"
|
|
@@ -10,7 +10,6 @@ from zou import __version__
|
|
|
10
10
|
from zou.app import app, config
|
|
11
11
|
from zou.app.utils import permissions, shell, date_helpers
|
|
12
12
|
from zou.app.services import projects_service, stats_service, persons_service
|
|
13
|
-
|
|
14
13
|
from flask_jwt_extended import jwt_required
|
|
15
14
|
|
|
16
15
|
|
|
@@ -62,15 +61,7 @@ class BaseStatusResource(Resource):
|
|
|
62
61
|
|
|
63
62
|
is_jq_up = True
|
|
64
63
|
try:
|
|
65
|
-
|
|
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]
|
|
64
|
+
args = ["rq", "info", "--url", redis.get_redis_url()]
|
|
74
65
|
out = shell.run_command(args)
|
|
75
66
|
is_jq_up = b"0 workers" not in out
|
|
76
67
|
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
|
|
211
|
+
class BaseNewPreviewFilePicture:
|
|
211
212
|
"""
|
|
212
|
-
|
|
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"]
|
|
@@ -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=
|
|
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=
|
|
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
|
|
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.
|
|
3
|
+
Version: 0.20.2
|
|
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.
|
|
60
|
-
Requires-Dist: pillow==11.
|
|
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.
|
|
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=
|
|
1
|
+
zou/__init__.py,sha256=WRDggaYcSjn5kcl6mpNUIM5VWOlcd9HZTeEz-I3_kvQ,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=
|
|
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=
|
|
85
|
+
zou/app/blueprints/index/resources.py,sha256=bJ001pBi9uKaOtfHazzfj_wMpAImT_U7L1EbQOkm-h8,8494
|
|
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=
|
|
94
|
-
zou/app/blueprints/previews/resources.py,sha256=
|
|
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=
|
|
130
|
-
zou/app/blueprints/tasks/resources.py,sha256=
|
|
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=
|
|
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
|
|
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.
|
|
417
|
-
zou-0.20.
|
|
418
|
-
zou-0.20.
|
|
419
|
-
zou-0.20.
|
|
420
|
-
zou-0.20.
|
|
421
|
-
zou-0.20.
|
|
416
|
+
zou-0.20.2.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
|
|
417
|
+
zou-0.20.2.dist-info/METADATA,sha256=x35J_KVDGGpKulbt6-TR9SszF6AESVOte8zzxBaR_Lk,6708
|
|
418
|
+
zou-0.20.2.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
|
419
|
+
zou-0.20.2.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
|
|
420
|
+
zou-0.20.2.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
|
|
421
|
+
zou-0.20.2.dist-info/RECORD,,
|
zou/job_settings.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|