azuredol.ops#
Key-taking and scope-wide operations, as free functions over the caller’s (possibly wrapped) store.
dol wraps stores by delegation, so a method of a wrapped azuredol store runs bound to
the inner leaf: it receives the caller’s outer, unmapped key and reads the leaf’s own
prefix (i2mint/azuredol#4, i2mint/dol#83). Under a key codec that made
AccountStore.delete('logs', force=True) cascade-delete the container literally named
logs instead of tenantA-logs, and ContainerCollection.walk list the wrong scope.
A free function is handed the outer store, so it resolves the key through every layer:
delete_container()(store, name, force=False):del store[name]through the caller’s store, with a context-scoped authorisation to cascade for that one container. Key mapping, read-only wrappers and scope checks (name in store) are the layers’ own.walk()(store, delimiter):walk_blobsover the prefix the caller’s empty key resolves to (leaf prefix + any key codec).substore()(store, key): the sub-storestore['2026/']is meant to be, built through the caller’s own store (i2mint/azuredol#6):substore(store, 'a/')[k]is alwaysstore['a/' + k], whatever wrappers (key or value codecs, scopes) sit onstore.
The removed methods (AccountStore.delete, ContainerCollection.walk) now raise an
AttributeError naming their replacement. This is the design of cosmodol.ops and s3dol’s
ADR-0011.
What stays outside reach, stated rather than hidden: walk() yields raw Azure nodes whose
.name is an absolute blob id (azure’s own objects), and a filt_iter scope that filters
by key cannot narrow a server-side walk. A layer that performs the delete in another thread
escapes the cascade authorisation (the delete is then refused as non-empty, never widened).
Functions
|
Delete container |
|
The sub-store of |
|
Hierarchical walk ( |
- azuredol.ops.delete_container(store, name, *, force=False)[source]#
Delete container
name(a key ofstore); withforce=Truecascade-delete its blobs.The deletion is
del store[name]on the caller’s own store, so a key codec mapsname, a read-only wrapper refuses, and a scoped view cannot reach out of scope.- Raises:
ContainerNotFoundError – if
nameis not a container ofstoreContainerNotEmptyError – if the container has blobs and
forceis false
- Return type:
- azuredol.ops.substore(store, key)[source]#
The sub-store of
storeunderkey(a key ending in'/'), as the caller sees it.This is the portable form.
store['a/']is kept and works on bare stores and typed-store classes, but not through every wrapper stack; prefersubstoreeverywhere else.substore(store, 'a/')[k]isstore['a/' + k]for every wrapper stack onstore(up to the key limits below). On a bareContainerStoreit is the cheap, server-scopedstore['a/'](listing onlya/’s blobs). On anything wrapped (adolkey/value codec or scope, including the classestyped_store/AzureJsonStorebuild) it is aKeyCodecs.prefixed(key)view of that store, so the caller’s key and value mappings still apply; that view lists the wrapped store’s whole scope and keeps the keys underkey. (store['a/']on a store wrapped as an instance is minted by the innermost class and does not know about the wrappers: i2mint/azuredol#6.)The cheap path needs a leaf that does not override
_id_of_key(a subclass that maps keysgets the view). Attribute lookups on the view fall through to the wrapped store, so
.prefixand.walk_ids()of a view describe the parent’s scope: usewalk()on it. Needsdol>=0.3.75(its prefix view skips out-of-scope keys when iterating).- Parameters:
store – a
ContainerReader/ContainerStore, wrapped or notkey (
str) – a key ending in'/', without a leading'/'or an inner'//'
- azuredol.ops.walk(store, delimiter='/')[source]#
Hierarchical walk (
BlobProperties/BlobPrefixnodes) ofstore’s own scope.The scope is the blob prefix the caller’s empty key resolves to, so a key codec’s prefix is included (a codec that is not a pure prefix, e.g. a suffix, raises
ValueError; unlikeContainerCollection.walk_ids, which sees only the leaf’s prefix).