SIENTIAPDE-1717: Remove MinIO cleanup functionality and associated components. This change streamlines the cleanup workflow to focus solely on local temporary directories, removes the ModelTrainingError exception, and updates related configurations, documentation, and tests.
This commit is contained in:
@@ -8,15 +8,12 @@ def test_experiment_status_values():
|
||||
assert ExperimentStatus.ORCHESTRATOR_WAITING_PROC == 'ORCHESTRATOR_WAITING_PROC'
|
||||
assert ExperimentStatus.TRAINING_SUCCESS == 'TRAINING_SUCCESS'
|
||||
assert ExperimentStatus.TRAINING_ERROR == 'TRAINING_ERROR'
|
||||
assert ExperimentStatus.TRACKING_SENT == 'TRACKING_SENT'
|
||||
assert ExperimentStatus.TRACKING_SEND_ERROR == 'TRACKING_SEND_ERROR'
|
||||
assert ExperimentStatus.FILE_DELETED == 'FILE_DELETED'
|
||||
assert ExperimentStatus.FILE_DELETE_ERROR == 'FILE_DELETE_ERROR'
|
||||
|
||||
|
||||
def test_experiment_status_count():
|
||||
"""Test that enum has exactly 8 status values."""
|
||||
assert len(ExperimentStatus) == 8
|
||||
assert len(ExperimentStatus) == 5
|
||||
|
||||
|
||||
def test_experiment_status_is_string():
|
||||
@@ -31,22 +28,16 @@ def test_experiment_status_membership():
|
||||
assert 'ORCHESTRATOR_WAITING_PROC' in [s.value for s in ExperimentStatus]
|
||||
assert 'TRAINING_SUCCESS' in [s.value for s in ExperimentStatus]
|
||||
assert 'TRAINING_ERROR' in [s.value for s in ExperimentStatus]
|
||||
assert 'TRACKING_SENT' in [s.value for s in ExperimentStatus]
|
||||
assert 'TRACKING_SEND_ERROR' in [s.value for s in ExperimentStatus]
|
||||
assert 'FILE_DELETED' in [s.value for s in ExperimentStatus]
|
||||
assert 'FILE_DELETE_ERROR' in [s.value for s in ExperimentStatus]
|
||||
|
||||
|
||||
def test_experiment_status_iteration():
|
||||
"""Test that enum can be iterated."""
|
||||
statuses = list(ExperimentStatus)
|
||||
assert len(statuses) == 8
|
||||
assert len(statuses) == 5
|
||||
assert ExperimentStatus.ORCHESTRATOR_WAITING_PROC in statuses
|
||||
assert ExperimentStatus.TRAINING_SUCCESS in statuses
|
||||
assert ExperimentStatus.TRAINING_ERROR in statuses
|
||||
assert ExperimentStatus.TRACKING_SENT in statuses
|
||||
assert ExperimentStatus.TRACKING_SEND_ERROR in statuses
|
||||
assert ExperimentStatus.FILE_DELETED in statuses
|
||||
assert ExperimentStatus.FILE_DELETE_ERROR in statuses
|
||||
|
||||
|
||||
@@ -64,9 +55,6 @@ def test_experiment_status_access_by_name():
|
||||
)
|
||||
assert ExperimentStatus['TRAINING_SUCCESS'] == ExperimentStatus.TRAINING_SUCCESS
|
||||
assert ExperimentStatus['TRAINING_ERROR'] == ExperimentStatus.TRAINING_ERROR
|
||||
assert ExperimentStatus['TRACKING_SENT'] == ExperimentStatus.TRACKING_SENT
|
||||
assert ExperimentStatus['TRACKING_SEND_ERROR'] == ExperimentStatus.TRACKING_SEND_ERROR
|
||||
assert ExperimentStatus['FILE_DELETED'] == ExperimentStatus.FILE_DELETED
|
||||
assert ExperimentStatus['FILE_DELETE_ERROR'] == ExperimentStatus.FILE_DELETE_ERROR
|
||||
|
||||
|
||||
@@ -77,7 +65,4 @@ def test_experiment_status_access_by_value():
|
||||
)
|
||||
assert ExperimentStatus('TRAINING_SUCCESS') == ExperimentStatus.TRAINING_SUCCESS
|
||||
assert ExperimentStatus('TRAINING_ERROR') == ExperimentStatus.TRAINING_ERROR
|
||||
assert ExperimentStatus('TRACKING_SENT') == ExperimentStatus.TRACKING_SENT
|
||||
assert ExperimentStatus('TRACKING_SEND_ERROR') == ExperimentStatus.TRACKING_SEND_ERROR
|
||||
assert ExperimentStatus('FILE_DELETED') == ExperimentStatus.FILE_DELETED
|
||||
assert ExperimentStatus('FILE_DELETE_ERROR') == ExperimentStatus.FILE_DELETE_ERROR
|
||||
|
||||
@@ -237,83 +237,6 @@ def test_fetch_file_network_error(mock_boto3, mock_logger, storage_config):
|
||||
repo.fetch_file('test-bucket', 'test-file.csv')
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_delete_file_success(mock_boto3, mock_logger, storage_config):
|
||||
"""Test successful file deletion from MinIO."""
|
||||
from model_manager.utils.repository.storage_repository import StorageRepository
|
||||
|
||||
mock_s3_client = Mock()
|
||||
mock_s3_client.delete_object.return_value = {}
|
||||
mock_boto3.client.return_value = mock_s3_client
|
||||
|
||||
repo = StorageRepository(logger=mock_logger, **storage_config)
|
||||
|
||||
# Delete file
|
||||
repo.delete_file('test-bucket', 'test-file.csv')
|
||||
|
||||
# Verify delete_object was called correctly
|
||||
mock_s3_client.delete_object.assert_called_once_with(Bucket='test-bucket', Key='test-file.csv')
|
||||
|
||||
# Verify logging
|
||||
assert mock_logger.info.call_count >= 2 # Init + delete
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_delete_file_non_existent(mock_boto3, mock_logger, storage_config):
|
||||
"""Test delete file that doesn't exist (should succeed silently in S3)."""
|
||||
from model_manager.utils.repository.storage_repository import StorageRepository
|
||||
|
||||
# S3/MinIO delete is idempotent - deleting non-existent file succeeds
|
||||
mock_s3_client = Mock()
|
||||
mock_s3_client.delete_object.return_value = {}
|
||||
mock_boto3.client.return_value = mock_s3_client
|
||||
|
||||
repo = StorageRepository(logger=mock_logger, **storage_config)
|
||||
|
||||
# Delete non-existent file (should succeed)
|
||||
repo.delete_file('test-bucket', 'non-existent.csv')
|
||||
|
||||
mock_s3_client.delete_object.assert_called_once()
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_delete_file_access_denied(mock_boto3, mock_logger, storage_config):
|
||||
"""Test delete file when access is denied."""
|
||||
from model_manager.utils.repository.storage_repository import StorageRepository
|
||||
|
||||
# Setup mock to raise AccessDenied error
|
||||
mock_s3_client = Mock()
|
||||
mock_s3_client.delete_object.side_effect = ClientError(
|
||||
{'Error': {'Code': 'AccessDenied', 'Message': 'Access Denied'}}, 'DeleteObject'
|
||||
)
|
||||
mock_boto3.client.return_value = mock_s3_client
|
||||
|
||||
repo = StorageRepository(logger=mock_logger, **storage_config)
|
||||
|
||||
# Attempt to delete file without permissions
|
||||
with pytest.raises(ClientError) as exc_info:
|
||||
repo.delete_file('test-bucket', 'protected-file.csv')
|
||||
|
||||
assert exc_info.value.response['Error']['Code'] == 'AccessDenied'
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_delete_file_network_error(mock_boto3, mock_logger, storage_config):
|
||||
"""Test delete file when network error occurs."""
|
||||
from model_manager.utils.repository.storage_repository import StorageRepository
|
||||
|
||||
# Setup mock to raise network error
|
||||
mock_s3_client = Mock()
|
||||
mock_s3_client.delete_object.side_effect = ConnectionError('Network unreachable')
|
||||
mock_boto3.client.return_value = mock_s3_client
|
||||
|
||||
repo = StorageRepository(logger=mock_logger, **storage_config)
|
||||
|
||||
# Attempt to delete file with network error
|
||||
with pytest.raises(ConnectionError):
|
||||
repo.delete_file('test-bucket', 'test-file.csv')
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_storage_repository_with_ssl(mock_boto3, mock_logger, storage_config):
|
||||
"""Test StorageRepository initialization with SSL enabled."""
|
||||
@@ -404,24 +327,6 @@ def test_fetch_file_with_special_characters(mock_boto3, mock_logger, storage_con
|
||||
mock_s3_client.get_object.assert_called_once_with(Bucket='test-bucket', Key=special_filename)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_delete_file_with_path_separators(mock_boto3, mock_logger, storage_config):
|
||||
"""Test delete file with path separators in object key."""
|
||||
from model_manager.utils.repository.storage_repository import StorageRepository
|
||||
|
||||
mock_s3_client = Mock()
|
||||
mock_s3_client.delete_object.return_value = {}
|
||||
mock_boto3.client.return_value = mock_s3_client
|
||||
|
||||
repo = StorageRepository(logger=mock_logger, **storage_config)
|
||||
|
||||
# Delete file with path separators
|
||||
file_path = 'data/2023/01/test-file.csv'
|
||||
repo.delete_file('test-bucket', file_path)
|
||||
|
||||
mock_s3_client.delete_object.assert_called_once_with(Bucket='test-bucket', Key=file_path)
|
||||
|
||||
|
||||
@patch('model_manager.utils.repository.storage_repository.boto3')
|
||||
def test_storage_repository_different_regions(mock_boto3, mock_logger, storage_config):
|
||||
"""Test StorageRepository with different AWS regions."""
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
"""Unit tests for custom exceptions with 100% coverage."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_model_training_error_with_default_message():
|
||||
"""Test ModelTrainingError with default message."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
error = ModelTrainingError(model_trained=True, model_saved=False)
|
||||
|
||||
assert error.model_trained is True
|
||||
assert error.model_saved is False
|
||||
assert str(error) == 'Model training workflow failed (model_trained=True, model_saved=False)'
|
||||
|
||||
|
||||
def test_model_training_error_with_custom_message():
|
||||
"""Test ModelTrainingError with custom message."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
custom_msg = 'Custom error occurred during training'
|
||||
error = ModelTrainingError(model_trained=False, model_saved=False, message=custom_msg)
|
||||
|
||||
assert error.model_trained is False
|
||||
assert error.model_saved is False
|
||||
assert str(error) == custom_msg
|
||||
|
||||
|
||||
def test_model_training_error_both_true():
|
||||
"""Test ModelTrainingError when both flags are True."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
error = ModelTrainingError(model_trained=True, model_saved=True)
|
||||
|
||||
assert error.model_trained is True
|
||||
assert error.model_saved is True
|
||||
assert str(error) == 'Model training workflow failed (model_trained=True, model_saved=True)'
|
||||
|
||||
|
||||
def test_model_training_error_both_false():
|
||||
"""Test ModelTrainingError when both flags are False."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
error = ModelTrainingError(model_trained=False, model_saved=False)
|
||||
|
||||
assert error.model_trained is False
|
||||
assert error.model_saved is False
|
||||
assert str(error) == 'Model training workflow failed (model_trained=False, model_saved=False)'
|
||||
|
||||
|
||||
def test_model_training_error_is_exception():
|
||||
"""Test ModelTrainingError is an Exception subclass."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
error = ModelTrainingError(model_trained=True, model_saved=False)
|
||||
|
||||
assert isinstance(error, Exception)
|
||||
|
||||
|
||||
def test_model_training_error_can_be_raised():
|
||||
"""Test ModelTrainingError can be raised and caught."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
with pytest.raises(ModelTrainingError) as exc_info:
|
||||
raise ModelTrainingError(model_trained=True, model_saved=False)
|
||||
|
||||
assert exc_info.value.model_trained is True
|
||||
assert exc_info.value.model_saved is False
|
||||
|
||||
|
||||
def test_model_training_error_with_empty_message():
|
||||
"""Test ModelTrainingError with empty string message."""
|
||||
from model_manager.utils.exceptions import ModelTrainingError
|
||||
|
||||
error = ModelTrainingError(model_trained=True, model_saved=True, message='')
|
||||
|
||||
assert error.model_trained is True
|
||||
assert error.model_saved is True
|
||||
assert str(error) == ''
|
||||
Reference in New Issue
Block a user