Skip to content

Commit 19f00d4

Browse files
authored
Merge pull request #46 from afranken/feat-multipart-its
feat: partially implement multipart its
2 parents 8a956db + 5d39c08 commit 19f00d4

File tree

4 files changed

+468
-64
lines changed

4 files changed

+468
-64
lines changed

pyproject.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@ classifiers = [
2121
]
2222
# Runtime dependencies (for running tests/examples)
2323
dependencies = [
24-
"boto3>=1.40.35",
25-
"requests>=2.32.3",
24+
"boto3>=1.42.34",
25+
"requests>=2.32.5",
26+
"awscrt>=0.31.1",
2627
]
2728

2829
[dependency-groups]
2930
dev = [
30-
"pytest>=8.4.2",
31-
"testcontainers>=4.13.3",
32-
"boto3-stubs[s3]>=1.40.35",
33-
"ruff>=0.13.1",
34-
"ty>=0.0.1-alpha.33"
31+
"pytest>=9.0.2",
32+
"testcontainers>=4.14.0",
33+
"boto3-stubs[s3]>=1.42.34",
34+
"ruff>=0.14.14",
35+
"ty>=0.0.13"
3536
]
3637

3738
[project.urls]

s3mock_test.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import time
77
import uuid
8+
import zlib
89
from enum import Enum
910
from pathlib import Path
1011
from typing import Optional
@@ -13,6 +14,7 @@
1314
import boto3
1415
import pytest
1516
from _pytest.fixtures import FixtureRequest
17+
from awscrt import checksums as awscrt_checksums
1618
from boto3.s3.transfer import TransferConfig
1719
from botocore.client import Config
1820
from botocore.exceptions import ClientError
@@ -416,3 +418,51 @@ def checksum_algorithms() -> list[ChecksumAlgorithm]:
416418
ChecksumAlgorithm.CRC32C,
417419
ChecksumAlgorithm.CRC64NVME,
418420
]
421+
422+
def crc32(data: bytes) -> bytes:
423+
crc = zlib.crc32(data) & 0xFFFFFFFF
424+
return crc.to_bytes(4, byteorder="big")
425+
426+
def crc32_b64(data: bytes) -> str:
427+
return base64.b64encode(crc32(data)).decode("ascii")
428+
429+
def crc64nvme(data: bytes) -> bytes:
430+
checksum = awscrt_checksums.crc64nvme(data)
431+
return checksum.to_bytes(8, byteorder="big")
432+
433+
def crc64nvme_b64(data: bytes) -> str:
434+
return base64.b64encode(crc64nvme(data)).decode("ascii")
435+
436+
def hex_digest(path: str) -> str:
437+
h = hashlib.sha256()
438+
with open(path, "rb") as f:
439+
while True:
440+
chunk = f.read(8192)
441+
if not chunk:
442+
break
443+
h.update(chunk)
444+
return h.hexdigest()
445+
446+
447+
def multipart_etag_hex(parts: list[bytes]) -> str:
448+
digests = [hashlib.md5(part).digest() for part in parts]
449+
combined = hashlib.md5(b"".join(digests)).hexdigest()
450+
return f"{combined}-{len(parts)}"
451+
452+
453+
def multipart_crc32_checksum(parts: list[bytes]) -> str:
454+
part_checksums = [
455+
crc32(part)
456+
for part in parts
457+
]
458+
checksum_b64 = crc32_b64(b"".join(part_checksums))
459+
return f"{checksum_b64}-{len(parts)}"
460+
461+
462+
def multipart_crc64nvme_checksum(parts: list[bytes]) -> str:
463+
part_checksums = [
464+
crc64nvme(part)
465+
for part in parts
466+
]
467+
checksum_b64 = crc64nvme_b64(b"".join(part_checksums))
468+
return f"{checksum_b64}-{len(parts)}"

0 commit comments

Comments
 (0)