From 4ad85091563f7eb830a48437ec7c9354131cbfcc Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Sun, 9 Aug 2026 22:39:49 -0400 Subject: [PATCH] Copy source metadata when creating a single-camera soft clone --- server/dive_server/crud_dataset.py | 2 +- server/tests/test_multicam_export_clone.py | 40 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/server/dive_server/crud_dataset.py b/server/dive_server/crud_dataset.py index 0f1ef8915..fdad615f6 100644 --- a/server/dive_server/crud_dataset.py +++ b/server/dive_server/crud_dataset.py @@ -180,7 +180,7 @@ def _create_single_camera_soft_clone( reuseExisting=False, creator=owner, ) - cloned_folder['meta'] = source_folder['meta'] + cloned_folder['meta'] = copy.deepcopy(source_folder['meta']) media_source_folder = crud.getCloneRoot(owner, source_folder) cloned_folder[constants.ForeignMediaIdMarker] = str(media_source_folder['_id']) cloned_folder['meta'][constants.PublishedMarker] = False diff --git a/server/tests/test_multicam_export_clone.py b/server/tests/test_multicam_export_clone.py index 4adec598d..70a0dd6bb 100644 --- a/server/tests/test_multicam_export_clone.py +++ b/server/tests/test_multicam_export_clone.py @@ -58,6 +58,46 @@ def _descriptor(name: str): return {'itemId': f'{name}-id', 'name': name} +@patch('dive_server.crud_dataset.crud_annotation.clone_annotations') +@patch('dive_server.crud_dataset.crud.get_or_create_auxiliary_folder') +@patch('dive_server.crud_dataset.crud.getCloneRoot') +@patch('dive_server.crud_dataset.Folder') +def test_create_single_camera_soft_clone_copies_metadata( + folder_cls, get_clone_root_mock, _aux, _clone_ann +): + owner = {'login': 'tester'} + source = { + '_id': 'source-id', + 'name': 'source-dataset', + 'meta': { + 'annotate': True, + 'type': 'image-sequence', + 'custom': {'labels': ['fish'], 'settings': {'enabled': True}}, + }, + } + parent = {'_id': 'dest-parent'} + cloned_folder = {'_id': 'clone-id', 'name': 'Clone dataset'} + folder_cls.return_value.createFolder.return_value = cloned_folder + get_clone_root_mock.return_value = source + + result = crud_dataset.createSoftClone(owner, source, parent, 'Clone dataset', None) + + assert result is cloned_folder + source['meta']['custom']['labels'].append('shark') + source['meta']['custom']['settings']['enabled'] = False + assert cloned_folder['meta']['custom'] == { + 'labels': ['fish'], + 'settings': {'enabled': True}, + } + + cloned_folder['meta']['custom']['labels'].append('ray') + cloned_folder['meta']['custom']['settings']['enabled'] = None + assert source['meta']['custom'] == { + 'labels': ['fish', 'shark'], + 'settings': {'enabled': False}, + } + + @patch('dive_server.crud_dataset.find_json_calibration_item_id', return_value=None) @patch('dive_server.crud_dataset.find_calibration_item_id', return_value=None) @patch('dive_server.crud_dataset.crud_annotation.clone_annotations')