diff --git a/requirements.txt b/requirements.txt index 3a405e7..4f0b448 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,5 +3,5 @@ pydantic==1.10.4 python-ms-core==0.0.23 uvicorn==0.20.0 html_testRunner==1.2.1 -osm-osw-reformatter==0.2.12 +osm-osw-reformatter==0.3.1 numpy==1.26.4 \ No newline at end of file diff --git a/src/service/osw_formatter_service.py b/src/service/osw_formatter_service.py index 239c673..2e398cc 100644 --- a/src/service/osw_formatter_service.py +++ b/src/service/osw_formatter_service.py @@ -111,10 +111,10 @@ def format(self, received_message: OSWValidationMessage): formatter_result = ValidationResult() if result and result.status and result.error is None and result.generated_files is not None: # Generated files can be .xml or a bunch of geojson - if isinstance(result.generated_files, list): # If it's a list - converted_file = formatter.create_zip(result.generated_files) - else: - converted_file = result.generated_files + converted_file = self._prepare_upload_file( + formatter=formatter, + generated_files=result.generated_files, + ) upload_path = self.upload_to_azure( file_path=converted_file, project_group_id=received_message.data.tdei_project_group_id, @@ -211,10 +211,10 @@ def process_on_demand_format(self, request: OSWOnDemandRequest): # Create remote path if result and result.status and result.error is None and result.generated_files is not None: logger.info('Formatting complete') - if isinstance(result.generated_files, list): # If its a list - converted_file = formatter.create_zip(result.generated_files) - else: - converted_file = result.generated_files + converted_file = self._prepare_upload_file( + formatter=formatter, + generated_files=result.generated_files, + ) target_directory = f'jobs/{request.data.jobId}/{request.data.target}' target_file_remote_path = f'{target_directory}/{os.path.basename(converted_file)}' @@ -288,6 +288,15 @@ def upload_to_azure_on_demand(self, remote_path: str, local_url: str): file.upload(data) return file.get_remote_url() + def _prepare_upload_file(self, formatter: OSWFormat, generated_files): + if isinstance(generated_files, list): + return formatter.create_zip(generated_files) + if isinstance(generated_files, str): + _, extension = os.path.splitext(generated_files) + if extension.lower() == ".xml": + return formatter.create_zip([generated_files]) + return generated_files + def stop_listening(self): self.listening_thread.join(timeout=0) return diff --git a/tests/unit_tests/service/test_osw_formatter_service.py b/tests/unit_tests/service/test_osw_formatter_service.py index bc06633..844b4e3 100644 --- a/tests/unit_tests/service/test_osw_formatter_service.py +++ b/tests/unit_tests/service/test_osw_formatter_service.py @@ -60,21 +60,18 @@ def test_start_listening(self, mock_start_listening): # Assert mock_start_listening.assert_called_once() + @patch('src.service.osw_formatter_service.OSWFormat') @patch.object(OSWFormat, 'download_single_file') @patch.object(OSWFomatterService, 'send_status') - def test_format_success(self, mock_send_status, mock_download_single_file): + def test_format_success(self, mock_send_status, mock_download_single_file, mock_osw_format): # Set up mock data file_path = f'{SAVED_FILE_PATH}/osw.zip' # Mock OSWFormat instance - with patch.object(OSWFormat, '__init__', return_value=None): - self.OSW_format = OSWFormat(file_path=file_path, storage_client=MagicMock()) - self.OSW_format.file_path = MagicMock() - self.OSW_format.file_path.return_value = Mock(file_path) - self.OSW_format.file_relative_path = MagicMock() - self.OSW_format.file_relative_path.return_value = Mock(file_path.split('/')[-1]) - mock_download_single_file.return_value = f'{DOWNLOAD_PATH}/osw.zip' - self.OSW_format.format = MagicMock() - self.OSW_format.format.return_value = Mock(status=True, error=None, generated_files='file1.xml') + mock_osw_instance = MagicMock() + mock_osw_instance.format.return_value = Mock(status=True, error=None, generated_files='file1.xml') + mock_osw_instance.create_zip.return_value = 'file1.zip' + mock_osw_format.return_value = mock_osw_instance + mock_download_single_file.return_value = f'{DOWNLOAD_PATH}/osw.zip' # Arrange received_message = OSWValidationMessage(data=TEST_DATA) @@ -89,6 +86,7 @@ def test_format_success(self, mock_send_status, mock_download_single_file): # Assert mock_send_status.assert_called_once() + mock_osw_instance.create_zip.assert_called_once_with(['file1.xml']) @patch.object(OSWFomatterService, 'send_status') def test_format_failure(self, mock_send_status): @@ -96,10 +94,10 @@ def test_format_failure(self, mock_send_status): file_path = f'{SAVED_FILE_PATH}/osw.zip' # Mock OSWFormat instance - with patch.object(OSWFormat, '__init__', return_value=None): + with patch.object(OSWFormat, '__init__', return_value=None), \ + patch.object(OSWFormat, 'format', return_value=Mock(status=True, error=None, generated_files='file1.xml')), \ + patch.object(OSWFormat, 'create_zip', return_value='file1.zip'): self.OSW_format = OSWFormat(file_path=file_path, storage_client=MagicMock()) - self.OSW_format.format = MagicMock() - self.OSW_format.format.return_value = Mock(status=True, error=None, generated_files='file1.xml') # Arrange received_message = OSWValidationMessage(data=TEST_DATA) @@ -121,10 +119,10 @@ def test_format_failure_with_invalid_file_path(self, mock_send_status): file_path = f'{SAVED_FILE_PATH}/osw.zip' # Mock OSWFormat instance - with patch.object(OSWFormat, '__init__', return_value=None): + with patch.object(OSWFormat, '__init__', return_value=None), \ + patch.object(OSWFormat, 'format', return_value=Mock(status=True, error=None, generated_files='file1.xml')), \ + patch.object(OSWFormat, 'create_zip', return_value='file1.zip'): self.OSW_format = OSWFormat(file_path=file_path, storage_client=MagicMock()) - self.OSW_format.format = MagicMock() - self.OSW_format.format.return_value = Mock(status=True, error=None, generated_files='file1.xml') # Arrange received_message = OSWValidationMessage(data=TEST_DATA) @@ -207,7 +205,8 @@ def test_invalid_send_status(self): @patch.object(OSWFormat, 'format') def test_process_on_demand_format_success(self, mock_format): file_path = f'{SAVED_FILE_PATH}/osw.zip' - with patch.object(OSWFormat, '__init__', return_value=None): + with patch.object(OSWFormat, '__init__', return_value=None), \ + patch.object(OSWFormat, 'create_zip', return_value='file1.zip') as mock_create_zip: mock_init = OSWFormat(file_path=file_path, storage_client=MagicMock()) mock_init.file_path = file_path mock_init.file_relative_path = file_path.split('/')[-1] @@ -227,6 +226,7 @@ def test_process_on_demand_format_success(self, mock_format): self.formatter.process_on_demand_format(request=request) mock_format.assert_called_once() + mock_create_zip.assert_called_once_with(['file1.xml']) @patch.object(OSWFormat, 'format') def test_process_on_demand_format_failure(self, mock_format): diff --git a/tests/unit_tests/service/test_service.py b/tests/unit_tests/service/test_service.py index 4f11f6f..cc8d016 100644 --- a/tests/unit_tests/service/test_service.py +++ b/tests/unit_tests/service/test_service.py @@ -227,15 +227,18 @@ def test_format_with_generated_file(self, mock_osw_format): mock_format_result = MagicMock() mock_format_result.status = True mock_format_result.error = None - mock_format_result.generated_files = 'file1.geojson' + mock_format_result.generated_files = 'file1.xml' mock_osw_instance.format.return_value = mock_format_result + mock_osw_instance.create_zip.return_value = 'zipped_file.zip' + self.service.upload_to_azure = MagicMock() self.service.upload_to_azure.return_value = 'uploaded_path' # Act self.service.format(received_message) + mock_osw_instance.create_zip.assert_called_once_with(['file1.xml']) self.service.upload_to_azure.assert_called_once() @patch('src.service.osw_formatter_service.OSWFormat') @@ -277,6 +280,45 @@ def test_process_on_demand_format_with_generated_files_list(self, mock_osw_forma mock_osw_instance.create_zip.assert_called_once_with(['file1.geojson', 'file2.geojson']) self.service.upload_to_azure_on_demand.assert_called_once() + @patch('src.service.osw_formatter_service.OSWFormat') + def test_process_on_demand_format_with_generated_xml(self, mock_osw_format): + # Arrange + message_data = { + 'sourceUrl': 'http://example.com/file.osm', + 'jobId': '1234', + 'source': 'source_format', + 'target': 'target_format' + } + received_message = OSWOnDemandRequest( + messageId='1234', + messageType='message_type', + data=message_data + ) + + # Mock OSWFormat instance + mock_osw_instance = MagicMock() + mock_osw_format.return_value = mock_osw_instance + + # Mock format method return values + mock_format_result = MagicMock() + mock_format_result.status = True + mock_format_result.error = None + mock_format_result.generated_files = 'file1.xml' + mock_osw_instance.format.return_value = mock_format_result + + # Mock create_zip return value + mock_osw_instance.create_zip.return_value = 'zipped_file.zip' + + self.service.upload_to_azure_on_demand = MagicMock() + self.service.upload_to_azure_on_demand.return_value = 'uploaded_path' + + # Act + self.service.process_on_demand_format(received_message) + + # Assert + mock_osw_instance.create_zip.assert_called_once_with(['file1.xml']) + self.service.upload_to_azure_on_demand.assert_called_once() + @patch('src.service.osw_formatter_service.OSWFormat') @patch('src.service.osw_formatter_service.logger') def test_process_on_demand_format_exception(self, mock_logger, mock_osw_format):