zou 0.19.68__py3-none-any.whl → 0.19.70__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. zou/__init__.py +1 -1
  2. zou/app/__init__.py +1 -1
  3. zou/app/blueprints/auth/resources.py +17 -15
  4. zou/app/blueprints/breakdown/resources.py +4 -4
  5. zou/app/blueprints/comments/resources.py +2 -2
  6. zou/app/blueprints/crud/base.py +11 -20
  7. zou/app/blueprints/crud/comments.py +4 -40
  8. zou/app/blueprints/crud/event.py +1 -1
  9. zou/app/blueprints/crud/metadata_descriptor.py +9 -9
  10. zou/app/blueprints/crud/organisation.py +16 -1
  11. zou/app/blueprints/crud/person.py +4 -0
  12. zou/app/blueprints/crud/task.py +4 -1
  13. zou/app/blueprints/events/resources.py +8 -8
  14. zou/app/blueprints/export/csv/assets.py +15 -6
  15. zou/app/blueprints/export/csv/edits.py +15 -5
  16. zou/app/blueprints/export/csv/shots.py +15 -5
  17. zou/app/blueprints/index/resources.py +2 -0
  18. zou/app/blueprints/news/resources.py +6 -6
  19. zou/app/blueprints/persons/resources.py +0 -1
  20. zou/app/blueprints/shots/resources.py +0 -1
  21. zou/app/blueprints/source/csv/assets.py +10 -3
  22. zou/app/blueprints/source/csv/base.py +1 -1
  23. zou/app/blueprints/source/csv/edits.py +10 -3
  24. zou/app/blueprints/source/csv/shots.py +10 -3
  25. zou/app/blueprints/tasks/resources.py +7 -1
  26. zou/app/config.py +1 -0
  27. zou/app/models/organisation.py +11 -19
  28. zou/app/models/person.py +1 -1
  29. zou/app/models/serializer.py +17 -17
  30. zou/app/services/assets_service.py +6 -12
  31. zou/app/services/breakdown_service.py +1 -1
  32. zou/app/services/comments_service.py +1 -1
  33. zou/app/services/concepts_service.py +4 -12
  34. zou/app/services/edits_service.py +5 -11
  35. zou/app/services/events_service.py +4 -4
  36. zou/app/services/news_service.py +8 -8
  37. zou/app/services/persons_service.py +9 -4
  38. zou/app/services/preview_files_service.py +12 -4
  39. zou/app/services/projects_service.py +4 -13
  40. zou/app/services/shots_service.py +6 -12
  41. zou/app/services/sync_service.py +4 -4
  42. zou/app/services/tasks_service.py +12 -29
  43. zou/app/services/user_service.py +22 -37
  44. zou/app/utils/commands.py +4 -4
  45. zou/app/utils/csv_utils.py +1 -4
  46. zou/cli.py +4 -4
  47. zou/remote/config_payload.py +2 -1
  48. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/METADATA +9 -9
  49. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/RECORD +53 -53
  50. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/LICENSE +0 -0
  51. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/WHEEL +0 -0
  52. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/entry_points.txt +0 -0
  53. {zou-0.19.68.dist-info → zou-0.19.70.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ from zou.app.services.tasks_service import (
21
21
  )
22
22
  from zou.app.services.comments_service import create_comment
23
23
  from zou.app.services.exception import WrongParameterException
24
- from zou.app.utils import events
24
+ from zou.app.utils import events, string
25
25
 
26
26
 
27
27
  class EditsCsvImportResource(BaseCsvProjectImportResource):
@@ -192,9 +192,16 @@ class EditsCsvImportResource(BaseCsvProjectImportResource):
192
192
  else:
193
193
  edit_new_values["data"] = entity.data.copy()
194
194
 
195
- for name, field_name in self.descriptor_fields.items():
195
+ for name, descriptor in self.descriptor_fields.items():
196
196
  if name in row:
197
- edit_new_values["data"][field_name] = row[name]
197
+ if descriptor["data_type"] == "boolean":
198
+ edit_new_values["data"][descriptor["field_name"]] = (
199
+ "true" if string.strtobool(row[name]) else "false"
200
+ )
201
+ else:
202
+ edit_new_values["data"][descriptor["field_name"]] = row[
203
+ name
204
+ ]
198
205
 
199
206
  tasks_update = self.get_tasks_update(row)
200
207
 
@@ -21,7 +21,7 @@ from zou.app.services.tasks_service import (
21
21
  )
22
22
  from zou.app.services.comments_service import create_comment
23
23
  from zou.app.services.exception import WrongParameterException
24
- from zou.app.utils import events
24
+ from zou.app.utils import events, string
25
25
 
26
26
 
27
27
  class ShotsCsvImportResource(BaseCsvProjectImportResource):
@@ -229,9 +229,16 @@ class ShotsCsvImportResource(BaseCsvProjectImportResource):
229
229
  if fps is not None:
230
230
  shot_new_values["data"]["fps"] = fps
231
231
 
232
- for name, field_name in self.descriptor_fields.items():
232
+ for name, descriptor in self.descriptor_fields.items():
233
233
  if name in row:
234
- shot_new_values["data"][field_name] = row[name]
234
+ if descriptor["data_type"] == "boolean":
235
+ shot_new_values["data"][descriptor["field_name"]] = (
236
+ "true" if string.strtobool(row[name]) else "false"
237
+ )
238
+ else:
239
+ shot_new_values["data"][descriptor["field_name"]] = row[
240
+ name
241
+ ]
235
242
 
236
243
  tasks_update = self.get_tasks_update(row)
237
244
 
@@ -1532,6 +1532,11 @@ class ProjectCommentsResource(Resource, ArgsMixin):
1532
1532
  type: string
1533
1533
  format: UUID
1534
1534
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
1535
+ - in: query
1536
+ name: limit
1537
+ type: integer
1538
+ default: 100
1539
+ x-example: 100
1535
1540
  responses:
1536
1541
  200:
1537
1542
  description: All comments to tasks related to given project
@@ -1544,7 +1549,8 @@ class ProjectCommentsResource(Resource, ArgsMixin):
1544
1549
  ):
1545
1550
  raise permissions.PermissionDenied
1546
1551
  page = self.get_page()
1547
- return tasks_service.get_comments_for_project(project_id, page)
1552
+ limit = self.get_limit()
1553
+ return tasks_service.get_comments_for_project(project_id, page, limit)
1548
1554
 
1549
1555
 
1550
1556
  class ProjectPreviewFilesResource(Resource, ArgsMixin):
zou/app/config.py CHANGED
@@ -158,6 +158,7 @@ CRISP_TOKEN = os.getenv("CRISP_TOKEN", "")
158
158
  IS_SELF_HOSTED = envtobool("IS_SELF_HOSTED", True)
159
159
 
160
160
  DEFAULT_TIMEZONE = os.getenv("DEFAULT_TIMEZONE", "Europe/Paris")
161
+ DEFAULT_LOCALE = os.getenv("DEFAULT_LOCALE", "en_US")
161
162
 
162
163
  USER_LIMIT = int(os.getenv("USER_LIMIT", "100"))
163
164
  MIN_PASSWORD_LENGTH = int(os.getenv("MIN_PASSWORD_LENGTH", 8))
@@ -1,7 +1,6 @@
1
1
  from zou.app import db
2
2
  from zou.app.models.serializer import SerializerMixin
3
3
  from zou.app.models.base import BaseMixin
4
- from zou.app.utils import fields
5
4
 
6
5
 
7
6
  class Organisation(db.Model, BaseMixin, SerializerMixin):
@@ -22,22 +21,15 @@ class Organisation(db.Model, BaseMixin, SerializerMixin):
22
21
  dark_theme_by_default = db.Column(db.Boolean(), default=False)
23
22
  format_duration_in_hours = db.Column(db.Boolean(), default=False)
24
23
 
25
- def present(self):
26
- return fields.serialize_dict(
27
- {
28
- "id": self.id,
29
- "chat_token_slack": self.chat_token_slack,
30
- "chat_webhook_mattermost": self.chat_webhook_mattermost,
31
- "chat_token_discord": self.chat_token_discord,
32
- "name": self.name,
33
- "has_avatar": self.has_avatar,
34
- "hours_by_day": self.hours_by_day,
35
- "hd_by_default": self.hd_by_default,
36
- "use_original_file_name": self.use_original_file_name,
37
- "timesheets_locked": self.timesheets_locked,
38
- "dark_theme_by_default": self.dark_theme_by_default,
39
- "format_duration_in_hours": self.format_duration_in_hours,
40
- "updated_at": self.updated_at,
41
- "created_at": self.created_at,
42
- }
24
+ def present(self, sensitive=False):
25
+ return self.serialize(
26
+ ignored_attrs=(
27
+ []
28
+ if sensitive
29
+ else [
30
+ "chat_token_slack",
31
+ "chat_webhook_mattermost",
32
+ "chat_token_discord",
33
+ ]
34
+ )
43
35
  )
zou/app/models/person.py CHANGED
@@ -94,7 +94,7 @@ class Person(db.Model, BaseMixin, SerializerMixin):
94
94
  TimezoneType(backend="pytz"),
95
95
  default=pytz_timezone(config.DEFAULT_TIMEZONE),
96
96
  )
97
- locale = db.Column(LocaleType, default=Locale("en", "US"))
97
+ locale = db.Column(LocaleType, default=Locale(config.DEFAULT_LOCALE))
98
98
  data = db.Column(JSONB)
99
99
  role = db.Column(ChoiceType(ROLE_TYPES), default="user", nullable=False)
100
100
  has_avatar = db.Column(db.Boolean(), default=False)
@@ -14,35 +14,35 @@ class SerializerMixin(object):
14
14
  orm.attributes.CollectionAttributeImpl,
15
15
  )
16
16
 
17
- def serialize(self, obj_type=None, relations=False, milliseconds=False):
17
+ def serialize(
18
+ self,
19
+ obj_type=None,
20
+ relations=False,
21
+ milliseconds=False,
22
+ ignored_attrs=[],
23
+ ):
18
24
  attrs = inspect(self.__class__).all_orm_descriptors.keys()
19
- if relations:
20
- obj_dict = {
21
- attr: serialize_value(
22
- getattr(self, attr), milliseconds=milliseconds
23
- )
24
- for attr in attrs
25
- }
26
- else:
27
- obj_dict = {
28
- attr: serialize_value(
29
- getattr(self, attr), milliseconds=milliseconds
30
- )
31
- for attr in attrs
32
- if not self.is_join(attr)
33
- }
25
+ obj_dict = {
26
+ attr: serialize_value(
27
+ getattr(self, attr), milliseconds=milliseconds
28
+ )
29
+ for attr in attrs
30
+ if attr not in ignored_attrs
31
+ and (relations or not self.is_join(attr))
32
+ }
34
33
  obj_dict["type"] = obj_type or type(self).__name__
35
34
  return obj_dict
36
35
 
37
36
  @staticmethod
38
37
  def serialize_list(
39
- models, obj_type=None, relations=False, milliseconds=False
38
+ models, obj_type=None, relations=False, milliseconds=False, **kwargs
40
39
  ):
41
40
  return [
42
41
  model.serialize(
43
42
  obj_type=obj_type,
44
43
  relations=relations,
45
44
  milliseconds=milliseconds,
45
+ **kwargs
46
46
  )
47
47
  for model in models
48
48
  ]
@@ -40,7 +40,7 @@ from zou.app.services.exception import (
40
40
 
41
41
  def clear_asset_cache(asset_id):
42
42
  cache.cache.delete_memoized(get_asset, asset_id)
43
- cache.cache.delete_memoized(get_asset_with_relations, asset_id)
43
+ cache.cache.delete_memoized(get_asset, asset_id, True)
44
44
  cache.cache.delete_memoized(get_full_asset, asset_id)
45
45
 
46
46
 
@@ -416,19 +416,13 @@ def get_asset_raw(entity_id):
416
416
 
417
417
 
418
418
  @cache.memoize_function(120)
419
- def get_asset(entity_id):
419
+ def get_asset(entity_id, relations=False):
420
420
  """
421
421
  Return a given asset as a dict.
422
422
  """
423
- return get_asset_raw(entity_id).serialize(obj_type="Asset")
424
-
425
-
426
- @cache.memoize_function(120)
427
- def get_asset_with_relations(entity_id):
428
- """
429
- Return a given asset as a dict.
430
- """
431
- return get_asset_raw(entity_id).serialize(obj_type="Asset", relations=True)
423
+ return get_asset_raw(entity_id).serialize(
424
+ obj_type="Asset", relations=relations
425
+ )
432
426
 
433
427
 
434
428
  def get_asset_by_shotgun_id(shotgun_id):
@@ -458,7 +452,7 @@ def get_full_asset(asset_id):
458
452
  """
459
453
  assets = get_assets_and_tasks({"id": asset_id}, with_episode_ids=True)
460
454
  if len(assets) > 0:
461
- asset = get_asset_with_relations(asset_id)
455
+ asset = get_asset(asset_id, relations=True)
462
456
  asset_type_id = asset["entity_type_id"]
463
457
  asset_type = get_asset_type(asset_type_id)
464
458
  project = Project.get(asset["project_id"])
@@ -414,7 +414,7 @@ def _create_episode_casting_link(entity, asset_id, nb_occurences=1, label=""):
414
414
  link = EntityLink.create(
415
415
  entity_in_id=sequence["parent_id"],
416
416
  entity_out_id=asset_id,
417
- nb_occurences=1,
417
+ nb_occurences=nb_occurences,
418
418
  label=label,
419
419
  )
420
420
  events.emit(
@@ -82,7 +82,7 @@ def create_comment(
82
82
  """
83
83
  Create a new comment and related: news, notifications and events.
84
84
  """
85
- task = tasks_service.get_task_with_relations(task_id)
85
+ task = tasks_service.get_task(task_id, relations=True)
86
86
  task_status = tasks_service.get_task_status(task_status_id)
87
87
  author = _get_comment_author(person_id)
88
88
  _check_retake_capping(task_status, task)
@@ -33,7 +33,7 @@ from zou.app.services.exception import (
33
33
 
34
34
  def clear_concept_cache(concept_id):
35
35
  cache.cache.delete_memoized(get_concept, concept_id)
36
- cache.cache.delete_memoized(get_concept_with_relations, concept_id)
36
+ cache.cache.delete_memoized(get_concept, concept_id, True)
37
37
  cache.cache.delete_memoized(get_full_concept, concept_id)
38
38
 
39
39
 
@@ -61,23 +61,15 @@ def get_concept_raw(concept_id):
61
61
 
62
62
 
63
63
  @cache.memoize_function(120)
64
- def get_concept_with_relations(concept_id):
64
+ def get_concept(concept_id, relations=False):
65
65
  """
66
66
  Return given concept as a dictionary.
67
67
  """
68
68
  return get_concept_raw(concept_id).serialize(
69
- obj_type="Concept", relations=True
69
+ obj_type="Concept", relations=relations
70
70
  )
71
71
 
72
72
 
73
- @cache.memoize_function(120)
74
- def get_concept(concept_id):
75
- """
76
- Return given concept as a dictionary.
77
- """
78
- return get_concept_raw(concept_id).serialize(obj_type="Concept")
79
-
80
-
81
73
  @cache.memoize_function(120)
82
74
  def get_full_concept(concept_id):
83
75
  """
@@ -86,7 +78,7 @@ def get_full_concept(concept_id):
86
78
  concepts = get_concepts_and_tasks({"id": concept_id})
87
79
  if len(concepts) > 0:
88
80
  concept = concepts[0]
89
- concept.update(get_concept_with_relations(concept_id))
81
+ concept.update(get_concept(concept_id, relations=True))
90
82
  return concept
91
83
  else:
92
84
  raise ConceptNotFoundException
@@ -33,7 +33,7 @@ from zou.app.services.exception import (
33
33
 
34
34
  def clear_edit_cache(edit_id):
35
35
  cache.cache.delete_memoized(get_edit, edit_id)
36
- cache.cache.delete_memoized(get_edit_with_relations, edit_id)
36
+ cache.cache.delete_memoized(get_edit, edit_id, True)
37
37
  cache.cache.delete_memoized(get_full_edit, edit_id)
38
38
 
39
39
 
@@ -241,19 +241,13 @@ def get_edit_raw(edit_id):
241
241
 
242
242
 
243
243
  @cache.memoize_function(120)
244
- def get_edit(edit_id):
244
+ def get_edit(edit_id, relations=False):
245
245
  """
246
246
  Return given edit as a dictionary.
247
247
  """
248
- return get_edit_raw(edit_id).serialize(obj_type="Edit")
249
-
250
-
251
- @cache.memoize_function(120)
252
- def get_edit_with_relations(edit_id):
253
- """
254
- Return given edit as a dictionary.
255
- """
256
- return get_edit_raw(edit_id).serialize(obj_type="Edit", relations=True)
248
+ return get_edit_raw(edit_id).serialize(
249
+ obj_type="Edit", relations=relations
250
+ )
257
251
 
258
252
 
259
253
  @cache.memoize_function(120)
@@ -7,7 +7,7 @@ from sqlalchemy import func
7
7
  def get_last_events(
8
8
  after=None,
9
9
  before=None,
10
- page_size=100,
10
+ limit=100,
11
11
  only_files=False,
12
12
  project_id=None,
13
13
  name=None,
@@ -46,7 +46,7 @@ def get_last_events(
46
46
  if name is not None:
47
47
  query = query.filter(ApiEvent.name == name)
48
48
 
49
- events = query.limit(page_size).all()
49
+ events = query.limit(limit).all()
50
50
  return [
51
51
  fields.serialize_dict(
52
52
  {
@@ -71,7 +71,7 @@ def create_login_log(person_id, ip_address, origin):
71
71
  return login_log.serialize()
72
72
 
73
73
 
74
- def get_last_login_logs(before=None, page_size=100):
74
+ def get_last_login_logs(before=None, limit=100):
75
75
  """
76
76
  Return last 100 login logs published. If before parameter is set, it returns
77
77
  last 100 login logs before this date.
@@ -85,7 +85,7 @@ def get_last_login_logs(before=None, page_size=100):
85
85
  LoginLog.created_at < func.cast(before, LoginLog.created_at.type)
86
86
  )
87
87
 
88
- login_logs = query.limit(page_size).all()
88
+ login_logs = query.limit(limit).all()
89
89
  return [
90
90
  {
91
91
  "created_at": fields.serialize_value(created_at),
@@ -92,7 +92,7 @@ def get_last_news_for_project(
92
92
  task_status_id=None,
93
93
  author_id=None,
94
94
  page=1,
95
- page_size=50,
95
+ limit=50,
96
96
  before=None,
97
97
  after=None,
98
98
  episode_id=None,
@@ -102,7 +102,7 @@ def get_last_news_for_project(
102
102
  Return last 50 news for given project. Add related information to make it
103
103
  displayable.
104
104
  """
105
- offset = (page - 1) * page_size
105
+ offset = (page - 1) * limit
106
106
 
107
107
  query = (
108
108
  News.query.order_by(News.created_at.desc())
@@ -158,7 +158,7 @@ def get_last_news_for_project(
158
158
  News.created_at < func.cast(before, News.created_at.type)
159
159
  )
160
160
 
161
- (total, nb_pages) = _get_news_total(query, page_size)
161
+ (total, nb_pages) = _get_news_total(query, limit)
162
162
 
163
163
  query = query.add_columns(
164
164
  Project.id,
@@ -172,7 +172,7 @@ def get_last_news_for_project(
172
172
  Entity.preview_file_id,
173
173
  )
174
174
 
175
- query = query.limit(page_size)
175
+ query = query.limit(limit)
176
176
  query = query.offset(offset)
177
177
  news_list = query.all()
178
178
  result = []
@@ -221,15 +221,15 @@ def get_last_news_for_project(
221
221
  "data": result,
222
222
  "total": total,
223
223
  "nb_pages": nb_pages,
224
- "limit": page_size,
224
+ "limit": limit,
225
225
  "offset": offset,
226
226
  "page": page,
227
227
  }
228
228
 
229
229
 
230
- def _get_news_total(query, page_size):
230
+ def _get_news_total(query, limit):
231
231
  total = query.count()
232
- nb_pages = int(math.ceil(total / float(page_size)))
232
+ nb_pages = int(math.ceil(total / float(limit)))
233
233
  return total, nb_pages
234
234
 
235
235
 
@@ -314,4 +314,4 @@ def get_news_for_entity(entity_id):
314
314
  """
315
315
  Get all news related to a given entity.
316
316
  """
317
- return get_last_news_for_project(entity_id=entity_id, page_size=2000)
317
+ return get_last_news_for_project(entity_id=entity_id, limit=2000)
@@ -36,8 +36,9 @@ def clear_person_cache():
36
36
  cache.cache.delete_memoized(get_persons)
37
37
 
38
38
 
39
- def clear_oranisation_cache():
39
+ def clear_organisation_cache():
40
40
  cache.cache.delete_memoized(get_organisation)
41
+ cache.cache.delete_memoized(get_organisation, True)
41
42
 
42
43
 
43
44
  @cache.memoize_function(120)
@@ -230,6 +231,8 @@ def create_person(
230
231
  raise WrongParameterException(
231
232
  "Expiration date can't be in the past."
232
233
  )
234
+ except WrongParameterException:
235
+ raise
233
236
  except:
234
237
  raise WrongParameterException("Expiration date is not valid.")
235
238
 
@@ -310,6 +313,8 @@ def update_person(person_id, data, bypass_protected_accounts=False):
310
313
  raise WrongParameterException(
311
314
  "Expiration date can't be in the past."
312
315
  )
316
+ except WrongParameterException:
317
+ raise
313
318
  except:
314
319
  raise WrongParameterException("Expiration date is not valid.")
315
320
 
@@ -480,14 +485,14 @@ Thank you and see you soon on Kitsu,
480
485
 
481
486
 
482
487
  @cache.memoize_function(120)
483
- def get_organisation():
488
+ def get_organisation(sensitive=False):
484
489
  """
485
490
  Return organisation set up on this instance. It creates it if none exists.
486
491
  """
487
492
  organisation = Organisation.query.first()
488
493
  if organisation is None:
489
494
  organisation = Organisation.create(name="Kitsu")
490
- return organisation.present()
495
+ return organisation.present(sensitive=sensitive)
491
496
 
492
497
 
493
498
  def update_organisation(organisation_id, data):
@@ -497,7 +502,7 @@ def update_organisation(organisation_id, data):
497
502
  organisation = Organisation.get(organisation_id)
498
503
  organisation.update(data)
499
504
  events.emit("organisation:update", {"organisation_id": organisation_id})
500
- clear_oranisation_cache()
505
+ clear_organisation_cache()
501
506
  return organisation.present()
502
507
 
503
508
 
@@ -89,7 +89,7 @@ def _is_valid_partial_resolution(resolution):
89
89
  return resolution is not None and bool(re.match(r"x\d{3,4}", resolution))
90
90
 
91
91
 
92
- def get_preview_file_fps(project):
92
+ def get_preview_file_fps(project, entity=None):
93
93
  """
94
94
  Return fps set at project level or default fps if the dimensions are not
95
95
  set.
@@ -97,6 +97,12 @@ def get_preview_file_fps(project):
97
97
  fps = "25.00"
98
98
  if project.get("fps", None) is not None:
99
99
  fps = project["fps"].replace(",", ".")
100
+
101
+ if entity is not None:
102
+ entity_data = entity.get("data", {}) or {}
103
+ if entity_data.get("fps", None) is not None:
104
+ fps = entity_data["fps"].replace(",", ".")
105
+
100
106
  return "%.3f" % float(fps)
101
107
 
102
108
 
@@ -193,7 +199,7 @@ def prepare_and_store_movie(
193
199
  preview_file = set_preview_file_as_broken(preview_file_id)
194
200
  return preview_file
195
201
 
196
- fps = get_preview_file_fps(project)
202
+ fps = get_preview_file_fps(project, entity)
197
203
  (width, height) = get_preview_file_dimensions(project, entity)
198
204
 
199
205
  if normalize:
@@ -619,7 +625,9 @@ def extract_frame_from_preview_file(preview_file, frame_number):
619
625
  else:
620
626
  raise PreviewFileNotFoundException
621
627
 
622
- fps = get_preview_file_fps(project)
628
+ fps = get_preview_file_fps(
629
+ project, get_entity_from_preview_file(preview_file["id"])
630
+ )
623
631
  extracted_frame_path = movie.extract_frame_from_movie(
624
632
  preview_file_path, frame_number, fps
625
633
  )
@@ -650,7 +658,7 @@ def extract_tile_from_preview_file(preview_file):
650
658
  extracted_tile_path = movie.generate_tile(preview_file_path)
651
659
  return extracted_tile_path
652
660
  else:
653
- return WrongParameterException("Preview file is not a movie")
661
+ raise WrongParameterException("Preview file is not a movie")
654
662
 
655
663
 
656
664
  def reset_movie_files_metadata():
@@ -38,7 +38,7 @@ from sqlalchemy import or_
38
38
 
39
39
  def clear_project_cache(project_id):
40
40
  cache.cache.delete_memoized(get_project, project_id)
41
- cache.cache.delete_memoized(get_project_with_relations, project_id)
41
+ cache.cache.delete_memoized(get_project, project_id, True)
42
42
  cache.cache.delete_memoized(get_project_by_name)
43
43
  cache.cache.delete_memoized(open_projects)
44
44
 
@@ -259,21 +259,12 @@ def get_project_raw(project_id):
259
259
 
260
260
 
261
261
  @cache.memoize_function(240)
262
- def get_project(project_id):
262
+ def get_project(project_id, relations=False):
263
263
  """
264
264
  Get project matching given id, as a dict. Raises an exception if project is
265
265
  not found.
266
266
  """
267
- return get_project_raw(project_id).serialize()
268
-
269
-
270
- @cache.memoize_function(240)
271
- def get_project_with_relations(project_id):
272
- """
273
- Get project matching given id, as a dict. Raises an exception if project is
274
- not found.
275
- """
276
- return get_project_raw(project_id).serialize(relations=True)
267
+ return get_project_raw(project_id).serialize(relations=relations)
277
268
 
278
269
 
279
270
  @cache.memoize_function(120)
@@ -487,7 +478,7 @@ def add_metadata_descriptor(
487
478
  field_name=slugify.slugify(name, separator="_"),
488
479
  )
489
480
  except Exception:
490
- raise WrongParameterException
481
+ raise WrongParameterException("Metadata descriptor already exists.")
491
482
  events.emit(
492
483
  "metadata-descriptor:new",
493
484
  {"metadata_descriptor_id": str(descriptor.id)},
@@ -50,7 +50,7 @@ from zou.app.services.exception import (
50
50
 
51
51
  def clear_shot_cache(shot_id):
52
52
  cache.cache.delete_memoized(get_shot, shot_id)
53
- cache.cache.delete_memoized(get_shot_with_relations, shot_id)
53
+ cache.cache.delete_memoized(get_shot, shot_id, True)
54
54
  cache.cache.delete_memoized(get_full_shot, shot_id)
55
55
 
56
56
 
@@ -402,19 +402,13 @@ def get_shot_raw(shot_id):
402
402
 
403
403
 
404
404
  @cache.memoize_function(120)
405
- def get_shot(shot_id):
405
+ def get_shot(shot_id, relations=False):
406
406
  """
407
407
  Return given shot as a dictionary.
408
408
  """
409
- return get_shot_raw(shot_id).serialize(obj_type="Shot")
410
-
411
-
412
- @cache.memoize_function(120)
413
- def get_shot_with_relations(shot_id):
414
- """
415
- Return given shot as a dictionary.
416
- """
417
- return get_shot_raw(shot_id).serialize(obj_type="Shot", relations=True)
409
+ return get_shot_raw(shot_id).serialize(
410
+ obj_type="Shot", relations=relations
411
+ )
418
412
 
419
413
 
420
414
  @cache.memoize_function(120)
@@ -426,7 +420,7 @@ def get_full_shot(shot_id):
426
420
  shots = get_shots_and_tasks({"id": shot_id})
427
421
  if len(shots) > 0:
428
422
  shot = shots[0]
429
- shot.update(get_shot_with_relations(shot_id))
423
+ shot.update(get_shot(shot_id, relations=True))
430
424
  return shot
431
425
  else:
432
426
  raise ShotNotFoundException
@@ -323,12 +323,12 @@ def run_other_sync(project=None, with_events=False):
323
323
  sync_entries("events", ApiEvent, project=project)
324
324
 
325
325
 
326
- def run_last_events_sync(minutes=0, page_size=300):
326
+ def run_last_events_sync(minutes=0, limit=300):
327
327
  """
328
328
  Retrieve last events from source instance and import related data and
329
329
  action.
330
330
  """
331
- path = "events/last?page_size=%s" % page_size
331
+ path = "events/last?limit=%s" % limit
332
332
  if minutes > 0:
333
333
  now = date_helpers.get_utc_now_datetime()
334
334
  min_before = now - datetime.timedelta(minutes=minutes)
@@ -346,12 +346,12 @@ def run_last_events_sync(minutes=0, page_size=300):
346
346
  pass
347
347
 
348
348
 
349
- def run_last_events_files(minutes=0, page_size=50):
349
+ def run_last_events_files(minutes=0, limit=50):
350
350
  """
351
351
  Retrieve last events from source instance and import related data and
352
352
  action.
353
353
  """
354
- path = "events/last?only_files=true&page_size=%s" % page_size
354
+ path = "events/last?only_files=true&limit=%s" % limit
355
355
  if minutes > 0:
356
356
  now = date_helpers.get_utc_now_datetime()
357
357
  min_before = now - datetime.timedelta(minutes=minutes)