diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ff8953402d2..aab4a5be9e00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## \[Unreleased\] ### Added -- Helm: Added configurable default storage option to chart() - Multi-line text attributes supported () - Now you can configure default attribute value for SELECT, RADIO types on UI () @@ -15,13 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 () ### Changed -- Helm: Added configurable default storage option to chart() +- \[Helm\] Added configurable default storage option to chart () ### Deprecated - TDB ### Removed -- Helm: Removed hardcoded mandatory traefik ingress usage() +- \[Helm\] Removed hardcoded mandatory traefik ingress usage() ### Fixed - Calculating number of objects on annotation view when frames are deleted @@ -34,10 +33,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed SAM plugin (403 code for workers in organizations) () - Using initial frame from query parameter to open specific frame in a job () -- Helm: fixed issue with multiple caches in same RWX volume, which prevents db migration to start() +- Problem with first keyframe removing () - Server-side validation for attribute specifications () - \[API\] File downloading failures for filenames with special characters l() +- \[Helm\] fixed issue with multiple caches in same RWX volume, which prevents db migration to start () ### Security - TDB diff --git a/cvat/apps/dataset_manager/task.py b/cvat/apps/dataset_manager/task.py index 66fd499a6002..1269883e30fa 100644 --- a/cvat/apps/dataset_manager/task.py +++ b/cvat/apps/dataset_manager/task.py @@ -160,6 +160,7 @@ def _add_missing_shape(self, track, first_shape): missing_shape = deepcopy(first_shape) missing_shape["frame"] = track["frame"] missing_shape["outside"] = True + missing_shape.pop("id") track["shapes"].append(missing_shape) def _correct_frame_of_tracked_shapes(self, track): diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index 4d498d495a0a..3740d2a47568 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -194,13 +194,13 @@ def annotation_formats(request): }) @action(detail=False, methods=['GET'], url_path='plugins', serializer_class=PluginsSerializer) def plugins(request): - response = { + data = { 'GIT_INTEGRATION': apps.is_installed('cvat.apps.dataset_repo'), 'ANALYTICS': strtobool(os.environ.get("CVAT_ANALYTICS", '0')), 'MODELS': strtobool(os.environ.get("CVAT_SERVERLESS", '0')), 'PREDICT': False, # FIXME: it is unused anymore (for UI only) } - return Response(response) + return Response(PluginsSerializer(data).data) @extend_schema(tags=['projects']) @extend_schema_view( diff --git a/cvat/apps/iam/permissions.py b/cvat/apps/iam/permissions.py index 2a1893e8b1b9..f568415fbec9 100644 --- a/cvat/apps/iam/permissions.py +++ b/cvat/apps/iam/permissions.py @@ -62,7 +62,7 @@ def get_organization(request, obj): except AttributeError as exc: # Skip initialization of organization for those objects that don't related with organization view = request.parser_context.get('view') - if view and view.basename in ('user', 'function', 'request',): + if view and view.basename in ('user', 'function', 'request', 'server'): return request.iam_context['organization'] raise exc diff --git a/tests/python/rest_api/test_tasks.py b/tests/python/rest_api/test_tasks.py index 0184f66e56c9..98c443b290bd 100644 --- a/tests/python/rest_api/test_tasks.py +++ b/tests/python/rest_api/test_tasks.py @@ -517,6 +517,22 @@ def test_member_update_task_annotation( self._test_check_response(is_allow, response, data) + def test_remove_first_keyframe(self): + endpoint = "tasks/8/annotations" + shapes0 = [ + {"type": "rectangle", "frame": 1, "points": [1, 2, 3, 4]}, + {"type": "rectangle", "frame": 4, "points": [5, 6, 7, 8]}, + ] + + annotations = {"tracks": [{"label_id": 13, "frame": 0, "shapes": shapes0}]} + + response = patch_method("admin1", endpoint, annotations, action="create") + assert response.status_code == HTTPStatus.OK, response.content + + annotations["tracks"][0]["shapes"] = shapes0[1:] + response = patch_method("admin1", endpoint, annotations, action="update") + assert response.status_code == HTTPStatus.OK + @pytest.mark.usefixtures("restore_db_per_class") class TestGetTaskDataset: