You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
s3dol becomes a dol-based adapter for S3 and S3-compatible object storage (MinIO, R2, Scaleway, Hetzner, Backblaze, Wasabi, Ceph, Supabase, GCS-interop, Tigris, …), with AWS as the reference semantics. Same shape as azuredol, so one adapter in the family reads like the next.
Three layers: connection (credential + endpoint SSOT, lazy, picklable, redacting) → base (close-to-metal Collection→Reader→Store triads, owns the prefix, one error seam, ObjectHandle) → recipes (factories + codec stacks, by composition only).
Scope: core + large-object I/O. Deferred to v1.x, tracked separately: versions/tags/bucket-config/in-flight-uploads as Mappings, async, fsspec adapter, obstore engine.
Why now — what's actually broken
Verified against the current release:
explicit endpoint_urlsilently dropped when env credentials exist (base.py:82)
store aims at AWS instead of the configured provider
explicit credentials overridden by env (base.py:71)
writing to a missing bucket creates it — even with make_bucket=False
a typo mints a bucket
url_for presigns with SigV2
#10 — rejected by modern S3 and every major alternative
stores are unpicklable
unusable with ProcessPoolExecutor or Dask
del store[k] on a missing key silently succeeds; del buckets[name] cascades unpaginated
partial, non-idempotent destruction past 1000 objects
anonymous access to public buckets is impossible
the entire open-data use case
Supabase support is a per-vendor subclass that hand-parses HTTP chunked framing out of object bodies
read-side workaround for a write-side client misconfiguration; corrupts payloads >1 chunk
Most of these share one root cause: credential/endpoint resolution is spread across three functions instead of living in one connection object.
Phases
P0 — safety net first. Tier-1 (no-I/O) tests: error classification over synthesized ClientErrors, key-codec property tests, preset merging. Plus s3dol.diagnose() shipped in a 0.1.x patch so dependents can record what their environment currently resolves to before the resolution order changes. (ADR-0008, ADR-0007 §5)
P7 — testing.py: in-memory fake + exported conformance suite, so downstream users can test without S3.
P8 — compat + release: s3dol.store.S3Store deprecated shim; pin dependents; release notes lead with behaviour changes.
Compatibility
s3dol.store.S3Store keeps working with its current signature and is removed in v2. It is also the fix delivery mechanism — dependents get corrected endpoint/credential resolution without changing a line.
s3dol/store.py must survive as a module (dependents import the fully-qualified path), bucket_name stays accepted both positionally and by keyword, path= is not renamed, and s3dol/tests/util.py keeps its two functions (py2store imports them under suppress(ImportError), so breaking them fails silently).
Release ordering matters because merging auto-publishes to PyPI and versions burn permanently — see ADR-0007 §5. In particular, the endpoint/credential fix ships separately from the naming/API change so a dependent whose data target moves can bisect it.
Three landmines for anyone picking this up
dol's prefix machinery corrupts non-matching keys — the "obvious" refactor reproduces the bug it was meant to fix. dol#82.
A dol key-wrapper delegates methods with the outer key, so url_for/sub/handle/info/delete_many silently address the wrong object. This is why the prefix lives in the leaf. dol#83.
Never pass EncodingType to a list call — botocore sets it and decodes it, but only when it set it itself.
Tracking issue for the v1 redesign. Design docs live in
misc/docs/— architecture.md is the entry point, decisions/ holds ten ADRs.What v1 is
s3dolbecomes adol-based adapter for S3 and S3-compatible object storage (MinIO, R2, Scaleway, Hetzner, Backblaze, Wasabi, Ceph, Supabase, GCS-interop, Tigris, …), with AWS as the reference semantics. Same shape asazuredol, so one adapter in the family reads like the next.Three layers:
connection(credential + endpoint SSOT, lazy, picklable, redacting) →base(close-to-metal Collection→Reader→Store triads, owns the prefix, one error seam,ObjectHandle) →recipes(factories + codec stacks, by composition only).Scope: core + large-object I/O. Deferred to v1.x, tracked separately: versions/tags/bucket-config/in-flight-uploads as Mappings, async, fsspec adapter, obstore engine.
Why now — what's actually broken
Verified against the current release:
endpoint_urlsilently dropped when env credentials exist (base.py:82)base.py:71)list(store)returns[]on any error (base.py:109)make_bucket=Falseurl_forpresigns with SigV2ProcessPoolExecutoror Daskdel store[k]on a missing key silently succeeds;del buckets[name]cascades unpaginatedMost of these share one root cause: credential/endpoint resolution is spread across three functions instead of living in one connection object.
Phases
ClientErrors, key-codec property tests, preset merging. Pluss3dol.diagnose()shipped in a 0.1.x patch so dependents can record what their environment currently resolves to before the resolution order changes. (ADR-0008, ADR-0007 §5)dolfixes: Prefix relativization silently corrupts non-matching keys (boundary violation) dol#82 (prefix corruption), Key-transform wrappers delegate capability methods with the unmapped key (url_for etc. silently address the wrong object) dol#83 (delegation with unmapped key). Raise thedolfloor.connection.py+presets.py: the credential/endpoint SSOT, the provider registry, capabilities. Fixes the first two rows above.errors.py: the(operation, code, status)translation seam. Fixes the third row. (discussion An extendable KeyError for s3dol and more #6)base.py: the triads, prefix in the leaf,ObjectHandle.values.py/writes.py/reads.py: large-object I/O. (Appendable s3dol #5)testing.py: in-memory fake + exported conformance suite, so downstream users can test without S3.s3dol.store.S3Storedeprecated shim; pin dependents; release notes lead with behaviour changes.Compatibility
s3dol.store.S3Storekeeps working with its current signature and is removed in v2. It is also the fix delivery mechanism — dependents get corrected endpoint/credential resolution without changing a line.s3dol/store.pymust survive as a module (dependents import the fully-qualified path),bucket_namestays accepted both positionally and by keyword,path=is not renamed, ands3dol/tests/util.pykeeps its two functions (py2storeimports them undersuppress(ImportError), so breaking them fails silently).Release ordering matters because merging auto-publishes to PyPI and versions burn permanently — see ADR-0007 §5. In particular, the endpoint/credential fix ships separately from the naming/API change so a dependent whose data target moves can bisect it.
Three landmines for anyone picking this up
dol's prefix machinery corrupts non-matching keys — the "obvious" refactor reproduces the bug it was meant to fix. dol#82.dolkey-wrapper delegates methods with the outer key, sourl_for/sub/handle/info/delete_manysilently address the wrong object. This is why the prefix lives in the leaf. dol#83.EncodingTypeto a list call — botocore sets it and decodes it, but only when it set it itself.