From bb2b85f9d1d86ddfff2722cee8201d275e918b49 Mon Sep 17 00:00:00 2001 From: sujata-m Date: Wed, 24 Sep 2025 11:27:51 +0530 Subject: [PATCH 1/2] Added override feature Updated the Azure file upload flow to pass overwrite=True so existing blobs are replaced when uploading and the remote URL remains captured. Adjusted the Azure file entity unit test to assert that the overwrite flag is supplied to upload_blob. --- CHANGELOG.md | 4 ++++ .../core/storage/providers/azure/azure_file_entity.py | 2 +- src/python_ms_core/version.py | 2 +- tests/unit_tests/test_storage/test_azure_file_entity.py | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f9d565..254acaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log +# Version 0.0.24 +- Updated unit test cases pipeline +- Added support to override uploaded blob access tier + # Version 0.0.23 - Updated unit test cases pipeline - Added support to upload test cases results on Azure blob diff --git a/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py b/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py index c92a518..095f474 100644 --- a/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py +++ b/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py @@ -21,7 +21,7 @@ def get_body_text(self): @ExceptionHandler.decorated def upload(self, upload_stream): - upload_file = self.blob_client.upload_blob(self.file_path, upload_stream) + upload_file = self.blob_client.upload_blob(self.file_path, upload_stream, overwrite=True) self._get_remote_url = upload_file.url @ExceptionHandler.decorated diff --git a/src/python_ms_core/version.py b/src/python_ms_core/version.py index 29906fb..071e34f 100644 --- a/src/python_ms_core/version.py +++ b/src/python_ms_core/version.py @@ -1 +1 @@ -__version__ = '0.0.23' \ No newline at end of file +__version__ = '0.0.24' \ No newline at end of file diff --git a/tests/unit_tests/test_storage/test_azure_file_entity.py b/tests/unit_tests/test_storage/test_azure_file_entity.py index 26b85b7..7c6e48f 100644 --- a/tests/unit_tests/test_storage/test_azure_file_entity.py +++ b/tests/unit_tests/test_storage/test_azure_file_entity.py @@ -56,7 +56,9 @@ def test_upload(self): # Assert the result self.assertEqual(file_entity._get_remote_url, 'http://example.com/file') - self.blob_client.upload_blob.assert_called_once_with(file_entity.file_path, upload_stream) + self.blob_client.upload_blob.assert_called_once_with( + file_entity.file_path, upload_stream, overwrite=True + ) def test_get_remote_url(self): # Create an instance of the AzureFileEntity From dca162abe94de7cc4c7f880bf3ca06f626f0e1e8 Mon Sep 17 00:00:00 2001 From: sujata-m Date: Wed, 24 Sep 2025 13:33:00 +0530 Subject: [PATCH 2/2] =?UTF-8?q?-=20Updated=20the=20abstract=20FileEntity.u?= =?UTF-8?q?pload=20signature=20to=20accept=20an=20optional=20overwrite=20f?= =?UTF-8?q?lag=20so=20every=20storage=20provider=20exposes=20the=20same=20?= =?UTF-8?q?interface.=20-=20Adjusted=20the=20local=20file=20entity?= =?UTF-8?q?=E2=80=99s=20upload=20method=20to=20accept=20the=20new=20flag?= =?UTF-8?q?=20while=20keeping=20its=20upload=20behavior=20unchanged.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/storage/abstract/file_entity.py | 2 +- .../providers/azure/azure_file_entity.py | 6 ++-- .../providers/local/local_file_entity.py | 2 +- .../test_storage/test_azure_file_entity.py | 30 +++++++++++++++++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/python_ms_core/core/storage/abstract/file_entity.py b/src/python_ms_core/core/storage/abstract/file_entity.py index 1d4efb5..5d2f1a4 100644 --- a/src/python_ms_core/core/storage/abstract/file_entity.py +++ b/src/python_ms_core/core/storage/abstract/file_entity.py @@ -20,7 +20,7 @@ def get_body_text(self): pass @abstractmethod - def upload(self, upload_stream): + def upload(self, upload_stream, overwrite=False): pass @abstractmethod diff --git a/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py b/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py index 095f474..dfd6fc6 100644 --- a/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py +++ b/src/python_ms_core/core/storage/providers/azure/azure_file_entity.py @@ -20,8 +20,10 @@ def get_body_text(self): return self.blob_client.download_blob().content_as_text() @ExceptionHandler.decorated - def upload(self, upload_stream): - upload_file = self.blob_client.upload_blob(self.file_path, upload_stream, overwrite=True) + def upload(self, upload_stream, overwrite=False): + upload_file = self.blob_client.upload_blob( + self.file_path, upload_stream, overwrite=overwrite + ) self._get_remote_url = upload_file.url @ExceptionHandler.decorated diff --git a/src/python_ms_core/core/storage/providers/local/local_file_entity.py b/src/python_ms_core/core/storage/providers/local/local_file_entity.py index 6dfd098..d03256b 100644 --- a/src/python_ms_core/core/storage/providers/local/local_file_entity.py +++ b/src/python_ms_core/core/storage/providers/local/local_file_entity.py @@ -25,7 +25,7 @@ def get_body_text(self): return StringIO(self.get_stream()).read() @ExceptionHandler.decorated - def upload(self, upload_stream): + def upload(self, upload_stream, overwrite=False): upload_path = f'{self.path}/{self.name}' upload_relative_path = f'{self.config.connection_string}{self.upload_path}{upload_path}' requests.post(upload_relative_path, files={'uploadFile': upload_stream}) diff --git a/tests/unit_tests/test_storage/test_azure_file_entity.py b/tests/unit_tests/test_storage/test_azure_file_entity.py index 7c6e48f..f4cf07f 100644 --- a/tests/unit_tests/test_storage/test_azure_file_entity.py +++ b/tests/unit_tests/test_storage/test_azure_file_entity.py @@ -1,6 +1,7 @@ import unittest from unittest.mock import MagicMock -from azure.storage.blob import BlobClient +from azure.core.exceptions import ResourceExistsError +from src.python_ms_core.core.resource_errors.errors import UnProcessableError from src.python_ms_core.core.storage.providers.azure.azure_file_entity import AzureFileEntity @@ -41,7 +42,7 @@ def test_get_body_text(self): self.assertEqual(result, 'Test content') self.blob_client.download_blob.assert_called_once() - def test_upload(self): + def test_upload_without_overwrite(self): # Create an instance of the AzureFileEntity file_entity = AzureFileEntity(self.name, self.blob_client) @@ -55,11 +56,36 @@ def test_upload(self): file_entity.upload(upload_stream) # Assert the result + self.assertEqual(file_entity._get_remote_url, 'http://example.com/file') + self.blob_client.upload_blob.assert_called_once_with(file_entity.file_path, upload_stream, overwrite=False) + + def test_upload_with_overwrite_true(self): + file_entity = AzureFileEntity(self.name, self.blob_client) + + mock_upload_blob = MagicMock() + mock_upload_blob.url = 'http://example.com/file' + self.blob_client.upload_blob.return_value = mock_upload_blob + + upload_stream = b'Test content' + file_entity.upload(upload_stream, overwrite=True) + self.assertEqual(file_entity._get_remote_url, 'http://example.com/file') self.blob_client.upload_blob.assert_called_once_with( file_entity.file_path, upload_stream, overwrite=True ) + def test_upload_without_overwrite_raises_error_when_blob_exists(self): + file_entity = AzureFileEntity(self.name, self.blob_client) + self.blob_client.upload_blob.side_effect = ResourceExistsError("already exists") + + with self.assertRaises(UnProcessableError): + file_entity.upload(b'Test content') + + self.blob_client.upload_blob.assert_called_once_with( + file_entity.file_path, b'Test content', overwrite=False + ) + self.assertIsNone(file_entity._get_remote_url) + def test_get_remote_url(self): # Create an instance of the AzureFileEntity file_entity = AzureFileEntity(self.name, self.blob_client)