From 3204e6cdcefaad3826554635ef33442b72d349c6 Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Thu, 28 Nov 2024 23:43:32 +0100 Subject: [PATCH 1/7] [qa] fix nb_occurences not used in _create_episode_casting_link --- zou/app/services/breakdown_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zou/app/services/breakdown_service.py b/zou/app/services/breakdown_service.py index 3da27761e6..fb66ae92e3 100644 --- a/zou/app/services/breakdown_service.py +++ b/zou/app/services/breakdown_service.py @@ -414,7 +414,7 @@ def _create_episode_casting_link(entity, asset_id, nb_occurences=1, label=""): link = EntityLink.create( entity_in_id=sequence["parent_id"], entity_out_id=asset_id, - nb_occurences=1, + nb_occurences=nb_occurences, label=label, ) events.emit( From 6b9099f0dc8bcb4ec5c178b91b46c4759ff1c94d Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Thu, 28 Nov 2024 23:44:57 +0100 Subject: [PATCH 2/7] [requirements] upgrade --- setup.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 808ef615c8..5f18b51f75 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,7 @@ install_requires = discord.py==2.4.0 email-validator==2.2.0 ffmpeg-python==0.2.0 - fido2==1.1.3 + fido2==1.2.0 flasgger==0.9.7.1 flask_bcrypt==1.0.1 flask_caching==2.3.0 @@ -47,7 +47,7 @@ install_requires = flask-migrate==4.0.7 flask-socketio==5.4.1 flask==3.1.0 - gazu==0.10.19 + gazu==0.10.20 gevent-websocket==0.10.1 gevent==24.11.1 gunicorn==23.0.0 @@ -56,7 +56,7 @@ install_requires = Jinja2==3.1.4 ldap3==2.9.1 matterhook==0.2 - meilisearch==0.31.6 + meilisearch==0.32.0 numpy==2.0.1; python_version == '3.9' numpy==2.1.3; python_version >= '3.10' opencv-python==4.10.0.84 @@ -78,7 +78,7 @@ install_requires = slackclient==2.9.4 sqlalchemy_utils==0.41.2 sqlalchemy==2.0.36 - ua-parser==0.18.0 + ua-parser==1.0.0 werkzeug==3.1.3 [options.package_data] From 18b2d8a7dd0c0cbfa64596912e8b815db7a58c6e Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Fri, 29 Nov 2024 00:13:33 +0100 Subject: [PATCH 3/7] [exceptions] Fix changes made by commit 8bedda8 (some exceptions are catch before the errorhandler) --- tests/models/test_person.py | 2 +- zou/app/blueprints/crud/base.py | 17 ----------------- zou/app/blueprints/crud/person.py | 4 ++++ zou/app/blueprints/persons/resources.py | 1 - zou/app/blueprints/shots/resources.py | 1 - zou/app/services/persons_service.py | 4 ++++ zou/app/services/preview_files_service.py | 2 +- zou/app/services/projects_service.py | 2 +- 8 files changed, 11 insertions(+), 22 deletions(-) diff --git a/tests/models/test_person.py b/tests/models/test_person.py index e155063fa3..e137483b6e 100644 --- a/tests/models/test_person.py +++ b/tests/models/test_person.py @@ -77,7 +77,7 @@ def test_create_too_much_person(self): "email": "john3.doe@gmail.com", } resp = self.post("data/persons", data, 400) - self.assertEqual(resp["limit"], 4) + self.assertEqual(resp["data"]["limit"], 4) config.USER_LIMIT = 100 def test_create_person_with_no_data(self): diff --git a/zou/app/blueprints/crud/base.py b/zou/app/blueprints/crud/base.py index f1757aadaa..7c7b4a8ffa 100644 --- a/zou/app/blueprints/crud/base.py +++ b/zou/app/blueprints/crud/base.py @@ -13,7 +13,6 @@ from zou.app.utils import events, fields, permissions, query from zou.app.services.exception import ( WrongParameterException, - WrongParameterException, ) @@ -259,14 +258,6 @@ def post(self): current_app.logger.error(str(exception), exc_info=1) return {"message": str(exception)}, 400 - except WrongParameterException as exception: - current_app.logger.error(str(exception), exc_info=1) - return ( - exception.dict - if exception.dict is not None - else {"message": str(exception)} - ), 400 - def emit_create_event(self, instance_dict): return events.emit( "%s:new" % self.model.__tablename__.replace("_", "-"), @@ -430,14 +421,6 @@ def put(self, instance_id): current_app.logger.error(str(exception), exc_info=1) return {"message": str(exception)}, 400 - except WrongParameterException as exception: - current_app.logger.error(str(exception), exc_info=1) - return ( - exception.dict - if exception.dict is not None - else {"message": str(exception)} - ), 400 - @jwt_required() def delete(self, instance_id): """ diff --git a/zou/app/blueprints/crud/person.py b/zou/app/blueprints/crud/person.py index 1995cb8e7c..ee186d359c 100644 --- a/zou/app/blueprints/crud/person.py +++ b/zou/app/blueprints/crud/person.py @@ -97,6 +97,8 @@ def check_creation_integrity(self, data): raise WrongParameterException( "Expiration date can't be in the past." ) + except WrongParameterException: + raise except: raise WrongParameterException("Expiration date is not valid.") return data @@ -178,6 +180,8 @@ def update_data(self, data, instance_id): raise WrongParameterException( "Expiration date can't be in the past." ) + except WrongParameterException: + raise except: raise WrongParameterException("Expiration date is not valid.") return data diff --git a/zou/app/blueprints/persons/resources.py b/zou/app/blueprints/persons/resources.py index 734d33c7da..daaabe6dfd 100644 --- a/zou/app/blueprints/persons/resources.py +++ b/zou/app/blueprints/persons/resources.py @@ -30,7 +30,6 @@ UnactiveUserException, TwoFactorAuthenticationNotEnabledException, PersonInProtectedAccounts, - WrongParameterException, ) from zou.app.services.auth_service import ( disable_two_factor_authentication_for_person, diff --git a/zou/app/blueprints/shots/resources.py b/zou/app/blueprints/shots/resources.py index da70d7b88f..f5db6c7a22 100644 --- a/zou/app/blueprints/shots/resources.py +++ b/zou/app/blueprints/shots/resources.py @@ -20,7 +20,6 @@ from zou.app.utils import fields, query, permissions from zou.app.services.exception import ( WrongParameterException, - WrongParameterException, ) diff --git a/zou/app/services/persons_service.py b/zou/app/services/persons_service.py index 5128ba25a5..bdea4e85c2 100644 --- a/zou/app/services/persons_service.py +++ b/zou/app/services/persons_service.py @@ -230,6 +230,8 @@ def create_person( raise WrongParameterException( "Expiration date can't be in the past." ) + except WrongParameterException: + raise except: raise WrongParameterException("Expiration date is not valid.") @@ -310,6 +312,8 @@ def update_person(person_id, data, bypass_protected_accounts=False): raise WrongParameterException( "Expiration date can't be in the past." ) + except WrongParameterException: + raise except: raise WrongParameterException("Expiration date is not valid.") diff --git a/zou/app/services/preview_files_service.py b/zou/app/services/preview_files_service.py index b822e6069a..70b010e93f 100644 --- a/zou/app/services/preview_files_service.py +++ b/zou/app/services/preview_files_service.py @@ -650,7 +650,7 @@ def extract_tile_from_preview_file(preview_file): extracted_tile_path = movie.generate_tile(preview_file_path) return extracted_tile_path else: - return WrongParameterException("Preview file is not a movie") + raise WrongParameterException("Preview file is not a movie") def reset_movie_files_metadata(): diff --git a/zou/app/services/projects_service.py b/zou/app/services/projects_service.py index 8e58e88021..44385d5c19 100644 --- a/zou/app/services/projects_service.py +++ b/zou/app/services/projects_service.py @@ -487,7 +487,7 @@ def add_metadata_descriptor( field_name=slugify.slugify(name, separator="_"), ) except Exception: - raise WrongParameterException + raise WrongParameterException("Metadata descriptor already exists.") events.emit( "metadata-descriptor:new", {"metadata_descriptor_id": str(descriptor.id)}, From c979b3bd3d9e88307f1187e7ea65f03f1551ca82 Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Fri, 29 Nov 2024 02:26:31 +0100 Subject: [PATCH 4/7] [config] add new environment variable DEFAULT_LOCALE to specify a default locale for persons --- zou/app/config.py | 1 + zou/app/models/person.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/zou/app/config.py b/zou/app/config.py index 21b2ed92fe..b9cd57e1b3 100644 --- a/zou/app/config.py +++ b/zou/app/config.py @@ -158,6 +158,7 @@ IS_SELF_HOSTED = envtobool("IS_SELF_HOSTED", True) DEFAULT_TIMEZONE = os.getenv("DEFAULT_TIMEZONE", "Europe/Paris") +DEFAULT_LOCALE = os.getenv("DEFAULT_LOCALE", "en_US") USER_LIMIT = int(os.getenv("USER_LIMIT", "100")) MIN_PASSWORD_LENGTH = int(os.getenv("MIN_PASSWORD_LENGTH", 8)) diff --git a/zou/app/models/person.py b/zou/app/models/person.py index ce71965e71..4cd3ff4a65 100644 --- a/zou/app/models/person.py +++ b/zou/app/models/person.py @@ -94,7 +94,7 @@ class Person(db.Model, BaseMixin, SerializerMixin): TimezoneType(backend="pytz"), default=pytz_timezone(config.DEFAULT_TIMEZONE), ) - locale = db.Column(LocaleType, default=Locale("en", "US")) + locale = db.Column(LocaleType, default=Locale(config.DEFAULT_LOCALE)) data = db.Column(JSONB) role = db.Column(ChoiceType(ROLE_TYPES), default="user", nullable=False) has_avatar = db.Column(db.Boolean(), default=False) From 04b63c7292478fe94c315dcbcfe599d324901850 Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Fri, 29 Nov 2024 03:06:42 +0100 Subject: [PATCH 5/7] [qa] refactoring --- zou/app/blueprints/comments/resources.py | 4 +-- zou/app/blueprints/crud/base.py | 9 ++++-- zou/app/blueprints/crud/comments.py | 31 +++------------------ zou/app/blueprints/crud/task.py | 5 +++- zou/app/services/assets_service.py | 18 ++++-------- zou/app/services/comments_service.py | 2 +- zou/app/services/concepts_service.py | 16 +++-------- zou/app/services/edits_service.py | 16 ++++------- zou/app/services/projects_service.py | 15 ++-------- zou/app/services/shots_service.py | 18 ++++-------- zou/app/services/tasks_service.py | 35 ++++++------------------ zou/app/services/user_service.py | 2 +- 12 files changed, 51 insertions(+), 120 deletions(-) diff --git a/zou/app/blueprints/comments/resources.py b/zou/app/blueprints/comments/resources.py index 7122bff48c..39b8d2fcdc 100644 --- a/zou/app/blueprints/comments/resources.py +++ b/zou/app/blueprints/comments/resources.py @@ -435,8 +435,8 @@ def get_allowed_comments_only(self, comments, person): allowed_comments = [] for comment in comments: try: - task = tasks_service.get_task_with_relations( - comment["object_id"], + task = tasks_service.get_task( + comment["object_id"], relations=True ) if ( person["role"] == "supervisor" diff --git a/zou/app/blueprints/crud/base.py b/zou/app/blueprints/crud/base.py index 7c7b4a8ffa..a7bffe4362 100644 --- a/zou/app/blueprints/crud/base.py +++ b/zou/app/blueprints/crud/base.py @@ -281,6 +281,10 @@ def get_model_or_404(self, instance_id): abort(404) return instance + def get_serialized_instance(self, instance_id, relations=True): + instance = self.get_model_or_404(instance_id) + return self.serialize_instance(instance, relations=relations) + def check_read_permissions(self, instance_dict): return permissions.check_admin_permissions() @@ -329,8 +333,9 @@ def get(self, instance_id): """ relations = self.get_bool_parameter("relations", "true") try: - instance = self.get_model_or_404(instance_id) - result = self.serialize_instance(instance, relations=relations) + result = self.get_serialized_instance( + instance_id, relations=relations + ) self.check_read_permissions(result) result = self.clean_get_result(result) diff --git a/zou/app/blueprints/crud/comments.py b/zou/app/blueprints/crud/comments.py index cab3060a49..51a24194f2 100644 --- a/zou/app/blueprints/crud/comments.py +++ b/zou/app/blueprints/crud/comments.py @@ -1,7 +1,5 @@ from flask_jwt_extended import jwt_required -from flask import current_app -from sqlalchemy.exc import StatementError from zou.app.models.comment import Comment from zou.app.models.attachment_file import AttachmentFile @@ -19,10 +17,6 @@ from zou.app.blueprints.crud.base import BaseModelResource, BaseModelsResource -from zou.app.services.exception import ( - CommentNotFoundException, -) - class CommentsResource(BaseModelsResource): def __init__(self): @@ -47,25 +41,8 @@ def __init__(self): BaseModelResource.__init__(self, Comment) self.protected_fields += ["mentions", "department_mentions"] - @jwt_required() - def get(self, instance_id): - """ - Retrieve a model corresponding at given ID and return it as a JSON - object. - """ - try: - instance = tasks_service.get_comment_with_relations(instance_id) - self.check_read_permissions(instance) - result = self.clean_get_result(instance) - - except StatementError as exception: - current_app.logger.error(str(exception), exc_info=1) - return {"message": str(exception)}, 400 - - except ValueError: - raise CommentNotFoundException - - return result, 200 + def get_serialized_instance(self, instance_id, relations=True): + return tasks_service.get_comment(instance_id, relations=relations) def clean_get_result(self, result): if permissions.has_client_permissions(): @@ -123,8 +100,8 @@ def check_update_permissions(self, instance, data): instance["object_id"], relations=True ) task_type = tasks_service.get_task_type(task["task_type_id"]) - project = projects_service.get_project_with_relations( - task["project_id"] + project = projects_service.get_project( + task["project_id"], relations=True ) current_user = persons_service.get_current_user(relations=True) if current_user["id"] not in project["team"]: diff --git a/zou/app/blueprints/crud/task.py b/zou/app/blueprints/crud/task.py index b61de87849..8ec1278fe2 100644 --- a/zou/app/blueprints/crud/task.py +++ b/zou/app/blueprints/crud/task.py @@ -116,7 +116,10 @@ def post(self): instance.save() self.emit_create_event(instance.serialize()) - return tasks_service.get_task_with_relations(str(instance.id)), 201 + return ( + tasks_service.get_task(str(instance.id), relations=True), + 201, + ) except TypeError as exception: current_app.logger.error(str(exception), exc_info=1) diff --git a/zou/app/services/assets_service.py b/zou/app/services/assets_service.py index fb0f328f57..5d1311aff1 100644 --- a/zou/app/services/assets_service.py +++ b/zou/app/services/assets_service.py @@ -40,7 +40,7 @@ def clear_asset_cache(asset_id): cache.cache.delete_memoized(get_asset, asset_id) - cache.cache.delete_memoized(get_asset_with_relations, asset_id) + cache.cache.delete_memoized(get_asset, asset_id, True) cache.cache.delete_memoized(get_full_asset, asset_id) @@ -416,19 +416,13 @@ def get_asset_raw(entity_id): @cache.memoize_function(120) -def get_asset(entity_id): +def get_asset(entity_id, relations=False): """ Return a given asset as a dict. """ - return get_asset_raw(entity_id).serialize(obj_type="Asset") - - -@cache.memoize_function(120) -def get_asset_with_relations(entity_id): - """ - Return a given asset as a dict. - """ - return get_asset_raw(entity_id).serialize(obj_type="Asset", relations=True) + return get_asset_raw(entity_id).serialize( + obj_type="Asset", relations=relations + ) def get_asset_by_shotgun_id(shotgun_id): @@ -458,7 +452,7 @@ def get_full_asset(asset_id): """ assets = get_assets_and_tasks({"id": asset_id}, with_episode_ids=True) if len(assets) > 0: - asset = get_asset_with_relations(asset_id) + asset = get_asset(asset_id, relations=True) asset_type_id = asset["entity_type_id"] asset_type = get_asset_type(asset_type_id) project = Project.get(asset["project_id"]) diff --git a/zou/app/services/comments_service.py b/zou/app/services/comments_service.py index 0b3fd44af4..13f34abf9a 100644 --- a/zou/app/services/comments_service.py +++ b/zou/app/services/comments_service.py @@ -82,7 +82,7 @@ def create_comment( """ Create a new comment and related: news, notifications and events. """ - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) task_status = tasks_service.get_task_status(task_status_id) author = _get_comment_author(person_id) _check_retake_capping(task_status, task) diff --git a/zou/app/services/concepts_service.py b/zou/app/services/concepts_service.py index 09cee0d45e..74b6b3d82b 100644 --- a/zou/app/services/concepts_service.py +++ b/zou/app/services/concepts_service.py @@ -33,7 +33,7 @@ def clear_concept_cache(concept_id): cache.cache.delete_memoized(get_concept, concept_id) - cache.cache.delete_memoized(get_concept_with_relations, concept_id) + cache.cache.delete_memoized(get_concept, concept_id, True) cache.cache.delete_memoized(get_full_concept, concept_id) @@ -61,23 +61,15 @@ def get_concept_raw(concept_id): @cache.memoize_function(120) -def get_concept_with_relations(concept_id): +def get_concept(concept_id, relations=False): """ Return given concept as a dictionary. """ return get_concept_raw(concept_id).serialize( - obj_type="Concept", relations=True + obj_type="Concept", relations=relations ) -@cache.memoize_function(120) -def get_concept(concept_id): - """ - Return given concept as a dictionary. - """ - return get_concept_raw(concept_id).serialize(obj_type="Concept") - - @cache.memoize_function(120) def get_full_concept(concept_id): """ @@ -86,7 +78,7 @@ def get_full_concept(concept_id): concepts = get_concepts_and_tasks({"id": concept_id}) if len(concepts) > 0: concept = concepts[0] - concept.update(get_concept_with_relations(concept_id)) + concept.update(get_concept(concept_id, relations=True)) return concept else: raise ConceptNotFoundException diff --git a/zou/app/services/edits_service.py b/zou/app/services/edits_service.py index 8eca344870..cdb6d16f9d 100644 --- a/zou/app/services/edits_service.py +++ b/zou/app/services/edits_service.py @@ -33,7 +33,7 @@ def clear_edit_cache(edit_id): cache.cache.delete_memoized(get_edit, edit_id) - cache.cache.delete_memoized(get_edit_with_relations, edit_id) + cache.cache.delete_memoized(get_edit, edit_id, True) cache.cache.delete_memoized(get_full_edit, edit_id) @@ -241,19 +241,13 @@ def get_edit_raw(edit_id): @cache.memoize_function(120) -def get_edit(edit_id): +def get_edit(edit_id, relations=False): """ Return given edit as a dictionary. """ - return get_edit_raw(edit_id).serialize(obj_type="Edit") - - -@cache.memoize_function(120) -def get_edit_with_relations(edit_id): - """ - Return given edit as a dictionary. - """ - return get_edit_raw(edit_id).serialize(obj_type="Edit", relations=True) + return get_edit_raw(edit_id).serialize( + obj_type="Edit", relations=relations + ) @cache.memoize_function(120) diff --git a/zou/app/services/projects_service.py b/zou/app/services/projects_service.py index 44385d5c19..99841b88b8 100644 --- a/zou/app/services/projects_service.py +++ b/zou/app/services/projects_service.py @@ -38,7 +38,7 @@ def clear_project_cache(project_id): cache.cache.delete_memoized(get_project, project_id) - cache.cache.delete_memoized(get_project_with_relations, project_id) + cache.cache.delete_memoized(get_project, project_id, True) cache.cache.delete_memoized(get_project_by_name) cache.cache.delete_memoized(open_projects) @@ -259,21 +259,12 @@ def get_project_raw(project_id): @cache.memoize_function(240) -def get_project(project_id): +def get_project(project_id, relations=False): """ Get project matching given id, as a dict. Raises an exception if project is not found. """ - return get_project_raw(project_id).serialize() - - -@cache.memoize_function(240) -def get_project_with_relations(project_id): - """ - Get project matching given id, as a dict. Raises an exception if project is - not found. - """ - return get_project_raw(project_id).serialize(relations=True) + return get_project_raw(project_id).serialize(relations=relations) @cache.memoize_function(120) diff --git a/zou/app/services/shots_service.py b/zou/app/services/shots_service.py index efe2b8ffab..ede6e6c10d 100644 --- a/zou/app/services/shots_service.py +++ b/zou/app/services/shots_service.py @@ -50,7 +50,7 @@ def clear_shot_cache(shot_id): cache.cache.delete_memoized(get_shot, shot_id) - cache.cache.delete_memoized(get_shot_with_relations, shot_id) + cache.cache.delete_memoized(get_shot, shot_id, True) cache.cache.delete_memoized(get_full_shot, shot_id) @@ -402,19 +402,13 @@ def get_shot_raw(shot_id): @cache.memoize_function(120) -def get_shot(shot_id): +def get_shot(shot_id, relations=False): """ Return given shot as a dictionary. """ - return get_shot_raw(shot_id).serialize(obj_type="Shot") - - -@cache.memoize_function(120) -def get_shot_with_relations(shot_id): - """ - Return given shot as a dictionary. - """ - return get_shot_raw(shot_id).serialize(obj_type="Shot", relations=True) + return get_shot_raw(shot_id).serialize( + obj_type="Shot", relations=relations + ) @cache.memoize_function(120) @@ -426,7 +420,7 @@ def get_full_shot(shot_id): shots = get_shots_and_tasks({"id": shot_id}) if len(shots) > 0: shot = shots[0] - shot.update(get_shot_with_relations(shot_id)) + shot.update(get_shot(shot_id, relations=True)) return shot else: raise ShotNotFoundException diff --git a/zou/app/services/tasks_service.py b/zou/app/services/tasks_service.py index ad2212765d..e9fbb5a691 100644 --- a/zou/app/services/tasks_service.py +++ b/zou/app/services/tasks_service.py @@ -91,13 +91,12 @@ def clear_studio_cache(studio_id): def clear_task_cache(task_id): cache.cache.delete_memoized(get_task, task_id) cache.cache.delete_memoized(get_task, task_id, True) - cache.cache.delete_memoized(get_task_with_relations, task_id) @cache.memoize_function(120) def clear_comment_cache(comment_id): cache.cache.delete_memoized(get_comment, comment_id) - cache.cache.delete_memoized(get_comment_with_relations, comment_id) + cache.cache.delete_memoized(get_comment, comment_id, True) @cache.memoize_function(120) @@ -250,14 +249,6 @@ def get_task(task_id, relations=False): return get_task_raw(task_id).serialize(relations=relations) -@cache.memoize_function(120) -def get_task_with_relations(task_id): - """ - Get task matching given id as a dictionary. - """ - return get_task_raw(task_id).serialize(relations=True) - - def get_task_by_shotgun_id(shotgun_id): """ Get task matching given shotgun id as a dictionary. @@ -396,7 +387,7 @@ def _convert_rows_to_detailed_tasks(rows, relations=False): entity_name, ) = entry - task = get_task_with_relations(str(task_object.id)) + task = get_task(str(task_object.id), relations=relations) task["project_name"] = project_name task["task_type_name"] = task_type_name task["task_status_name"] = task_status_name @@ -774,21 +765,11 @@ def get_comment_raw(comment_id): @cache.memoize_function(120) -def get_comment(comment_id): +def get_comment(comment_id, relations=False): """ Return comment matching give id as a dict. """ - comment = get_comment_raw(comment_id) - return comment.serialize() - - -@cache.memoize_function(120) -def get_comment_with_relations(comment_id): - """ - Return comment matching give id as a dict with joins information. - """ - comment = get_comment_raw(comment_id) - return comment.serialize(relations=True) + return get_comment_raw(comment_id).serialize(relations=relations) def get_comment_by_preview_file_id(preview_file_id): @@ -985,7 +966,7 @@ def get_person_tasks(person_id, projects, is_done=None): except EpisodeNotFoundException: episode_name = "MP" - task_dict = get_task_with_relations(str(task.id)) + task_dict = get_task(str(task.id), relations=True) if entity_type_name == "Sequence" and entity_parent_id is not None: episode_id = entity_parent_id episode = shots_service.get_episode(episode_id) @@ -1117,7 +1098,7 @@ def get_person_tasks_to_check(project_ids=None, department_ids=None): if episode_id is None: episode_id = entity_source_id - task_dict = get_task_with_relations(str(task.id)) + task_dict = get_task(str(task.id), relations=True) if entity_type_name == "Sequence" and entity_parent_id is not None: episode_id = entity_parent_id episode = shots_service.get_episode(episode_id) @@ -1729,7 +1710,7 @@ def get_tasks_for_project( def get_full_task(task_id, user_id): - task = get_task_with_relations(task_id) + task = get_task(task_id, relations=True) task_type = get_task_type(task["task_type_id"]) project = projects_service.get_project(task["project_id"]) task_status = get_task_status(task["task_status_id"]) @@ -2054,7 +2035,7 @@ def get_open_tasks( except EpisodeNotFoundException: episode_name = "MP" - task_dict = get_task_with_relations(str(task.id)) + task_dict = get_task(str(task.id), relations=True) if entity_type_name == "Sequence" and entity_parent_id is not None: episode_id = entity_parent_id episode = shots_service.get_episode(episode_id) diff --git a/zou/app/services/user_service.py b/zou/app/services/user_service.py index 87f647569b..55a049143a 100644 --- a/zou/app/services/user_service.py +++ b/zou/app/services/user_service.py @@ -410,7 +410,7 @@ def check_belong_to_project(project_id): if project_id is None: return False - project = projects_service.get_project_with_relations(str(project_id)) + project = projects_service.get_project(str(project_id), relations=True) current_user = persons_service.get_current_user() return current_user["id"] in project["team"] From 71e99e28fca3e37244d8f70ef965e25188df05bd Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Fri, 29 Nov 2024 03:26:45 +0100 Subject: [PATCH 6/7] [normalization] allow to override fps by entity[data][fps] (fix https://github.com/cgwire/zou/issues/863) --- zou/app/services/preview_files_service.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/zou/app/services/preview_files_service.py b/zou/app/services/preview_files_service.py index 70b010e93f..85b683190d 100644 --- a/zou/app/services/preview_files_service.py +++ b/zou/app/services/preview_files_service.py @@ -89,7 +89,7 @@ def _is_valid_partial_resolution(resolution): return resolution is not None and bool(re.match(r"x\d{3,4}", resolution)) -def get_preview_file_fps(project): +def get_preview_file_fps(project, entity=None): """ Return fps set at project level or default fps if the dimensions are not set. @@ -97,6 +97,12 @@ def get_preview_file_fps(project): fps = "25.00" if project.get("fps", None) is not None: fps = project["fps"].replace(",", ".") + + if entity is not None: + entity_data = entity.get("data", {}) or {} + if entity_data.get("fps", None) is not None: + fps = entity_data["fps"].replace(",", ".") + return "%.3f" % float(fps) @@ -193,7 +199,7 @@ def prepare_and_store_movie( preview_file = set_preview_file_as_broken(preview_file_id) return preview_file - fps = get_preview_file_fps(project) + fps = get_preview_file_fps(project, entity) (width, height) = get_preview_file_dimensions(project, entity) if normalize: @@ -619,7 +625,9 @@ def extract_frame_from_preview_file(preview_file, frame_number): else: raise PreviewFileNotFoundException - fps = get_preview_file_fps(project) + fps = get_preview_file_fps( + project, get_entity_from_preview_file(preview_file["id"]) + ) extracted_frame_path = movie.extract_frame_from_movie( preview_file_path, frame_number, fps ) From b16bf8612d66c3b7c4b6afd7769a0c0c9483c3e0 Mon Sep 17 00:00:00 2001 From: Evan Blaudy Date: Fri, 29 Nov 2024 03:40:28 +0100 Subject: [PATCH 7/7] [qa] fix tests --- tests/projects/test_route_open_projects.py | 4 ++-- tests/services/test_assets_service.py | 10 ++++++++-- tests/services/test_projects_service.py | 16 +++++++-------- tests/services/test_tasks_service.py | 2 +- tests/services/test_user_service.py | 2 +- .../shotgun/test_shotgun_import_assets.py | 5 ++++- .../shotgun/test_shotgun_import_shot.py | 5 ++++- .../shotgun/test_shotgun_import_tasks.py | 5 ++++- .../shotgun/test_shotgun_import_teams.py | 20 +++++++++++-------- tests/tasks/test_route_tasks.py | 16 +++++++-------- 10 files changed, 52 insertions(+), 33 deletions(-) diff --git a/tests/projects/test_route_open_projects.py b/tests/projects/test_route_open_projects.py index 5f64e18725..03ef648513 100644 --- a/tests/projects/test_route_open_projects.py +++ b/tests/projects/test_route_open_projects.py @@ -24,7 +24,7 @@ def test_add_team_member(self): "data/projects/%s/team" % self.project_id, {"person_id": self.person_id}, ) - project = projects_service.get_project_with_relations(self.project_id) + project = projects_service.get_project(self.project_id, relations=True) self.assertEqual(project["team"], [str(self.person_id)]) def test_remove_team_member(self): @@ -33,5 +33,5 @@ def test_remove_team_member(self): self.delete( "data/projects/%s/team/%s" % (self.project_id, self.person_id) ) - project = projects_service.get_project_with_relations(self.project_id) + project = projects_service.get_project(self.project_id, relations=True) self.assertEqual(project["team"], []) diff --git a/tests/services/test_assets_service.py b/tests/services/test_assets_service.py index 72cd9352f4..236dde5c5f 100644 --- a/tests/services/test_assets_service.py +++ b/tests/services/test_assets_service.py @@ -186,7 +186,10 @@ def test_add_asset_link(self): self.generate_fixture_asset_types() self.generate_fixture_asset_character() assets_service.add_asset_link(self.asset.id, self.asset_character.id) - asset = assets_service.get_asset_with_relations(self.asset.id) + asset = assets_service.get_asset( + self.asset.id, + relations=True, + ) self.assertEqual( asset["entities_out"][0], str(self.asset_character.id) ) @@ -198,5 +201,8 @@ def test_remove_asset_link(self): assets_service.remove_asset_link( self.asset.id, self.asset_character.id ) - asset = assets_service.get_asset_with_relations(self.asset.id) + asset = assets_service.get_asset( + self.asset.id, + relations=True, + ) self.assertEqual(len(asset["entities_out"]), 0) diff --git a/tests/services/test_projects_service.py b/tests/services/test_projects_service.py index e578b73b41..c33b833fa5 100644 --- a/tests/services/test_projects_service.py +++ b/tests/services/test_projects_service.py @@ -92,14 +92,14 @@ def test_update_project(self): def test_add_team_member(self): self.generate_fixture_person() projects_service.add_team_member(self.project.id, self.person.id) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["team"], [str(self.person.id)]) def test_remove_team_member(self): self.generate_fixture_person() projects_service.add_team_member(self.project.id, self.person.id) projects_service.remove_team_member(self.project.id, self.person.id) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["team"], []) def test_add_asset_type_setting(self): @@ -107,7 +107,7 @@ def test_add_asset_type_setting(self): projects_service.add_asset_type_setting( self.project.id, self.asset_type.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["asset_types"], [str(self.asset_type.id)]) def test_remove_asset_type(self): @@ -118,7 +118,7 @@ def test_remove_asset_type(self): projects_service.remove_asset_type_setting( self.project.id, self.asset_type.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["asset_types"], []) def test_add_task_type_setting(self): @@ -127,7 +127,7 @@ def test_add_task_type_setting(self): projects_service.add_task_type_setting( self.project.id, self.task_type.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["task_types"], [str(self.task_type.id)]) def test_remove_task_type(self): @@ -139,7 +139,7 @@ def test_remove_task_type(self): projects_service.remove_task_type_setting( self.project.id, self.task_type.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["task_types"], []) def test_add_task_status_setting(self): @@ -147,7 +147,7 @@ def test_add_task_status_setting(self): projects_service.add_task_status_setting( self.project.id, self.task_status.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["task_statuses"], [str(self.task_status.id)]) def test_remove_task_status(self): @@ -158,7 +158,7 @@ def test_remove_task_status(self): projects_service.remove_task_status_setting( self.project.id, self.task_status.id ) - project = projects_service.get_project_with_relations(self.project.id) + project = projects_service.get_project(self.project.id, relations=True) self.assertEqual(project["task_statuses"], []) def test_add_asset_metadata_descriptor(self): diff --git a/tests/services/test_tasks_service.py b/tests/services/test_tasks_service.py index c92830c0c1..d74777caeb 100644 --- a/tests/services/test_tasks_service.py +++ b/tests/services/test_tasks_service.py @@ -324,7 +324,7 @@ def test_clear_assignation(self): task_id = self.task.id tasks_service.assign_task(self.task.id, self.person.id) tasks_service.clear_assignation(task_id) - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) def test_get_tasks_for_person(self): diff --git a/tests/services/test_user_service.py b/tests/services/test_user_service.py index 9aaed73de4..0af91aec57 100644 --- a/tests/services/test_user_service.py +++ b/tests/services/test_user_service.py @@ -73,7 +73,7 @@ def test_check_project_access(self): projects_service.add_team_member( str(self.project.id), str(self.get_current_user_raw().id) ) - projects_service.get_project_with_relations(self.project_id) + projects_service.get_project(self.project_id, relations=True) self.assertTrue( user_service.check_project_access(str(self.project_id)) ) diff --git a/tests/source/shotgun/test_shotgun_import_assets.py b/tests/source/shotgun/test_shotgun_import_assets.py index 78e48bf0c0..231d4c0386 100644 --- a/tests/source/shotgun/test_shotgun_import_assets.py +++ b/tests/source/shotgun/test_shotgun_import_assets.py @@ -57,7 +57,10 @@ def test_import_asset(self): assets = sorted(self.assets, key=lambda x: x["name"]) asset = assets[0] - asset = assets_service.get_asset_with_relations(asset["id"]) + asset = assets_service.get_asset( + asset["id"], + relations=True, + ) project = Project.get_by(shotgun_id=sg_asset["project"]["id"]) self.assertEqual(asset["description"], sg_asset["description"]) self.assertEqual(asset["shotgun_id"], sg_asset["id"]) diff --git a/tests/source/shotgun/test_shotgun_import_shot.py b/tests/source/shotgun/test_shotgun_import_shot.py index a0e2596dd4..be9fe37fbe 100644 --- a/tests/source/shotgun/test_shotgun_import_shot.py +++ b/tests/source/shotgun/test_shotgun_import_shot.py @@ -37,7 +37,10 @@ def test_import_shot(self): self.assertEqual(len(self.shots), 1) shot = self.shots[0] - shot = shots_service.get_shot_with_relations(shot["id"]) + shot = shots_service.get_shot( + shot["id"], + relations=True, + ) sequence = Entity.get_by( shotgun_id=self.sg_shot["sg_sequence"]["id"], entity_type_id=shots_service.get_sequence_type()["id"], diff --git a/tests/source/shotgun/test_shotgun_import_tasks.py b/tests/source/shotgun/test_shotgun_import_tasks.py index d997ca5ea2..6fe4e62e1b 100644 --- a/tests/source/shotgun/test_shotgun_import_tasks.py +++ b/tests/source/shotgun/test_shotgun_import_tasks.py @@ -108,7 +108,10 @@ def test_import_task(self): self.assertEqual(len(self.tasks), 1) task = self.tasks[0] - task = tasks_service.get_task_with_relations(task["id"]) + task = tasks_service.get_task( + task["id"], + relations=True, + ) project = Project.get_by(name=self.sg_task["project"]["name"]) task_type = TaskType.get_by(name=self.sg_task["step"]["name"]) task_status = TaskStatus.get_by( diff --git a/tests/source/shotgun/test_shotgun_import_teams.py b/tests/source/shotgun/test_shotgun_import_teams.py index 03a2aeb836..a09e2c9386 100644 --- a/tests/source/shotgun/test_shotgun_import_teams.py +++ b/tests/source/shotgun/test_shotgun_import_teams.py @@ -11,12 +11,14 @@ def test_import_project_connections(self): self.load_fixture("projects") self.load_fixture("projectconnections") projects = self.get("data/projects") - project = projects_service.get_project_with_relations( - projects[0]["id"] + project = projects_service.get_project( + projects[0]["id"], + relations=True, ) self.assertEqual(len(project["team"]), 1) - project = projects_service.get_project_with_relations( - projects[1]["id"] + project = projects_service.get_project( + projects[1]["id"], + relations=True, ) self.assertEqual(len(project["team"]), 2) @@ -26,8 +28,9 @@ def test_import_projects_twice(self): self.load_fixture("projectconnections") self.load_fixture("projectconnections") projects = self.get("data/projects") - project = projects_service.get_project_with_relations( - projects[0]["id"] + project = projects_service.get_project( + projects[0]["id"], + relations=True, ) self.assertEqual(len(project["team"]), 2) @@ -46,7 +49,8 @@ def test_import_project_connection(self): self.assertEqual(len(self.projects), 1) projects = self.get("data/projects") - project = projects_service.get_project_with_relations( - projects[1]["id"] + project = projects_service.get_project( + projects[1]["id"], + relations=True, ) self.assertEqual(len(project["team"]), 1) diff --git a/tests/tasks/test_route_tasks.py b/tests/tasks/test_route_tasks.py index 792edff36d..f6c3c3fcdc 100644 --- a/tests/tasks/test_route_tasks.py +++ b/tests/tasks/test_route_tasks.py @@ -124,9 +124,9 @@ def test_multiple_task_assign(self): data = {"task_ids": [task_id, shot_task_id]} self.put("/actions/persons/%s/assign" % person_id, data) - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) self.assertEqual(len(task["assignees"]), 1) - task = tasks_service.get_task_with_relations(shot_task_id) + task = tasks_service.get_task(shot_task_id, relations=True) self.assertEqual(len(task["assignees"]), 1) notifications = notifications_service.get_last_notifications() self.assertEqual(len(notifications), 2) @@ -143,15 +143,15 @@ def test_multiple_task_assign_artist(self): self.put("/actions/tasks/clear-assignation", data) self.log_in_cg_artist() self.put("/actions/persons/%s/assign" % person_id, data) - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) - task = tasks_service.get_task_with_relations(shot_task_id) + task = tasks_service.get_task(shot_task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) persons_service.add_to_department(department_id, person_id) self.put("/actions/persons/%s/assign" % person_id, data) - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) - task = tasks_service.get_task_with_relations(shot_task_id) + task = tasks_service.get_task(shot_task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) def test_clear_assignation(self): @@ -164,9 +164,9 @@ def test_clear_assignation(self): data = {"task_ids": [task_id, shot_task_id]} self.put("/actions/tasks/clear-assignation", data) - task = tasks_service.get_task_with_relations(task_id) + task = tasks_service.get_task(task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) - task = tasks_service.get_task_with_relations(shot_task_id) + task = tasks_service.get_task(shot_task_id, relations=True) self.assertEqual(len(task["assignees"]), 0) def test_comment_task(self):