fix: Code quality improvements for v5.2.2 release

- Fix pagination bug using continuation_token instead of start_after
- Add stats caching to prevent blocking web apps
- Improve code formatting and type checking
- Add comprehensive unit tests for new features
- Fix test mock usage in object_listing tests
This commit is contained in:
Simone Scarduzio
2025-10-14 23:54:49 +02:00
parent ff05e77c24
commit e1259b7ea8
26 changed files with 2581 additions and 369 deletions

View File

@@ -153,13 +153,14 @@ class TestBucketManagement:
delta_objects=6,
direct_objects=4,
)
client._store_bucket_stats_cache("bucket1", detailed_stats=True, stats=cached_stats)
client._store_bucket_stats_cache("bucket1", mode="detailed", stats=cached_stats)
response = client.list_buckets()
bucket1 = next(bucket for bucket in response["Buckets"] if bucket["Name"] == "bucket1")
assert bucket1["DeltaGliderStats"]["Cached"] is True
assert bucket1["DeltaGliderStats"]["Detailed"] is True
assert bucket1["DeltaGliderStats"]["Mode"] == "detailed"
assert bucket1["DeltaGliderStats"]["ObjectCount"] == cached_stats.object_count
assert bucket1["DeltaGliderStats"]["TotalSize"] == cached_stats.total_size
@@ -254,10 +255,14 @@ class TestBucketManagement:
call_count = {"value": 0}
def fake_get_bucket_stats(_: Any, bucket: str, detailed_stats_flag: bool) -> BucketStats:
def fake_get_bucket_stats(_: Any, bucket: str, mode: str) -> BucketStats:
call_count["value"] += 1
assert bucket == "bucket1"
return detailed_stats if detailed_stats_flag else quick_stats
if mode == "detailed":
return detailed_stats
if mode == "sampled":
return detailed_stats # sampled treated as detailed for cache propagation
return quick_stats
monkeypatch.setattr("deltaglider.client._get_bucket_stats", fake_get_bucket_stats)
@@ -271,7 +276,7 @@ class TestBucketManagement:
assert call_count["value"] == 1
# Detailed call triggers new computation
result_detailed = client.get_bucket_stats("bucket1", detailed_stats=True)
result_detailed = client.get_bucket_stats("bucket1", mode="detailed")
assert result_detailed is detailed_stats
assert call_count["value"] == 2

View File

@@ -434,7 +434,7 @@ class TestDeltaGliderFeatures:
def test_get_bucket_stats(self, client):
"""Test getting bucket statistics."""
# Test quick stats (default: detailed_stats=False)
# Test quick stats (LIST only)
stats = client.get_bucket_stats("test-bucket")
assert isinstance(stats, BucketStats)
@@ -442,8 +442,8 @@ class TestDeltaGliderFeatures:
assert stats.total_size > 0
assert stats.delta_objects >= 1 # We have archive.zip.delta
# Test with detailed_stats=True
detailed_stats = client.get_bucket_stats("test-bucket", detailed_stats=True)
# Test with detailed mode
detailed_stats = client.get_bucket_stats("test-bucket", mode="detailed")
assert isinstance(detailed_stats, BucketStats)
assert detailed_stats.object_count == stats.object_count

View File

@@ -49,9 +49,7 @@ class TestStatsCommand:
assert output["direct_objects"] == 3
# Verify client was called correctly
mock_client.get_bucket_stats.assert_called_once_with(
"test-bucket", detailed_stats=False
)
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="quick")
def test_stats_json_output_detailed(self):
"""Test stats command with detailed JSON output."""
@@ -79,7 +77,44 @@ class TestStatsCommand:
assert output["average_compression_ratio"] == 0.95
# Verify detailed flag was passed
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", detailed_stats=True)
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="detailed")
def test_stats_json_output_sampled(self):
"""Test stats command with sampled JSON output."""
mock_stats = BucketStats(
bucket="test-bucket",
object_count=5,
total_size=2000000,
compressed_size=100000,
space_saved=1900000,
average_compression_ratio=0.95,
delta_objects=5,
direct_objects=0,
)
with patch("deltaglider.client.DeltaGliderClient") as mock_client_class:
mock_client = Mock()
mock_client.get_bucket_stats.return_value = mock_stats
mock_client_class.return_value = mock_client
runner = CliRunner()
result = runner.invoke(cli, ["stats", "test-bucket", "--sampled", "--json"])
assert result.exit_code == 0
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="sampled")
def test_stats_sampled_and_detailed_conflict(self):
"""--sampled and --detailed flags must be mutually exclusive."""
with patch("deltaglider.client.DeltaGliderClient") as mock_client_class:
mock_client = Mock()
mock_client_class.return_value = mock_client
runner = CliRunner()
result = runner.invoke(cli, ["stats", "test-bucket", "--sampled", "--detailed"])
assert result.exit_code == 1
assert "cannot be used together" in result.output
def test_stats_human_readable_output(self):
"""Test stats command with human-readable output."""
@@ -155,9 +190,7 @@ class TestStatsCommand:
assert result.exit_code == 0
# Verify bucket name was parsed correctly from S3 URL
mock_client.get_bucket_stats.assert_called_once_with(
"test-bucket", detailed_stats=False
)
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="quick")
def test_stats_with_s3_url_trailing_slash(self):
"""Test stats command with s3:// URL format with trailing slash."""
@@ -182,9 +215,7 @@ class TestStatsCommand:
assert result.exit_code == 0
# Verify bucket name was parsed correctly from S3 URL with trailing slash
mock_client.get_bucket_stats.assert_called_once_with(
"test-bucket", detailed_stats=False
)
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="quick")
def test_stats_with_s3_url_with_prefix(self):
"""Test stats command with s3:// URL format with prefix (should ignore prefix)."""
@@ -209,6 +240,4 @@ class TestStatsCommand:
assert result.exit_code == 0
# Verify only bucket name was extracted, prefix ignored
mock_client.get_bucket_stats.assert_called_once_with(
"test-bucket", detailed_stats=False
)
mock_client.get_bucket_stats.assert_called_once_with("test-bucket", mode="quick")