diff --git a/arkindex/process/serializers/imports.py b/arkindex/process/serializers/imports.py index f4944c9282c11e1c53659eca9210a39c338de8ff..0a3506f72fa2306a8d722d8b24c2b99077c1c814 100644 --- a/arkindex/process/serializers/imports.py +++ b/arkindex/process/serializers/imports.py @@ -149,12 +149,20 @@ class ProcessDetailsSerializer(ProcessSerializer): fields = ProcessSerializer.Meta.fields + ( 'farm', 'tasks', + 'created', + 'updated', + 'started', + 'finished', ) read_only_fields = ( # Make the state writable again to allow stopping processes tuple(set(ProcessSerializer.Meta.read_only_fields) - {'state'}) + ( 'farm', 'tasks', + 'created', + 'updated', + 'started', + 'finished', ) ) diff --git a/arkindex/process/tests/test_processes.py b/arkindex/process/tests/test_processes.py index f91f608b814a8158318b6efcf0256bb5760000a6..e88d40fce636168af54bf5a8adbfb74f787c462a 100644 --- a/arkindex/process/tests/test_processes.py +++ b/arkindex/process/tests/test_processes.py @@ -763,6 +763,10 @@ class TestProcesses(FixtureAPITestCase): 'use_cache': False, 'use_gpu': False, 'validation_folder_id': None, + 'created': self.user_img_process.created.isoformat().replace('+00:00', 'Z'), + 'updated': self.user_img_process.updated.isoformat().replace('+00:00', 'Z'), + 'started': self.user_img_process.started.isoformat().replace('+00:00', 'Z'), + 'finished': None, }) def test_details_training_process(self): @@ -795,6 +799,10 @@ class TestProcesses(FixtureAPITestCase): 'use_cache': False, 'use_gpu': False, 'validation_folder_id': str(self.val.id), + 'created': self.training_process.created.isoformat().replace('+00:00', 'Z'), + 'updated': self.training_process.updated.isoformat().replace('+00:00', 'Z'), + 'started': None, + 'finished': None, }) def test_delete_requires_login(self): @@ -1346,6 +1354,74 @@ class TestProcesses(FixtureAPITestCase): 'ml_class_id': [message], }) + def test_update_fields(self): + """ + Ensure determined fields can be updated on a non started workers process. + Editable fields are `name`, `name_contains`, `element_type`, and `load_children`. + """ + self.client.force_login(self.user) + process = Process.objects.create(mode=ProcessMode.Workers, corpus=self.corpus, creator=self.user) + + with self.assertNumQueries(12): + response = self.client.put( + reverse('api:process-details', kwargs={'pk': process.id}), + { + 'id': str(uuid.uuid4()), + 'revision': str(uuid.uuid4()), + 'element': str(uuid.uuid4()), + 'workflow': str(uuid.uuid4()), + 'creator': str(uuid.uuid4()), + 'files': [1, 2, 3], + 'mode': 'iiif', + 'folder_type': 'register', + 'name': 'newName', + 'element_name_contains': 'AAA', + 'element_type': 'page', + 'load_children': True, + 'use_cache': True, + 'use_gpu': False, + 'activity_state': ActivityState.Pending.value, + 'template_id': None, + 'created': '2038-01-19T03:14:08Z', + 'updated': '2038-01-19T03:14:08Z', + 'started': '2038-01-19T03:14:08Z', + 'finished': '2038-01-19T03:14:08Z', + }, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_200_OK, response.json()) + + process.refresh_from_db() + self.assertEqual(response.json(), { + 'name': 'newName', + 'element_name_contains': 'AAA', + 'element_type': 'page', + 'folder_type': None, + 'ml_class_id': None, + 'load_children': True, + 'use_cache': False, + 'use_gpu': False, + 'activity_state': ActivityState.Disabled.value, + 'id': str(process.id), + 'corpus': str(self.corpus.id), + 'element': None, + 'files': [], + 'mode': 'workers', + 'revision': None, + 'state': 'unscheduled', + 'template_id': None, + 'model_id': None, + 'train_folder_id': None, + 'validation_folder_id': None, + 'test_folder_id': None, + 'farm': None, + 'tasks': [], + 'created': process.created.isoformat().replace('+00:00', 'Z'), + 'updated': process.updated.isoformat().replace('+00:00', 'Z'), + 'started': None, + 'finished': None, + }) + def test_partial_update_wrong_mode(self): """ Fields other than 'name' cannot be updated in processes that are not of Workers mode @@ -1527,28 +1603,36 @@ class TestProcesses(FixtureAPITestCase): """ self.client.force_login(self.user) process = Process.objects.create(mode=ProcessMode.Workers, corpus=self.corpus, creator=self.user) - response = self.client.patch( - reverse('api:process-details', kwargs={'pk': process.id}), - { - 'id': str(uuid.uuid4()), - 'revision': str(uuid.uuid4()), - 'element': str(uuid.uuid4()), - 'workflow': str(uuid.uuid4()), - 'creator': str(uuid.uuid4()), - 'files': [1, 2, 3], - 'mode': 'iiif', - 'folder_type': 'register', - 'name': 'newName', - 'element_name_contains': 'AAA', - 'element_type': 'page', - 'load_children': True, - 'use_cache': True, - 'use_gpu': False, - 'activity_state': ActivityState.Pending.value, - }, - format='json' - ) - self.assertEqual(response.status_code, status.HTTP_200_OK, response.json()) + + with self.assertNumQueries(12): + response = self.client.patch( + reverse('api:process-details', kwargs={'pk': process.id}), + { + 'id': str(uuid.uuid4()), + 'revision': str(uuid.uuid4()), + 'element': str(uuid.uuid4()), + 'workflow': str(uuid.uuid4()), + 'creator': str(uuid.uuid4()), + 'files': [1, 2, 3], + 'mode': 'iiif', + 'folder_type': 'register', + 'name': 'newName', + 'element_name_contains': 'AAA', + 'element_type': 'page', + 'load_children': True, + 'use_cache': True, + 'use_gpu': False, + 'activity_state': ActivityState.Pending.value, + 'created': '2038-01-19T03:14:08Z', + 'updated': '2038-01-19T03:14:08Z', + 'started': '2038-01-19T03:14:08Z', + 'finished': '2038-01-19T03:14:08Z', + }, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + process.refresh_from_db() self.assertEqual(response.json(), { 'name': 'newName', 'element_name_contains': 'AAA', @@ -1572,6 +1656,10 @@ class TestProcesses(FixtureAPITestCase): 'test_folder_id': None, 'farm': None, 'tasks': [], + 'created': process.created.isoformat().replace('+00:00', 'Z'), + 'updated': process.updated.isoformat().replace('+00:00', 'Z'), + 'started': None, + 'finished': None, }) def test_retry_requires_login(self):