zou 0.19.44__py3-none-any.whl → 0.19.46__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/auth/resources.py +0 -2
- zou/app/blueprints/comments/resources.py +4 -1
- zou/app/blueprints/crud/entity.py +5 -5
- zou/app/blueprints/events/resources.py +2 -4
- zou/app/blueprints/files/resources.py +12 -3
- zou/app/blueprints/previews/__init__.py +3 -8
- zou/app/blueprints/previews/resources.py +195 -223
- zou/app/blueprints/shots/__init__.py +1 -1
- zou/app/blueprints/shots/resources.py +4 -5
- zou/app/mixin.py +3 -3
- zou/app/services/auth_service.py +0 -19
- zou/app/services/comments_service.py +2 -2
- zou/app/services/shots_service.py +15 -14
- zou/app/stores/auth_tokens_store.py +1 -1
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/METADATA +11 -10
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/RECORD +21 -21
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/WHEEL +1 -1
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/LICENSE +0 -0
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/entry_points.txt +0 -0
- {zou-0.19.44.dist-info → zou-0.19.46.dist-info}/top_level.txt +0 -0
zou/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.19.
|
|
1
|
+
__version__ = "0.19.46"
|
|
@@ -217,7 +217,6 @@ class LoginResource(Resource, ArgsMixin):
|
|
|
217
217
|
"identity_type": "person",
|
|
218
218
|
},
|
|
219
219
|
)
|
|
220
|
-
auth_service.register_tokens(app, access_token, refresh_token)
|
|
221
220
|
identity_changed.send(
|
|
222
221
|
current_app._get_current_object(),
|
|
223
222
|
identity=Identity(user["id"], "person"),
|
|
@@ -383,7 +382,6 @@ class RefreshTokenResource(Resource):
|
|
|
383
382
|
"identity_type": "person",
|
|
384
383
|
},
|
|
385
384
|
)
|
|
386
|
-
auth_service.register_tokens(app, access_token)
|
|
387
385
|
if is_from_browser(request.user_agent):
|
|
388
386
|
response = jsonify({"refresh": True})
|
|
389
387
|
set_access_cookies(response, access_token)
|
|
@@ -5,7 +5,7 @@ from flask_restful import Resource, reqparse
|
|
|
5
5
|
from flask_jwt_extended import jwt_required
|
|
6
6
|
|
|
7
7
|
from zou.app.mixin import ArgsMixin
|
|
8
|
-
from zou.app.utils import permissions
|
|
8
|
+
from zou.app.utils import permissions, date_helpers
|
|
9
9
|
|
|
10
10
|
from zou.app.services import (
|
|
11
11
|
chats_service,
|
|
@@ -80,6 +80,9 @@ class DownloadAttachmentResource(Resource):
|
|
|
80
80
|
as_attachment=False,
|
|
81
81
|
download_name=attachment_file["name"],
|
|
82
82
|
max_age=config.CLIENT_CACHE_MAX_AGE,
|
|
83
|
+
last_modified=date_helpers.get_datetime_from_string(
|
|
84
|
+
attachment_file["updated_at"]
|
|
85
|
+
),
|
|
83
86
|
)
|
|
84
87
|
except Exception:
|
|
85
88
|
current_app.logger.error(
|
|
@@ -23,7 +23,7 @@ from zou.app.services import (
|
|
|
23
23
|
user_service,
|
|
24
24
|
concepts_service,
|
|
25
25
|
)
|
|
26
|
-
from zou.app.utils import events,
|
|
26
|
+
from zou.app.utils import events, date_helpers
|
|
27
27
|
|
|
28
28
|
from werkzeug.exceptions import NotFound
|
|
29
29
|
|
|
@@ -187,11 +187,11 @@ class EntityResource(BaseModelResource, EntityEventMixin):
|
|
|
187
187
|
version = None
|
|
188
188
|
if frame_in != pframe_in or frame_out != pframe_out or name != pname:
|
|
189
189
|
current_user_id = persons_service.get_current_user()["id"]
|
|
190
|
-
previous_updated_at =
|
|
191
|
-
previous_shot["updated_at"]
|
|
190
|
+
previous_updated_at = date_helpers.get_datetime_from_string(
|
|
191
|
+
previous_shot["updated_at"]
|
|
192
192
|
)
|
|
193
|
-
updated_at =
|
|
194
|
-
shot["updated_at"]
|
|
193
|
+
updated_at = date_helpers.get_datetime_from_string(
|
|
194
|
+
shot["updated_at"]
|
|
195
195
|
)
|
|
196
196
|
if (
|
|
197
197
|
date_helpers.get_date_diff(previous_updated_at, updated_at)
|
|
@@ -2,7 +2,7 @@ from flask_restful import Resource
|
|
|
2
2
|
from flask_jwt_extended import jwt_required
|
|
3
3
|
|
|
4
4
|
from zou.app.mixin import ArgsMixin
|
|
5
|
-
from zou.app.utils import fields, permissions
|
|
5
|
+
from zou.app.utils import fields, permissions, date_helpers
|
|
6
6
|
|
|
7
7
|
from zou.app.services import events_service
|
|
8
8
|
from zou.app.services.exception import WrongParameterException
|
|
@@ -105,8 +105,6 @@ class LoginLogsResource(Resource, ArgsMixin):
|
|
|
105
105
|
permissions.check_manager_permissions()
|
|
106
106
|
before = None
|
|
107
107
|
if args["before"] is not None:
|
|
108
|
-
before =
|
|
109
|
-
args["before"], "%Y-%m-%dT%H:%M:%S"
|
|
110
|
-
)
|
|
108
|
+
before = date_helpers.get_datetime_from_string(args["before"])
|
|
111
109
|
page_size = args["page_size"]
|
|
112
110
|
return events_service.get_last_login_logs(before, page_size)
|
|
@@ -32,7 +32,10 @@ from zou.app.services.exception import (
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def send_storage_file(
|
|
35
|
-
working_file_id,
|
|
35
|
+
working_file_id,
|
|
36
|
+
as_attachment=False,
|
|
37
|
+
max_age=config.CLIENT_CACHE_MAX_AGE,
|
|
38
|
+
last_modified=None,
|
|
36
39
|
):
|
|
37
40
|
"""
|
|
38
41
|
Send file from storage. If it's not a local storage, cache the file in
|
|
@@ -60,6 +63,7 @@ def send_storage_file(
|
|
|
60
63
|
as_attachment=as_attachment,
|
|
61
64
|
download_name=download_name,
|
|
62
65
|
max_age=max_age,
|
|
66
|
+
last_modified=last_modified,
|
|
63
67
|
)
|
|
64
68
|
except IOError as e:
|
|
65
69
|
current_app.logger.error(e)
|
|
@@ -125,8 +129,13 @@ class WorkingFileFileResource(Resource):
|
|
|
125
129
|
schema:
|
|
126
130
|
type: file
|
|
127
131
|
"""
|
|
128
|
-
self.check_access(working_file_id)
|
|
129
|
-
return send_storage_file(
|
|
132
|
+
working_file = self.check_access(working_file_id)
|
|
133
|
+
return send_storage_file(
|
|
134
|
+
working_file_id,
|
|
135
|
+
last_modified=date_helpers.get_datetime_from_string(
|
|
136
|
+
working_file["updated_at"]
|
|
137
|
+
),
|
|
138
|
+
)
|
|
130
139
|
|
|
131
140
|
@jwt_required()
|
|
132
141
|
def post(self, working_file_id):
|
|
@@ -14,14 +14,13 @@ from zou.app.blueprints.previews.resources import (
|
|
|
14
14
|
PreviewFilePreviewResource,
|
|
15
15
|
PreviewFileOriginalResource,
|
|
16
16
|
PreviewFileTileResource,
|
|
17
|
-
CreateOrganisationThumbnailResource,
|
|
18
17
|
OrganisationThumbnailResource,
|
|
19
|
-
|
|
18
|
+
CreateOrganisationThumbnailResource,
|
|
20
19
|
ProjectThumbnailResource,
|
|
21
|
-
|
|
20
|
+
CreateProjectThumbnailResource,
|
|
22
21
|
PersonThumbnailResource,
|
|
22
|
+
CreatePersonThumbnailResource,
|
|
23
23
|
RunningPreviewFiles,
|
|
24
|
-
LegacySetMainPreviewResource,
|
|
25
24
|
SetMainPreviewResource,
|
|
26
25
|
UpdateAnnotationsResource,
|
|
27
26
|
UpdatePreviewPositionResource,
|
|
@@ -118,10 +117,6 @@ routes = [
|
|
|
118
117
|
"/pictures/preview-background-files/<instance_id>.<extension>",
|
|
119
118
|
PreviewBackgroundFileResource,
|
|
120
119
|
),
|
|
121
|
-
(
|
|
122
|
-
"/actions/entities/<entity_id>/set-main-preview/<preview_file_id>",
|
|
123
|
-
LegacySetMainPreviewResource,
|
|
124
|
-
),
|
|
125
120
|
(
|
|
126
121
|
"/actions/preview-files/<preview_file_id>/set-main-preview",
|
|
127
122
|
SetMainPreviewResource,
|
|
@@ -32,6 +32,7 @@ from zou.app.utils import (
|
|
|
32
32
|
events,
|
|
33
33
|
permissions,
|
|
34
34
|
thumbnail as thumbnail_utils,
|
|
35
|
+
date_helpers,
|
|
35
36
|
)
|
|
36
37
|
from zou.app.services.exception import (
|
|
37
38
|
ArgumentsException,
|
|
@@ -86,6 +87,7 @@ def send_standard_file(
|
|
|
86
87
|
extension,
|
|
87
88
|
mimetype="application/octet-stream",
|
|
88
89
|
as_attachment=False,
|
|
90
|
+
last_modified=None,
|
|
89
91
|
):
|
|
90
92
|
return send_storage_file(
|
|
91
93
|
file_store.get_local_file_path,
|
|
@@ -95,10 +97,13 @@ def send_standard_file(
|
|
|
95
97
|
extension,
|
|
96
98
|
mimetype=mimetype,
|
|
97
99
|
as_attachment=as_attachment,
|
|
100
|
+
last_modified=last_modified,
|
|
98
101
|
)
|
|
99
102
|
|
|
100
103
|
|
|
101
|
-
def send_movie_file(
|
|
104
|
+
def send_movie_file(
|
|
105
|
+
preview_file_id, as_attachment=False, lowdef=False, last_modified=None
|
|
106
|
+
):
|
|
102
107
|
folder = "previews"
|
|
103
108
|
if lowdef:
|
|
104
109
|
folder = "lowdef"
|
|
@@ -110,6 +115,7 @@ def send_movie_file(preview_file_id, as_attachment=False, lowdef=False):
|
|
|
110
115
|
"mp4",
|
|
111
116
|
mimetype="video/mp4",
|
|
112
117
|
as_attachment=as_attachment,
|
|
118
|
+
last_modified=last_modified,
|
|
113
119
|
)
|
|
114
120
|
|
|
115
121
|
|
|
@@ -119,6 +125,7 @@ def send_picture_file(
|
|
|
119
125
|
as_attachment=False,
|
|
120
126
|
extension="png",
|
|
121
127
|
download_name="",
|
|
128
|
+
last_modified=None,
|
|
122
129
|
):
|
|
123
130
|
if extension == "png":
|
|
124
131
|
mimetype = "image/png"
|
|
@@ -133,6 +140,7 @@ def send_picture_file(
|
|
|
133
140
|
mimetype=mimetype,
|
|
134
141
|
as_attachment=as_attachment,
|
|
135
142
|
download_name=download_name,
|
|
143
|
+
last_modified=last_modified,
|
|
136
144
|
)
|
|
137
145
|
|
|
138
146
|
|
|
@@ -146,6 +154,7 @@ def send_storage_file(
|
|
|
146
154
|
as_attachment=False,
|
|
147
155
|
max_age=config.CLIENT_CACHE_MAX_AGE,
|
|
148
156
|
download_name="",
|
|
157
|
+
last_modified=None,
|
|
149
158
|
):
|
|
150
159
|
"""
|
|
151
160
|
Send file from storage. If it's not a local storage, cache the file in
|
|
@@ -189,6 +198,7 @@ def send_storage_file(
|
|
|
189
198
|
as_attachment=as_attachment,
|
|
190
199
|
download_name=download_name,
|
|
191
200
|
max_age=max_age,
|
|
201
|
+
last_modified=last_modified,
|
|
192
202
|
)
|
|
193
203
|
except IOError as e:
|
|
194
204
|
current_app.logger.error(e)
|
|
@@ -410,26 +420,30 @@ class CreatePreviewFilePictureResource(Resource, ArgsMixin):
|
|
|
410
420
|
return files_service.get_preview_file(preview_file_id) is not None
|
|
411
421
|
|
|
412
422
|
|
|
413
|
-
class
|
|
423
|
+
class BasePreviewFileResource(Resource):
|
|
414
424
|
"""
|
|
415
|
-
|
|
425
|
+
Base class to download a preview file.
|
|
416
426
|
"""
|
|
417
427
|
|
|
418
428
|
def __init__(self):
|
|
419
429
|
Resource.__init__(self)
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return files_service.get_preview_file(preview_file_id) is not None
|
|
430
|
+
self.preview_file = None
|
|
431
|
+
self.last_modified = None
|
|
423
432
|
|
|
424
433
|
def is_allowed(self, preview_file_id):
|
|
425
|
-
preview_file = files_service.get_preview_file(preview_file_id)
|
|
426
|
-
task = tasks_service.get_task(preview_file["task_id"])
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
434
|
+
self.preview_file = files_service.get_preview_file(preview_file_id)
|
|
435
|
+
task = tasks_service.get_task(self.preview_file["task_id"])
|
|
436
|
+
user_service.check_project_access(task["project_id"])
|
|
437
|
+
user_service.check_entity_access(task["entity_id"])
|
|
438
|
+
self.last_modified = date_helpers.get_datetime_from_string(
|
|
439
|
+
self.preview_file["updated_at"]
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class PreviewFileMovieResource(BasePreviewFileResource):
|
|
444
|
+
"""
|
|
445
|
+
Allow to download a movie preview.
|
|
446
|
+
"""
|
|
433
447
|
|
|
434
448
|
@jwt_required()
|
|
435
449
|
def get(self, instance_id):
|
|
@@ -454,14 +468,12 @@ class PreviewFileMovieResource(Resource):
|
|
|
454
468
|
404:
|
|
455
469
|
description: File not found
|
|
456
470
|
"""
|
|
457
|
-
|
|
458
|
-
abort(404)
|
|
459
|
-
|
|
460
|
-
if not self.is_allowed(instance_id):
|
|
461
|
-
abort(403)
|
|
471
|
+
self.is_allowed(instance_id)
|
|
462
472
|
|
|
463
473
|
try:
|
|
464
|
-
return send_movie_file(
|
|
474
|
+
return send_movie_file(
|
|
475
|
+
instance_id, last_modified=self.last_modified
|
|
476
|
+
)
|
|
465
477
|
except FileNotFound:
|
|
466
478
|
current_app.logger.error(
|
|
467
479
|
"Movie file was not found for: %s" % instance_id
|
|
@@ -469,7 +481,7 @@ class PreviewFileMovieResource(Resource):
|
|
|
469
481
|
abort(404)
|
|
470
482
|
|
|
471
483
|
|
|
472
|
-
class PreviewFileLowMovieResource(
|
|
484
|
+
class PreviewFileLowMovieResource(BasePreviewFileResource):
|
|
473
485
|
"""
|
|
474
486
|
Allow to download a lowdef movie preview.
|
|
475
487
|
"""
|
|
@@ -496,14 +508,17 @@ class PreviewFileLowMovieResource(PreviewFileMovieResource):
|
|
|
496
508
|
404:
|
|
497
509
|
description: File not found
|
|
498
510
|
"""
|
|
499
|
-
|
|
500
|
-
abort(403)
|
|
511
|
+
self.is_allowed(instance_id)
|
|
501
512
|
|
|
502
513
|
try:
|
|
503
|
-
return send_movie_file(
|
|
514
|
+
return send_movie_file(
|
|
515
|
+
instance_id, lowdef=True, last_modified=self.last_modified
|
|
516
|
+
)
|
|
504
517
|
except Exception:
|
|
505
518
|
try:
|
|
506
|
-
return send_movie_file(
|
|
519
|
+
return send_movie_file(
|
|
520
|
+
instance_id, last_modified=self.last_modified
|
|
521
|
+
)
|
|
507
522
|
except FileNotFound:
|
|
508
523
|
current_app.logger.error(
|
|
509
524
|
"Movie file was not found for: %s" % instance_id
|
|
@@ -511,7 +526,7 @@ class PreviewFileLowMovieResource(PreviewFileMovieResource):
|
|
|
511
526
|
abort(404)
|
|
512
527
|
|
|
513
528
|
|
|
514
|
-
class PreviewFileMovieDownloadResource(
|
|
529
|
+
class PreviewFileMovieDownloadResource(BasePreviewFileResource):
|
|
515
530
|
"""
|
|
516
531
|
Allow to download a movie preview.
|
|
517
532
|
"""
|
|
@@ -538,11 +553,14 @@ class PreviewFileMovieDownloadResource(PreviewFileMovieResource):
|
|
|
538
553
|
404:
|
|
539
554
|
description: File not found
|
|
540
555
|
"""
|
|
541
|
-
|
|
542
|
-
abort(403)
|
|
556
|
+
self.is_allowed(instance_id)
|
|
543
557
|
|
|
544
558
|
try:
|
|
545
|
-
return send_movie_file(
|
|
559
|
+
return send_movie_file(
|
|
560
|
+
instance_id,
|
|
561
|
+
as_attachment=True,
|
|
562
|
+
last_modified=self.last_modified,
|
|
563
|
+
)
|
|
546
564
|
except FileNotFound:
|
|
547
565
|
current_app.logger.error(
|
|
548
566
|
"Movie file was not found for: %s" % instance_id
|
|
@@ -550,30 +568,11 @@ class PreviewFileMovieDownloadResource(PreviewFileMovieResource):
|
|
|
550
568
|
abort(404)
|
|
551
569
|
|
|
552
570
|
|
|
553
|
-
class PreviewFileResource(
|
|
571
|
+
class PreviewFileResource(BasePreviewFileResource):
|
|
554
572
|
"""
|
|
555
573
|
Allow to download a generic file preview.
|
|
556
574
|
"""
|
|
557
575
|
|
|
558
|
-
def __init__(self):
|
|
559
|
-
Resource.__init__(self)
|
|
560
|
-
|
|
561
|
-
def is_exist(self, preview_file_id):
|
|
562
|
-
return files_service.get_preview_file(preview_file_id) is not None
|
|
563
|
-
|
|
564
|
-
def is_allowed(self, preview_file_id):
|
|
565
|
-
if permissions.has_manager_permissions():
|
|
566
|
-
return True
|
|
567
|
-
else:
|
|
568
|
-
preview_file = files_service.get_preview_file(preview_file_id)
|
|
569
|
-
task = tasks_service.get_task(preview_file["task_id"])
|
|
570
|
-
try:
|
|
571
|
-
user_service.check_project_access(task["project_id"])
|
|
572
|
-
user_service.check_entity_access(task["entity_id"])
|
|
573
|
-
return True
|
|
574
|
-
except permissions.PermissionDenied:
|
|
575
|
-
return False
|
|
576
|
-
|
|
577
576
|
@jwt_required()
|
|
578
577
|
def get(self, instance_id, extension):
|
|
579
578
|
"""
|
|
@@ -601,21 +600,26 @@ class PreviewFileResource(Resource):
|
|
|
601
600
|
404:
|
|
602
601
|
description: Non-movie file not found
|
|
603
602
|
"""
|
|
604
|
-
|
|
605
|
-
abort(404)
|
|
606
|
-
|
|
607
|
-
if not self.is_allowed(instance_id):
|
|
608
|
-
abort(403)
|
|
603
|
+
self.is_allowed(instance_id)
|
|
609
604
|
|
|
610
605
|
try:
|
|
611
606
|
extension = extension.lower()
|
|
612
607
|
if extension == "png":
|
|
613
|
-
return send_picture_file(
|
|
608
|
+
return send_picture_file(
|
|
609
|
+
"original", instance_id, last_modified=self.last_modified
|
|
610
|
+
)
|
|
614
611
|
elif extension == "pdf":
|
|
615
612
|
mimetype = "application/pdf"
|
|
616
|
-
return send_standard_file(
|
|
613
|
+
return send_standard_file(
|
|
614
|
+
instance_id,
|
|
615
|
+
extension,
|
|
616
|
+
mimetype,
|
|
617
|
+
last_modified=self.last_modified,
|
|
618
|
+
)
|
|
617
619
|
else:
|
|
618
|
-
return send_standard_file(
|
|
620
|
+
return send_standard_file(
|
|
621
|
+
instance_id, extension, last_modified=self.last_modified
|
|
622
|
+
)
|
|
619
623
|
|
|
620
624
|
except FileNotFound:
|
|
621
625
|
current_app.logger.error(
|
|
@@ -624,14 +628,11 @@ class PreviewFileResource(Resource):
|
|
|
624
628
|
abort(404)
|
|
625
629
|
|
|
626
630
|
|
|
627
|
-
class PreviewFileDownloadResource(
|
|
631
|
+
class PreviewFileDownloadResource(BasePreviewFileResource):
|
|
628
632
|
"""
|
|
629
633
|
Allow to download a generic file preview as attachment.
|
|
630
634
|
"""
|
|
631
635
|
|
|
632
|
-
def __init__(self):
|
|
633
|
-
PreviewFileResource.__init__(self)
|
|
634
|
-
|
|
635
636
|
@jwt_required()
|
|
636
637
|
def get(self, instance_id):
|
|
637
638
|
"""
|
|
@@ -654,25 +655,40 @@ class PreviewFileDownloadResource(PreviewFileResource):
|
|
|
654
655
|
404:
|
|
655
656
|
description: Standard file not found
|
|
656
657
|
"""
|
|
657
|
-
|
|
658
|
-
abort(403)
|
|
658
|
+
self.is_allowed(instance_id)
|
|
659
659
|
|
|
660
|
-
|
|
661
|
-
extension = preview_file["extension"]
|
|
660
|
+
extension = self.preview_file["extension"]
|
|
662
661
|
|
|
663
662
|
try:
|
|
664
663
|
if extension == "png":
|
|
665
664
|
return send_picture_file(
|
|
666
|
-
"original",
|
|
665
|
+
"original",
|
|
666
|
+
instance_id,
|
|
667
|
+
as_attachment=True,
|
|
668
|
+
last_modified=self.last_modified,
|
|
667
669
|
)
|
|
668
670
|
elif extension == "pdf":
|
|
669
671
|
mimetype = "application/pdf"
|
|
670
672
|
return send_standard_file(
|
|
671
|
-
instance_id,
|
|
673
|
+
instance_id,
|
|
674
|
+
extension,
|
|
675
|
+
mimetype,
|
|
676
|
+
as_attachment=True,
|
|
677
|
+
last_modified=self.last_modified,
|
|
678
|
+
)
|
|
679
|
+
if extension == "mp4":
|
|
680
|
+
return send_picture_file(
|
|
681
|
+
"original",
|
|
682
|
+
instance_id,
|
|
683
|
+
as_attachment=True,
|
|
684
|
+
last_modified=self.last_modified,
|
|
672
685
|
)
|
|
673
686
|
else:
|
|
674
687
|
return send_standard_file(
|
|
675
|
-
instance_id,
|
|
688
|
+
instance_id,
|
|
689
|
+
extension,
|
|
690
|
+
as_attachment=True,
|
|
691
|
+
last_modified=self.last_modified,
|
|
676
692
|
)
|
|
677
693
|
except FileNotFound:
|
|
678
694
|
current_app.logger.error(
|
|
@@ -683,26 +699,31 @@ class PreviewFileDownloadResource(PreviewFileResource):
|
|
|
683
699
|
|
|
684
700
|
class AttachmentThumbnailResource(Resource):
|
|
685
701
|
|
|
686
|
-
def
|
|
687
|
-
|
|
702
|
+
def __init__(self):
|
|
703
|
+
Resource.__init__(self)
|
|
704
|
+
self.attachment_file = None
|
|
688
705
|
|
|
689
706
|
def is_allowed(self, attachment_id):
|
|
690
|
-
attachment_file = comments_service.get_attachment_file(
|
|
691
|
-
|
|
692
|
-
|
|
707
|
+
self.attachment_file = comments_service.get_attachment_file(
|
|
708
|
+
attachment_id
|
|
709
|
+
)
|
|
710
|
+
if self.attachment_file["comment_id"] is not None:
|
|
711
|
+
comment = tasks_service.get_comment(
|
|
712
|
+
self.attachment_file["comment_id"]
|
|
713
|
+
)
|
|
693
714
|
task = tasks_service.get_task(comment["object_id"])
|
|
694
715
|
user_service.check_project_access(task["project_id"])
|
|
695
716
|
user_service.check_entity_access(task["entity_id"])
|
|
696
|
-
elif attachment_file["chat_message_id"] is not None:
|
|
717
|
+
elif self.attachment_file["chat_message_id"] is not None:
|
|
697
718
|
message = chats_service.get_chat_message(
|
|
698
|
-
attachment_file["chat_message_id"]
|
|
719
|
+
self.attachment_file["chat_message_id"]
|
|
699
720
|
)
|
|
700
721
|
chat = chats_service.get_chat_by_id(message["chat_id"])
|
|
701
722
|
entity = entities_service.get_entity(chat["object_id"])
|
|
702
723
|
user_service.check_project_access(entity["project_id"])
|
|
703
724
|
user_service.check_entity_access(chat["object_id"])
|
|
704
725
|
else:
|
|
705
|
-
|
|
726
|
+
raise permissions.PermissionDenied
|
|
706
727
|
return True
|
|
707
728
|
|
|
708
729
|
@jwt_required()
|
|
@@ -727,14 +748,16 @@ class AttachmentThumbnailResource(Resource):
|
|
|
727
748
|
404:
|
|
728
749
|
description: Picture file not found
|
|
729
750
|
"""
|
|
730
|
-
|
|
731
|
-
abort(404)
|
|
732
|
-
|
|
733
|
-
if not self.is_allowed(attachment_file_id):
|
|
734
|
-
abort(403)
|
|
751
|
+
self.is_allowed(attachment_file_id)
|
|
735
752
|
|
|
736
753
|
try:
|
|
737
|
-
return send_picture_file(
|
|
754
|
+
return send_picture_file(
|
|
755
|
+
"thumbnails",
|
|
756
|
+
attachment_file_id,
|
|
757
|
+
last_modified=date_helpers.get_datetime_from_string(
|
|
758
|
+
self.attachment_file["updated_at"]
|
|
759
|
+
),
|
|
760
|
+
)
|
|
738
761
|
except FileNotFound:
|
|
739
762
|
current_app.logger.error(
|
|
740
763
|
"Picture file was not found for attachment: %s"
|
|
@@ -743,31 +766,15 @@ class AttachmentThumbnailResource(Resource):
|
|
|
743
766
|
abort(404)
|
|
744
767
|
|
|
745
768
|
|
|
746
|
-
class BasePreviewPictureResource(
|
|
769
|
+
class BasePreviewPictureResource(BasePreviewFileResource):
|
|
747
770
|
"""
|
|
748
771
|
Base class to download a thumbnail.
|
|
749
772
|
"""
|
|
750
773
|
|
|
751
774
|
def __init__(self, picture_type):
|
|
752
|
-
|
|
775
|
+
BasePreviewFileResource.__init__(self)
|
|
753
776
|
self.picture_type = picture_type
|
|
754
777
|
|
|
755
|
-
def is_exist(self, preview_file_id):
|
|
756
|
-
return files_service.get_preview_file(preview_file_id) is not None
|
|
757
|
-
|
|
758
|
-
def is_allowed(self, preview_file_id):
|
|
759
|
-
if permissions.has_manager_permissions():
|
|
760
|
-
return True
|
|
761
|
-
else:
|
|
762
|
-
preview_file = files_service.get_preview_file(preview_file_id)
|
|
763
|
-
task = tasks_service.get_task(preview_file["task_id"])
|
|
764
|
-
try:
|
|
765
|
-
user_service.check_project_access(task["project_id"])
|
|
766
|
-
user_service.check_entity_access(task["entity_id"])
|
|
767
|
-
return True
|
|
768
|
-
except permissions.PermissionDenied:
|
|
769
|
-
return False
|
|
770
|
-
|
|
771
778
|
@jwt_required()
|
|
772
779
|
def get(self, instance_id):
|
|
773
780
|
"""
|
|
@@ -790,14 +797,14 @@ class BasePreviewPictureResource(Resource):
|
|
|
790
797
|
404:
|
|
791
798
|
description: Picture file not found
|
|
792
799
|
"""
|
|
793
|
-
|
|
794
|
-
abort(404)
|
|
795
|
-
|
|
796
|
-
if not self.is_allowed(instance_id):
|
|
797
|
-
abort(403)
|
|
800
|
+
self.is_allowed(instance_id)
|
|
798
801
|
|
|
799
802
|
try:
|
|
800
|
-
return send_picture_file(
|
|
803
|
+
return send_picture_file(
|
|
804
|
+
self.picture_type,
|
|
805
|
+
instance_id,
|
|
806
|
+
last_modified=self.last_modified,
|
|
807
|
+
)
|
|
801
808
|
except FileNotFound:
|
|
802
809
|
current_app.logger.error(
|
|
803
810
|
"Picture file was not found for: %s" % instance_id
|
|
@@ -834,21 +841,38 @@ class PreviewFileOriginalResource(BasePreviewPictureResource):
|
|
|
834
841
|
BasePreviewPictureResource.__init__(self, "original")
|
|
835
842
|
|
|
836
843
|
|
|
837
|
-
class
|
|
844
|
+
class BaseThumbnailResource(Resource):
|
|
838
845
|
"""
|
|
839
|
-
Base class to
|
|
846
|
+
Base class to post and get a thumbnail.
|
|
840
847
|
"""
|
|
841
848
|
|
|
842
|
-
def __init__(
|
|
849
|
+
def __init__(
|
|
850
|
+
self,
|
|
851
|
+
data_type,
|
|
852
|
+
get_model_func,
|
|
853
|
+
update_model_func,
|
|
854
|
+
size=thumbnail_utils.RECTANGLE_SIZE,
|
|
855
|
+
):
|
|
843
856
|
Resource.__init__(self)
|
|
844
857
|
self.data_type = data_type
|
|
858
|
+
self.get_model_func = get_model_func
|
|
859
|
+
self.update_model_func = update_model_func
|
|
845
860
|
self.size = size
|
|
861
|
+
self.model = None
|
|
862
|
+
self.last_modified = None
|
|
846
863
|
|
|
847
|
-
def
|
|
864
|
+
def is_exist(self, instance_id):
|
|
865
|
+
self.model = self.get_model_func(instance_id)
|
|
866
|
+
|
|
867
|
+
def check_allowed_to_post(self, instance_id):
|
|
848
868
|
permissions.check_admin_permissions()
|
|
849
869
|
|
|
870
|
+
def check_allowed_to_get(self, instance_id):
|
|
871
|
+
if not self.model["has_avatar"]:
|
|
872
|
+
raise NotFound
|
|
873
|
+
|
|
850
874
|
def prepare_creation(self, instance_id):
|
|
851
|
-
|
|
875
|
+
self.model = self.update_model_func(instance_id, {"has_avatar": True})
|
|
852
876
|
|
|
853
877
|
def emit_event(self, instance_id):
|
|
854
878
|
model_name = self.data_type[:-1]
|
|
@@ -885,10 +909,9 @@ class BaseCreatePictureResource(Resource):
|
|
|
885
909
|
404:
|
|
886
910
|
description: Cannot found related object.
|
|
887
911
|
"""
|
|
888
|
-
|
|
889
|
-
|
|
912
|
+
self.is_exist(instance_id)
|
|
913
|
+
self.check_allowed_to_post(instance_id)
|
|
890
914
|
|
|
891
|
-
self.check_permissions(instance_id)
|
|
892
915
|
self.prepare_creation(instance_id)
|
|
893
916
|
|
|
894
917
|
tmp_folder = config.TMP_DIR
|
|
@@ -911,18 +934,6 @@ class BaseCreatePictureResource(Resource):
|
|
|
911
934
|
self.emit_event(instance_id)
|
|
912
935
|
return {"thumbnail_path": thumbnail_url_path}, 201
|
|
913
936
|
|
|
914
|
-
|
|
915
|
-
class BasePictureResource(Resource):
|
|
916
|
-
"""
|
|
917
|
-
Base resource to download a thumbnail.
|
|
918
|
-
"""
|
|
919
|
-
|
|
920
|
-
def is_exist(self, instance_id):
|
|
921
|
-
return False
|
|
922
|
-
|
|
923
|
-
def is_allowed(self, instance_id):
|
|
924
|
-
return True
|
|
925
|
-
|
|
926
937
|
@jwt_required()
|
|
927
938
|
def get(self, instance_id):
|
|
928
939
|
"""
|
|
@@ -945,14 +956,17 @@ class BasePictureResource(Resource):
|
|
|
945
956
|
404:
|
|
946
957
|
description: Object instance not found
|
|
947
958
|
"""
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
if not self.is_allowed(instance_id):
|
|
952
|
-
abort(403)
|
|
959
|
+
self.is_exist(instance_id)
|
|
960
|
+
self.check_allowed_to_get(instance_id)
|
|
953
961
|
|
|
954
962
|
try:
|
|
955
|
-
return send_picture_file(
|
|
963
|
+
return send_picture_file(
|
|
964
|
+
"thumbnails",
|
|
965
|
+
instance_id,
|
|
966
|
+
last_modified=date_helpers.get_datetime_from_string(
|
|
967
|
+
self.model["updated_at"]
|
|
968
|
+
),
|
|
969
|
+
)
|
|
956
970
|
except FileNotFound:
|
|
957
971
|
current_app.logger.error(
|
|
958
972
|
"Thumbnail file was not found for: %s" % instance_id
|
|
@@ -965,114 +979,63 @@ class BasePictureResource(Resource):
|
|
|
965
979
|
abort(404)
|
|
966
980
|
|
|
967
981
|
|
|
968
|
-
class
|
|
982
|
+
class PersonThumbnailResource(BaseThumbnailResource):
|
|
969
983
|
def __init__(self):
|
|
970
|
-
|
|
971
|
-
self,
|
|
984
|
+
BaseThumbnailResource.__init__(
|
|
985
|
+
self,
|
|
986
|
+
"persons",
|
|
987
|
+
persons_service.get_person,
|
|
988
|
+
persons_service.update_person,
|
|
989
|
+
thumbnail_utils.BIG_SQUARE_SIZE,
|
|
972
990
|
)
|
|
973
991
|
|
|
974
|
-
def
|
|
975
|
-
return persons_service.get_person(person_id) is not None
|
|
976
|
-
|
|
977
|
-
def check_permissions(self, instance_id):
|
|
992
|
+
def check_allowed_to_post(self, instance_id):
|
|
978
993
|
is_current_user = (
|
|
979
|
-
persons_service.get_current_user()["id"]
|
|
994
|
+
persons_service.get_current_user()["id"] == instance_id
|
|
980
995
|
)
|
|
981
|
-
if is_current_user and not permissions.has_admin_permissions():
|
|
996
|
+
if not is_current_user and not permissions.has_admin_permissions():
|
|
982
997
|
raise permissions.PermissionDenied
|
|
983
998
|
|
|
984
|
-
def prepare_creation(self, instance_id):
|
|
985
|
-
return persons_service.update_person(instance_id, {"has_avatar": True})
|
|
986
999
|
|
|
1000
|
+
class CreatePersonThumbnailResource(PersonThumbnailResource):
|
|
1001
|
+
pass
|
|
987
1002
|
|
|
988
|
-
class PersonThumbnailResource(BasePictureResource):
|
|
989
|
-
def is_exist(self, person_id):
|
|
990
|
-
person = persons_service.get_person(person_id)
|
|
991
|
-
return person is not None and person["has_avatar"]
|
|
992
1003
|
|
|
1004
|
+
class OrganisationThumbnailResource(BaseThumbnailResource):
|
|
993
1005
|
|
|
994
|
-
class CreateOrganisationThumbnailResource(BaseCreatePictureResource):
|
|
995
1006
|
def __init__(self):
|
|
996
|
-
|
|
997
|
-
self,
|
|
1007
|
+
BaseThumbnailResource.__init__(
|
|
1008
|
+
self,
|
|
1009
|
+
"organisations",
|
|
1010
|
+
persons_service.get_organisation,
|
|
1011
|
+
persons_service.update_organisation,
|
|
1012
|
+
thumbnail_utils.BIG_SQUARE_SIZE,
|
|
998
1013
|
)
|
|
999
1014
|
|
|
1000
1015
|
def is_exist(self, organisation_id):
|
|
1001
|
-
|
|
1016
|
+
self.model = persons_service.get_organisation(organisation_id)
|
|
1002
1017
|
|
|
1003
|
-
def check_permissions(self, organisation_id):
|
|
1004
|
-
if not permissions.has_admin_permissions():
|
|
1005
|
-
raise permissions.PermissionDenied
|
|
1006
1018
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
organisation_id, {"has_avatar": True}
|
|
1010
|
-
)
|
|
1019
|
+
class CreateOrganisationThumbnailResource(OrganisationThumbnailResource):
|
|
1020
|
+
pass
|
|
1011
1021
|
|
|
1012
1022
|
|
|
1013
|
-
class
|
|
1014
|
-
def is_exist(self, organisation_id):
|
|
1015
|
-
return True
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
class CreateProjectThumbnailResource(BaseCreatePictureResource):
|
|
1023
|
+
class ProjectThumbnailResource(BaseThumbnailResource):
|
|
1019
1024
|
def __init__(self):
|
|
1020
|
-
|
|
1021
|
-
self,
|
|
1025
|
+
BaseThumbnailResource.__init__(
|
|
1026
|
+
self,
|
|
1027
|
+
"projects",
|
|
1028
|
+
projects_service.get_project,
|
|
1029
|
+
projects_service.update_project,
|
|
1022
1030
|
)
|
|
1023
1031
|
|
|
1024
|
-
def
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
def prepare_creation(self, instance_id):
|
|
1028
|
-
return projects_service.update_project(
|
|
1029
|
-
instance_id, {"has_avatar": True}
|
|
1030
|
-
)
|
|
1032
|
+
def check_allowed_to_get(self, instance_id):
|
|
1033
|
+
super().check_allowed_to_get(instance_id)
|
|
1034
|
+
user_service.check_project_access(instance_id)
|
|
1031
1035
|
|
|
1032
1036
|
|
|
1033
|
-
class ProjectThumbnailResource
|
|
1034
|
-
|
|
1035
|
-
return projects_service.get_project(project_id) is not None
|
|
1036
|
-
|
|
1037
|
-
def is_allowed(self, project_id):
|
|
1038
|
-
try:
|
|
1039
|
-
user_service.check_project_access(project_id)
|
|
1040
|
-
return True
|
|
1041
|
-
except permissions.PermissionDenied:
|
|
1042
|
-
return False
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
class LegacySetMainPreviewResource(Resource):
|
|
1046
|
-
@jwt_required()
|
|
1047
|
-
def put(self, entity_id, preview_file_id):
|
|
1048
|
-
"""
|
|
1049
|
-
Set main preview to given file.
|
|
1050
|
-
---
|
|
1051
|
-
tags:
|
|
1052
|
-
- Previews
|
|
1053
|
-
parameters:
|
|
1054
|
-
- in: path
|
|
1055
|
-
name: entity_id
|
|
1056
|
-
required: True
|
|
1057
|
-
type: string
|
|
1058
|
-
format: UUID
|
|
1059
|
-
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1060
|
-
- in: path
|
|
1061
|
-
name: preview_file_id
|
|
1062
|
-
required: True
|
|
1063
|
-
type: string
|
|
1064
|
-
format: UUID
|
|
1065
|
-
x-example: a24a6ea4-ce75-4665-a070-57453082c25
|
|
1066
|
-
responses:
|
|
1067
|
-
200:
|
|
1068
|
-
description: Main preview set
|
|
1069
|
-
"""
|
|
1070
|
-
preview_file = files_service.get_preview_file(preview_file_id)
|
|
1071
|
-
task = tasks_service.get_task(preview_file["task_id"])
|
|
1072
|
-
user_service.check_project_access(task["project_id"])
|
|
1073
|
-
return entities_service.update_entity_preview(
|
|
1074
|
-
entity_id, preview_file_id
|
|
1075
|
-
)
|
|
1037
|
+
class CreateProjectThumbnailResource(ProjectThumbnailResource):
|
|
1038
|
+
pass
|
|
1076
1039
|
|
|
1077
1040
|
|
|
1078
1041
|
class SetMainPreviewResource(Resource, ArgsMixin):
|
|
@@ -1512,6 +1475,9 @@ class PreviewBackgroundFileResource(Resource):
|
|
|
1512
1475
|
instance_id,
|
|
1513
1476
|
extension=extension,
|
|
1514
1477
|
download_name=f"{preview_background_file['original_name']}.{extension}",
|
|
1478
|
+
last_modified=date_helpers.get_datetime_from_string(
|
|
1479
|
+
preview_background_file["updated_at"]
|
|
1480
|
+
),
|
|
1515
1481
|
)
|
|
1516
1482
|
except FileNotFound:
|
|
1517
1483
|
current_app.logger.error(
|
|
@@ -1520,11 +1486,17 @@ class PreviewBackgroundFileResource(Resource):
|
|
|
1520
1486
|
raise PreviewBackgroundFileNotFoundException
|
|
1521
1487
|
|
|
1522
1488
|
|
|
1523
|
-
class PreviewBackgroundFileThumbnailResource(
|
|
1524
|
-
def
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1489
|
+
class PreviewBackgroundFileThumbnailResource(BaseThumbnailResource):
|
|
1490
|
+
def __init__(self):
|
|
1491
|
+
BaseThumbnailResource.__init__(
|
|
1492
|
+
self,
|
|
1493
|
+
"preview-backgrounds",
|
|
1494
|
+
files_service.get_preview_background_file,
|
|
1495
|
+
files_service.update_preview_background_file,
|
|
1530
1496
|
)
|
|
1497
|
+
|
|
1498
|
+
def check_allowed_to_get(self, preview_background_file_id):
|
|
1499
|
+
return True
|
|
1500
|
+
|
|
1501
|
+
def post(self, preview_background_file_id):
|
|
1502
|
+
raise AttributeError("Method not allowed")
|
|
@@ -1529,7 +1529,6 @@ class ProjectQuotasResource(Resource, ArgsMixin):
|
|
|
1529
1529
|
)
|
|
1530
1530
|
|
|
1531
1531
|
|
|
1532
|
-
|
|
1533
1532
|
class SetShotsFramesResource(Resource, ArgsMixin):
|
|
1534
1533
|
@jwt_required()
|
|
1535
1534
|
def post(self, project_id, task_type_id):
|
|
@@ -1558,13 +1557,13 @@ class SetShotsFramesResource(Resource, ArgsMixin):
|
|
|
1558
1557
|
description: Frames set for given shots
|
|
1559
1558
|
"""
|
|
1560
1559
|
user_service.check_manager_project_access(project_id)
|
|
1561
|
-
if not fields.is_valid_id(task_type_id) or
|
|
1562
|
-
|
|
1560
|
+
if not fields.is_valid_id(task_type_id) or not fields.is_valid_id(
|
|
1561
|
+
project_id
|
|
1562
|
+
):
|
|
1563
1563
|
raise WrongParameterException("Invalid project or task type id")
|
|
1564
1564
|
|
|
1565
1565
|
episode_id = self.get_episode_id()
|
|
1566
|
-
if not episode_id in ["", None] and
|
|
1567
|
-
not fields.is_valid_id(episode_id):
|
|
1566
|
+
if not episode_id in ["", None] and not fields.is_valid_id(episode_id):
|
|
1568
1567
|
raise WrongParameterException("Invalid episode id")
|
|
1569
1568
|
|
|
1570
1569
|
if episode_id == "":
|
zou/app/mixin.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from flask_restful import reqparse
|
|
2
2
|
from flask import request
|
|
3
3
|
|
|
4
|
-
from zou.app.utils import
|
|
4
|
+
from zou.app.utils import date_helpers
|
|
5
5
|
from zou.app.services.exception import WrongParameterException
|
|
6
6
|
|
|
7
7
|
|
|
@@ -146,10 +146,10 @@ class ArgsMixin(object):
|
|
|
146
146
|
if param is None:
|
|
147
147
|
return date
|
|
148
148
|
try:
|
|
149
|
-
date =
|
|
149
|
+
date = date_helpers.get_datetime_from_string(param)
|
|
150
150
|
except Exception:
|
|
151
151
|
try:
|
|
152
|
-
date =
|
|
152
|
+
date = date_helpers.get_date_from_string(param)
|
|
153
153
|
except Exception:
|
|
154
154
|
raise WrongParameterException(
|
|
155
155
|
"Wrong date format for before argument."
|
zou/app/services/auth_service.py
CHANGED
|
@@ -9,7 +9,6 @@ from datetime import timedelta
|
|
|
9
9
|
from flask import request, session, current_app
|
|
10
10
|
from babel.dates import format_datetime
|
|
11
11
|
|
|
12
|
-
from flask_jwt_extended import get_jti
|
|
13
12
|
from ldap3 import Server, Connection, ALL, NTLM, SIMPLE
|
|
14
13
|
from ldap3.core.exceptions import (
|
|
15
14
|
LDAPSocketOpenError,
|
|
@@ -678,24 +677,6 @@ def generate_new_recovery_codes(person_id):
|
|
|
678
677
|
return otp_recovery_codes
|
|
679
678
|
|
|
680
679
|
|
|
681
|
-
def register_tokens(app, access_token, refresh_token=None):
|
|
682
|
-
"""
|
|
683
|
-
Register access and refresh tokens to auth token store. That way they
|
|
684
|
-
can be used like a session.
|
|
685
|
-
"""
|
|
686
|
-
access_jti = get_jti(encoded_token=access_token)
|
|
687
|
-
|
|
688
|
-
auth_tokens_store.add(
|
|
689
|
-
access_jti, "false", app.config["JWT_ACCESS_TOKEN_EXPIRES"]
|
|
690
|
-
)
|
|
691
|
-
|
|
692
|
-
if refresh_token is not None:
|
|
693
|
-
refresh_jti = get_jti(encoded_token=refresh_token)
|
|
694
|
-
auth_tokens_store.add(
|
|
695
|
-
refresh_jti, "false", app.config["JWT_REFRESH_TOKEN_EXPIRES"]
|
|
696
|
-
)
|
|
697
|
-
|
|
698
|
-
|
|
699
680
|
def revoke_tokens(app, jti):
|
|
700
681
|
"""
|
|
701
682
|
Remove access and refresh tokens from auth token store.
|
|
@@ -306,8 +306,8 @@ def new_comment(
|
|
|
306
306
|
)
|
|
307
307
|
except ValueError:
|
|
308
308
|
try:
|
|
309
|
-
created_at_date =
|
|
310
|
-
created_at
|
|
309
|
+
created_at_date = date_helpers.get_datetime_from_string(
|
|
310
|
+
created_at
|
|
311
311
|
)
|
|
312
312
|
except ValueError:
|
|
313
313
|
pass
|
|
@@ -1543,7 +1543,7 @@ def set_frames_from_task_type_preview_files(
|
|
|
1543
1543
|
subquery = (
|
|
1544
1544
|
db.session.query(
|
|
1545
1545
|
Shot.id.label("entity_id"),
|
|
1546
|
-
func.max(PreviewFile.created_at).label("max_created_at")
|
|
1546
|
+
func.max(PreviewFile.created_at).label("max_created_at"),
|
|
1547
1547
|
)
|
|
1548
1548
|
.join(Task, PreviewFile.task_id == Task.id)
|
|
1549
1549
|
.join(Shot, Task.entity_id == Shot.id)
|
|
@@ -1559,7 +1559,7 @@ def set_frames_from_task_type_preview_files(
|
|
|
1559
1559
|
subquery = (
|
|
1560
1560
|
db.session.query(
|
|
1561
1561
|
Shot.id.label("entity_id"),
|
|
1562
|
-
func.max(PreviewFile.created_at).label("max_created_at")
|
|
1562
|
+
func.max(PreviewFile.created_at).label("max_created_at"),
|
|
1563
1563
|
)
|
|
1564
1564
|
.join(Task, PreviewFile.task_id == Task.id)
|
|
1565
1565
|
.join(Shot, Task.entity_id == Shot.id)
|
|
@@ -1571,15 +1571,14 @@ def set_frames_from_task_type_preview_files(
|
|
|
1571
1571
|
)
|
|
1572
1572
|
|
|
1573
1573
|
query = (
|
|
1574
|
-
db.session.query(
|
|
1575
|
-
Shot,
|
|
1576
|
-
PreviewFile.duration
|
|
1577
|
-
)
|
|
1574
|
+
db.session.query(Shot, PreviewFile.duration)
|
|
1578
1575
|
.join(Task, Task.entity_id == Shot.id)
|
|
1579
1576
|
.join(subquery, (Shot.id == subquery.c.entity_id))
|
|
1580
|
-
.join(
|
|
1581
|
-
|
|
1582
|
-
|
|
1577
|
+
.join(
|
|
1578
|
+
PreviewFile,
|
|
1579
|
+
(PreviewFile.task_id == Task.id)
|
|
1580
|
+
& (PreviewFile.created_at == subquery.c.max_created_at),
|
|
1581
|
+
)
|
|
1583
1582
|
.filter(Task.task_type_id == task_type_id)
|
|
1584
1583
|
.filter(Shot.project_id == project_id)
|
|
1585
1584
|
)
|
|
@@ -1587,12 +1586,14 @@ def set_frames_from_task_type_preview_files(
|
|
|
1587
1586
|
results = query.all()
|
|
1588
1587
|
project = projects_service.get_project(project_id)
|
|
1589
1588
|
updates = []
|
|
1590
|
-
for
|
|
1589
|
+
for shot, preview_duration in results:
|
|
1591
1590
|
nb_frames = round(preview_duration * int(project["fps"]))
|
|
1592
|
-
updates.append(
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1591
|
+
updates.append(
|
|
1592
|
+
{
|
|
1593
|
+
"id": shot.id,
|
|
1594
|
+
"nb_frames": nb_frames,
|
|
1595
|
+
}
|
|
1596
|
+
)
|
|
1596
1597
|
clear_shot_cache(str(shot.id))
|
|
1597
1598
|
|
|
1598
1599
|
db.session.bulk_update_mappings(Shot, updates)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zou
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.46
|
|
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
|
|
@@ -35,12 +35,12 @@ Requires-Dist: flask-mail ==0.10.0
|
|
|
35
35
|
Requires-Dist: flask-principal ==0.4.0
|
|
36
36
|
Requires-Dist: flask-restful ==0.3.10
|
|
37
37
|
Requires-Dist: flask-sqlalchemy ==3.1.1
|
|
38
|
-
Requires-Dist: flask-fs2[s3,swift] ==0.7.
|
|
38
|
+
Requires-Dist: flask-fs2[s3,swift] ==0.7.27
|
|
39
39
|
Requires-Dist: flask-jwt-extended ==4.6.0
|
|
40
40
|
Requires-Dist: flask-migrate ==4.0.7
|
|
41
41
|
Requires-Dist: flask-socketio ==5.3.6
|
|
42
42
|
Requires-Dist: flask ==3.0.3
|
|
43
|
-
Requires-Dist: gazu ==0.10.
|
|
43
|
+
Requires-Dist: gazu ==0.10.11
|
|
44
44
|
Requires-Dist: gevent-websocket ==0.10.1
|
|
45
45
|
Requires-Dist: gevent ==24.2.1
|
|
46
46
|
Requires-Dist: gunicorn ==22.0.0
|
|
@@ -49,13 +49,14 @@ Requires-Dist: itsdangerous ==2.2.0
|
|
|
49
49
|
Requires-Dist: Jinja2 ==3.1.4
|
|
50
50
|
Requires-Dist: ldap3 ==2.9.1
|
|
51
51
|
Requires-Dist: matterhook ==0.2
|
|
52
|
-
Requires-Dist: meilisearch ==0.31.
|
|
52
|
+
Requires-Dist: meilisearch ==0.31.4
|
|
53
53
|
Requires-Dist: opencv-python ==4.10.0.84
|
|
54
54
|
Requires-Dist: OpenTimelineIO ==0.17.0
|
|
55
|
-
Requires-Dist:
|
|
56
|
-
Requires-Dist:
|
|
55
|
+
Requires-Dist: OpenTimelineIO-Plugins ==0.17.0
|
|
56
|
+
Requires-Dist: orjson ==3.10.6
|
|
57
|
+
Requires-Dist: pillow ==10.4.0
|
|
57
58
|
Requires-Dist: psutil ==6.0.0
|
|
58
|
-
Requires-Dist: psycopg[binary] ==3.1
|
|
59
|
+
Requires-Dist: psycopg[binary] ==3.2.1
|
|
59
60
|
Requires-Dist: pyotp ==2.9.0
|
|
60
61
|
Requires-Dist: python-nomad ==2.0.1
|
|
61
62
|
Requires-Dist: python-slugify ==8.0.4
|
|
@@ -78,14 +79,14 @@ Requires-Dist: autoflake ==2.3.1 ; extra == 'lint'
|
|
|
78
79
|
Requires-Dist: black ==24.4.2 ; extra == 'lint'
|
|
79
80
|
Requires-Dist: pre-commit ==3.7.1 ; (python_version >= "3.9") and extra == 'lint'
|
|
80
81
|
Provides-Extra: monitoring
|
|
81
|
-
Requires-Dist: prometheus-flask-exporter ==0.23.
|
|
82
|
+
Requires-Dist: prometheus-flask-exporter ==0.23.1 ; extra == 'monitoring'
|
|
82
83
|
Requires-Dist: pygelf ==0.4.2 ; extra == 'monitoring'
|
|
83
|
-
Requires-Dist: sentry-sdk ==2.
|
|
84
|
+
Requires-Dist: sentry-sdk ==2.10.0 ; extra == 'monitoring'
|
|
84
85
|
Provides-Extra: prod
|
|
85
86
|
Requires-Dist: gunicorn ; extra == 'prod'
|
|
86
87
|
Requires-Dist: gevent ; extra == 'prod'
|
|
87
88
|
Provides-Extra: test
|
|
88
|
-
Requires-Dist: fakeredis ==2.23.
|
|
89
|
+
Requires-Dist: fakeredis ==2.23.3 ; extra == 'test'
|
|
89
90
|
Requires-Dist: mixer ==7.2.2 ; extra == 'test'
|
|
90
91
|
Requires-Dist: pytest-cov ==5.0.0 ; extra == 'test'
|
|
91
92
|
Requires-Dist: pytest ==8.2.2 ; extra == 'test'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
zou/__init__.py,sha256=
|
|
1
|
+
zou/__init__.py,sha256=LvHLU-F515PGYfBGNu8GbSE2L78r7PFa-RIsPHqykKA,24
|
|
2
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
|
|
@@ -6,19 +6,19 @@ zou/job_settings.py,sha256=WB_RkYxmh4ffQHqg63_wsUDiS0zP3yxiwrxK7DhHG0g,150
|
|
|
6
6
|
zou/app/__init__.py,sha256=aWh9K5n63TpXdLDxpfFtNNoCYZVE6OV3YLCXLuygWQg,6700
|
|
7
7
|
zou/app/api.py,sha256=JTB_IMVO8EOoyqx9KdRkiIix0chOLi0yGDY-verUJXA,5127
|
|
8
8
|
zou/app/config.py,sha256=J0jmGmyvk8JqcMPAEW8KfvwP8GwEoC9BxQG8AQV9aiY,6393
|
|
9
|
-
zou/app/mixin.py,sha256=
|
|
9
|
+
zou/app/mixin.py,sha256=A4iIOwpkfYmRKXvF2Ykdc8BUQgufB0r_I4RdZYTiS3E,4896
|
|
10
10
|
zou/app/swagger.py,sha256=UW9DSik3a8GuH1_-7F5P7EYgjZ9DA_kFjukO-6n4kgk,54682
|
|
11
11
|
zou/app/blueprints/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
zou/app/blueprints/assets/__init__.py,sha256=tSRvVrnPj732F4k_lkxoTJBJNmIUAqKXPLJDHvOtAA4,2178
|
|
13
13
|
zou/app/blueprints/assets/resources.py,sha256=qY4K890kTTRWUVnNomilEuJY7qBy4RWHG2XiTuWPfBA,18988
|
|
14
14
|
zou/app/blueprints/auth/__init__.py,sha256=b8Syg8DHJn5s3avMZo5ukNQCzpX_2z9fmBSG3EIt5Yg,998
|
|
15
|
-
zou/app/blueprints/auth/resources.py,sha256=
|
|
15
|
+
zou/app/blueprints/auth/resources.py,sha256=b6zPYiBE_a1gE2ei3FFswy1Iml2r6TtMB5i48f9mPKk,41760
|
|
16
16
|
zou/app/blueprints/breakdown/__init__.py,sha256=Dp6GWSGxxWIedpyzTTEKpCRUYEo8oVNVyQhwNvTMmQM,1888
|
|
17
17
|
zou/app/blueprints/breakdown/resources.py,sha256=JY3j17kv7xPKV9S-XoOxNYivpGHlfZkXI5WuGtx3_Yk,13591
|
|
18
18
|
zou/app/blueprints/chats/__init__.py,sha256=YGmwGvddg3MgSYVIh-hmkX8t2em9_LblxBeJzFqFJD4,558
|
|
19
19
|
zou/app/blueprints/chats/resources.py,sha256=1THB-UNgMcedspNfB9-3-Tsr6rJ_PUl6Y2s_y0Ww0jk,5910
|
|
20
20
|
zou/app/blueprints/comments/__init__.py,sha256=WqpJ7-_dK1cInGTFJAxQ7syZtPCotwq2oO20UEnk1h4,1532
|
|
21
|
-
zou/app/blueprints/comments/resources.py,sha256=
|
|
21
|
+
zou/app/blueprints/comments/resources.py,sha256=_WoAnnv2uRLbc_fzg6XCeXF06_KNFS08r84YVN858Mc,19423
|
|
22
22
|
zou/app/blueprints/concepts/__init__.py,sha256=sP_P4mfYvfMcgeE6MHZYP3eD0Lz0Lwit5-CFuVnA-Jg,894
|
|
23
23
|
zou/app/blueprints/concepts/resources.py,sha256=maJNrBAWX0bKbDKtOZc3YFp4nTVtIdkkAA4H9WA9n1Y,10140
|
|
24
24
|
zou/app/blueprints/crud/__init__.py,sha256=qn7xkEh2EG0mPS_RBmm0GgYr0O1jnmI8ymXZnFWZCz8,8361
|
|
@@ -31,7 +31,7 @@ zou/app/blueprints/crud/comments.py,sha256=YH4cllfGloPMcIq1tgpT5pSvKTwNJ1zpkUssr
|
|
|
31
31
|
zou/app/blueprints/crud/custom_action.py,sha256=Nf6S6YBxePg4-nfaPTroIYZGWt9fJEHC719DOKJ8R98,978
|
|
32
32
|
zou/app/blueprints/crud/day_off.py,sha256=y0vahwLa7F9u6K5KUQ_6vt7XxHWQ_9vBdzDxvEMGIKg,2496
|
|
33
33
|
zou/app/blueprints/crud/department.py,sha256=AAN_qxZDQGS-mR1kRS_2qGx1D7PKT3h_Ke3IXtJ_F90,973
|
|
34
|
-
zou/app/blueprints/crud/entity.py,sha256=
|
|
34
|
+
zou/app/blueprints/crud/entity.py,sha256=Vsa3PFTT8L2x-FP9JXo4fYecWx-dRCzd8049V3g865w,8313
|
|
35
35
|
zou/app/blueprints/crud/entity_link.py,sha256=PlHGy3RPDUVdwWtOpQegz-wZCcxe9FZw_80nUVBy1Ac,819
|
|
36
36
|
zou/app/blueprints/crud/entity_type.py,sha256=eiOwyoxwA2r857vX6Nni1ukXnNnV-6GnpjIGuTrRqrI,1927
|
|
37
37
|
zou/app/blueprints/crud/event.py,sha256=bay2ggg5Oa69lOxNYGkHVQdSKuMxGhk2wqWP7QApKUg,589
|
|
@@ -66,7 +66,7 @@ zou/app/blueprints/edits/resources.py,sha256=IvgqEhIvjF6OO7VNK6i5w6NKEoFQyKfuZJ7
|
|
|
66
66
|
zou/app/blueprints/entities/__init__.py,sha256=v-qt2dl3s3tmK_ur-cpDHNPmcL0A6xCybczyuidjUCo,713
|
|
67
67
|
zou/app/blueprints/entities/resources.py,sha256=vyEs5ODyRqP9ICf_2KPVnwrGRCJQxZTgO5qFld0F3lg,3166
|
|
68
68
|
zou/app/blueprints/events/__init__.py,sha256=Vb0gO7Bpj_2Dpx9hhKd2SZW2qqnJrFVoDpJjFOmoMZw,394
|
|
69
|
-
zou/app/blueprints/events/resources.py,sha256=
|
|
69
|
+
zou/app/blueprints/events/resources.py,sha256=SSrfq5TioZj217Qzv8wxFTUzs3_3DP8yGDYUrkttMIs,3238
|
|
70
70
|
zou/app/blueprints/export/__init__.py,sha256=W3U93VD-dHlozFVSt_RDvP7h7K_FqgHPLA__W5H1DkE,1574
|
|
71
71
|
zou/app/blueprints/export/csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
72
|
zou/app/blueprints/export/csv/assets.py,sha256=QafmkM1BphI6wzbcqK6Hc1XBtisjgGTGYejOwJWwWW4,5561
|
|
@@ -81,7 +81,7 @@ zou/app/blueprints/export/csv/task_types.py,sha256=PCEEhOQcdOJv_38i-KNxbkGeNzmQ8
|
|
|
81
81
|
zou/app/blueprints/export/csv/tasks.py,sha256=CHFcs9S3eLIz6psE6Q6mZ-OSur_GrpBeLn98Nh9NNcA,4121
|
|
82
82
|
zou/app/blueprints/export/csv/time_spents.py,sha256=WHdy9Wf2e-kvviYbNyUFr7xgg49h9f-Di12KIZx5ssk,2981
|
|
83
83
|
zou/app/blueprints/files/__init__.py,sha256=7Wty30JW2OXIn-tBFXOWWmPuHnsnxPpH3jNtHvvr9tY,3987
|
|
84
|
-
zou/app/blueprints/files/resources.py,sha256=
|
|
84
|
+
zou/app/blueprints/files/resources.py,sha256=8SIV8kaqv3dxyL8nyqG3QiZmk5ZYIvUxw6k1ic-jhBs,69786
|
|
85
85
|
zou/app/blueprints/index/__init__.py,sha256=Dh3oQiirpg8RCkfVOuk3irIjSvUvuRf0jPxE6oGubz0,828
|
|
86
86
|
zou/app/blueprints/index/resources.py,sha256=DsYpNSO_wCAxyjWOaB9QmEqOBcjn1miLiGnfY-ii1z8,8165
|
|
87
87
|
zou/app/blueprints/news/__init__.py,sha256=HxBXjC15dVbotNAZ0CLf02iwUjxJr20kgf8_kT_9nwM,505
|
|
@@ -90,14 +90,14 @@ zou/app/blueprints/persons/__init__.py,sha256=0cnHHw3K_8OEMm0qOi3wKVomSAg9IJSnVj
|
|
|
90
90
|
zou/app/blueprints/persons/resources.py,sha256=-5J8ZswusYEBTNmX4I7fLFDZVMKyO0qhO_dkMs9SkXA,41406
|
|
91
91
|
zou/app/blueprints/playlists/__init__.py,sha256=vuEk1F3hFHsmuKWhdepMoLyOzmNKDn1YrjjfcaIz0lQ,1596
|
|
92
92
|
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=
|
|
93
|
+
zou/app/blueprints/previews/__init__.py,sha256=qGohO6LRNZKXBAegINcUXuZlrtxobJKQg84-rQ1L3AU,4202
|
|
94
|
+
zou/app/blueprints/previews/resources.py,sha256=SRPlEQ4WKSPkOdBvvGDlXdoDaT_2stbJkfzkwN1G1rQ,47077
|
|
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=
|
|
100
|
-
zou/app/blueprints/shots/resources.py,sha256=
|
|
99
|
+
zou/app/blueprints/shots/__init__.py,sha256=HfgLneZBYUMa2OGwIgEZTz8zrIEYFRiYmRbreBPYeYw,4076
|
|
100
|
+
zou/app/blueprints/shots/resources.py,sha256=NiuRZG2ltSn6KgaZvr_W7bHXJOQkBTFPUDYisShWZ6M,47738
|
|
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
|
|
@@ -180,12 +180,12 @@ zou/app/models/time_spent.py,sha256=n7i3FO9g1eE_zATkItoCgrGVqq3iMSfdlKSveEZPloc,
|
|
|
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
|
|
182
182
|
zou/app/services/assets_service.py,sha256=Vea-Ra69-Zi0Q2S-Apb5fsZv5E9f_6XYVn2HxaGQBE8,21339
|
|
183
|
-
zou/app/services/auth_service.py,sha256=
|
|
183
|
+
zou/app/services/auth_service.py,sha256=AxKN_THkjN2tmOHTSyFspwwFHqGBnslXuidfbav8Rxk,23224
|
|
184
184
|
zou/app/services/backup_service.py,sha256=_ZtZp6wkcVYnHxBosziwLGdrTvsUttXGphiydq53iy8,4840
|
|
185
185
|
zou/app/services/base_service.py,sha256=OZd0STFh-DyBBdwsmA7DMMnrwv4C8wJUbShvZ1isndU,1383
|
|
186
186
|
zou/app/services/breakdown_service.py,sha256=p93HncjC36qbmvZiB259QGRtciS37N-s_7IWVAQx5eE,26727
|
|
187
187
|
zou/app/services/chats_service.py,sha256=V1RmQeQnsH1xvtbs6wcjEpudQS547eJBM7bgJr9-qYM,8270
|
|
188
|
-
zou/app/services/comments_service.py,sha256=
|
|
188
|
+
zou/app/services/comments_service.py,sha256=CUr0CZGkR95OrHDRJnhAZAikBLtWhM-5uLIoxI4gNtA,18589
|
|
189
189
|
zou/app/services/concepts_service.py,sha256=KGvk6lF5udj3SWn40X9KE8OAigrLCZUKEz9_CW7EMgQ,11440
|
|
190
190
|
zou/app/services/custom_actions_service.py,sha256=fWISEOOdthadrxeHuacEel5Xj6msn0yWXJQDG1gzvsY,297
|
|
191
191
|
zou/app/services/deletion_service.py,sha256=ddaup7i_CTugcJDrynczNcfhjSKgDeGhPQjQ68We_l8,17255
|
|
@@ -206,7 +206,7 @@ zou/app/services/preview_files_service.py,sha256=SIZ_SB1bWNRE_Zm7SuEpvFWqVpHKOgf
|
|
|
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=
|
|
209
|
+
zou/app/services/shots_service.py,sha256=w96EbNyXZNKmZg1eUMbaQPAEng3WkfJaPkqEr39F2ug,50310
|
|
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
212
|
zou/app/services/sync_service.py,sha256=EunfXlma_IIb7011A_xLQLVQGAi-MteKgm2Y2NAxvMs,41586
|
|
@@ -215,7 +215,7 @@ zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6p
|
|
|
215
215
|
zou/app/services/time_spents_service.py,sha256=TBLC1O9Dg_UbciG5Nw-dejqX2-5n6q44lACeN6OnUkQ,15206
|
|
216
216
|
zou/app/services/user_service.py,sha256=BiOhPV7O-vowet7jOksjXk2V4yxZkdqsIyNboJ-Oz_A,46595
|
|
217
217
|
zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
218
|
-
zou/app/stores/auth_tokens_store.py,sha256=
|
|
218
|
+
zou/app/stores/auth_tokens_store.py,sha256=adcGe3SxfY4y_tP57HIR2SZbnu_Amqk-dAGVZIcJQ9c,1237
|
|
219
219
|
zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
|
|
220
220
|
zou/app/stores/publisher_store.py,sha256=0cD9bwDdF2rOEeumLrxJx7xNPR_xvf_IAAk5JttDsO4,1006
|
|
221
221
|
zou/app/stores/queue_store.py,sha256=Nyh8_nXilC1FHtJvj6nVVm4sNCEtmJcRRVK2cj2G22c,612
|
|
@@ -407,9 +407,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
|
|
|
407
407
|
zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
|
|
408
408
|
zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
409
409
|
zou/utils/movie.py,sha256=u9LCEOvmkxwm-KiZ6jKNdB9LSC6XXUDwJpVx8LkDwJg,16416
|
|
410
|
-
zou-0.19.
|
|
411
|
-
zou-0.19.
|
|
412
|
-
zou-0.19.
|
|
413
|
-
zou-0.19.
|
|
414
|
-
zou-0.19.
|
|
415
|
-
zou-0.19.
|
|
410
|
+
zou-0.19.46.dist-info/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
|
|
411
|
+
zou-0.19.46.dist-info/METADATA,sha256=VsjwOstLLDKC3fdmEmo8SUazHhPIDyDNWc6sF_kKpiw,6725
|
|
412
|
+
zou-0.19.46.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
|
|
413
|
+
zou-0.19.46.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
|
|
414
|
+
zou-0.19.46.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
|
|
415
|
+
zou-0.19.46.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|