> built 2026-10-30 07:53 UTC from 5dd2358 (master) · azuredol 0.1.17. Details: build_info.json

# index.html.md

<!-- generated by epythet -->

# azuredol

Azure Storage Data Object Layer

To install:	`pip install azuredol`

## Sub-stores: use `substore()`

To get the part of a store under a prefix, prefer `azuredol.substore(store, 'sub/')`: it is the portable form and returns a sub-store through any wrapper stack on `store` (key codecs, value codecs, scopes), so `substore(store, 'sub/')[k]` is always `store['sub/' + k]`.

```python
from azuredol import substore

sub = substore(store, '2026/')
```

`store['sub/']` (a key ending in `/`) also works and is kept, but only on a bare store and on typed-store classes (`typed_store`, `AzureJsonStore`). It does not work through every wrapper stack: a dol wrapper placed on top of an *instance* is not carried into `store['sub/']`.

<p class="epythet-aggregates">This documentation as a single file: <a href="azuredol.md">azuredol.md</a> (Markdown, for agents).</p>


# _autosummary/azuredol.base.html.md

# azuredol.base

Close-to-metal Mapping stores over Azure Blob Storage.

Three concrete classes:

- `ContainerStore` — the primary store. Mapping of blob name → bytes within one container.
- `AccountStore` — mapping of container name → `ContainerStore` within one account.
- `BlobHandle`  — non-Mapping escape hatch for one blob with the full Azure surface.

See `misc/docs/architecture.md` Layer B. Codec / convenience layers live in
`azuredol.recipes`; the connection layer lives in `azuredol.connection`.

### Classes

| [`AccountCollection`](_autosummary/azuredol.base.html.md#azuredol.base.AccountCollection)([connection, ...])              | Mapping over container names in an account (iter / contains / len).                     |
|----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| [`AccountReader`](_autosummary/azuredol.base.html.md#azuredol.base.AccountReader)([connection, ...])                  | Adds `__getitem__` returning a `ContainerStore` (or configured subclass).               |
| [`AccountStore`](_autosummary/azuredol.base.html.md#azuredol.base.AccountStore)([connection, ...])                   | Read-write Mapping over containers in an account.                                       |
| [`BlobHandle`](_autosummary/azuredol.base.html.md#azuredol.base.BlobHandle)(container, blob, \*[, connection])     | Thin facade over one `BlobClient`.                                                      |
| [`ContainerCollection`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerCollection)(container, \*[, prefix, ...]) | Iteration / membership / cardinality (`__len__` deliberately omitted) over a container. |
| [`ContainerReader`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerReader)(container, \*[, prefix, ...])     | Adds `__getitem__` (returns bytes) over `ContainerCollection`.                          |
| [`ContainerStore`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerStore)(container, \*[, prefix, ...])      | The primary read-write Mapping over an Azure container.                                 |

### *class* azuredol.base.AccountCollection(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: `_AccountStoreBase`, `KvReader`

Mapping over container names in an account (iter / contains / len).

### *class* azuredol.base.AccountReader(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: [`AccountCollection`](_autosummary/azuredol.base.html.md#azuredol.base.AccountCollection)

Adds `__getitem__` returning a `ContainerStore` (or configured subclass).

### *class* azuredol.base.AccountStore(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: [`AccountReader`](_autosummary/azuredol.base.html.md#azuredol.base.AccountReader), `KvPersister`

Read-write Mapping over containers in an account.

`__setitem__` creates a container; the value is ignored except when it’s a
Mapping (in which case it is treated as an initial bulk-load).

`__delitem__` refuses non-empty containers — call `azuredol.ops.delete_container(store, name, force=True)`
to acknowledge a cascading delete. See `misc/docs/design_decisions.md` §12.

### *class* azuredol.base.BlobHandle(container, blob, , connection=None)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Thin facade over one `BlobClient`. Not a Mapping.

Use when you need the full Azure-blob surface for a single blob: metadata,
properties, conditional writes, leases, copy, append, SAS URL generation,
streaming downloads.

* **Parameters:**
  * **container** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), `ContainerClient`]) – An existing `ContainerClient` or a container name string.
  * **blob** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The blob name (relative to the container root; full path including ‘/’).
  * **connection** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection), `BlobServiceClient`, [`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Ignored if `container` is a `ContainerClient`. Otherwise
    resolved via `AzureConnection.from_anything`.

#### acquire_lease(lease_duration=-1)

Acquire a lease (15-60s, or -1 for infinite). Returns a `BlobLeaseClient`.

#### append(data)

Append bytes to an append-blob (creating it if absent).

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

#### copy_from(source_url, , requires_sync=None)

Server-side copy from a URL. Same-account = sync; cross-account = async (poll).

#### create(data, , overwrite=False, \*\*kwargs)

Strict-create variant of `write`; raises `BlobAlreadyExistsError` on conflict.

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

#### download_stream(, chunk_size=None)

Return a streaming downloader. Iterate chunks via `.chunks()` or `.readinto(fp)`.

#### properties()

Return `BlobProperties` (size, last_modified, etag, content_settings, metadata, …).

#### read(, offset=None, length=None)

Download (possibly a range) and return bytes.

* **Return type:**
  [`bytes`](https://docs.python.org/3/builtins/stdtypes.html#bytes)

#### url(, expires_in=None)

Return the blob URL.

If `expires_in` is set and the underlying credential is a shared-key, a SAS
URL with read permission is generated. Otherwise the plain blob URL is returned
(which is only useful for public containers or pre-shared SAS contexts).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

#### write(data, , blob_type=BlobType.BLOCKBLOB, overwrite=True, content_type=None, metadata=None, \*\*kwargs)

Upload data; default overwrite=True for `MutableMapping` symmetry.

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### *class* azuredol.base.ContainerCollection(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: `_ContainerStoreBase`, `KvReader`

Iteration / membership / cardinality (`__len__` deliberately omitted) over a container.

`__len__` is intentionally NOT implemented — see
`misc/docs/design_decisions.md` §2. Pagination cost is unbounded; users wanting
a count call `sum(1 for _ in store)`.

#### walk_ids(delimiter='/')

Hierarchical walk of the *leaf’s* prefix, yielding `BlobProperties` / `BlobPrefix` nodes.

Thin pass-through to `ContainerClient.walk_blobs`. The scope is the leaf’s own
`prefix` and each node’s `.name` is an absolute blob id (never a store key), so
under a `dol` key codec it disagrees with `__iter__`. For a scope that follows
the caller’s (possibly wrapped) store use `azuredol.ops.walk(store)`.

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]

### *class* azuredol.base.ContainerReader(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: [`ContainerCollection`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerCollection)

Adds `__getitem__` (returns bytes) over `ContainerCollection`.

The trailing-slash sub-store convention lives here: `store['sub/']` returns a new
`ContainerReader` with extended prefix and zero round-trips. This works on a bare store
and on typed-store classes, but not through every wrapper stack (a `dol` wrapper placed
on an instance is not carried into the sub-store); [`azuredol.substore()`](_autosummary/azuredol.html.md#azuredol.substore) is the portable
form and should be preferred (i2mint/azuredol#9).

### *class* azuredol.base.ContainerStore(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: [`ContainerReader`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerReader), `KvPersister`

The primary read-write Mapping over an Azure container.

Doctest below requires Azurite (or live Azure). It is shown but not auto-run.

Example (requires Azurite):

```pycon
>>> from azuredol import ContainerStore
>>> s = ContainerStore(
...     'my-test-container',
...     connection='UseDevelopmentStorage=true',
...     create_container_if_missing=True,
... )
>>> s['k1'] = b'v1'
>>> s['k1']
b'v1'
>>> 'k1' in s
True
>>> del s['k1']
```

For unit tests without Azurite, prototype with `dol`’s in-memory pattern:
`wrap_kvs(dict(), ...)`.


# _autosummary/azuredol.connection.html.md

# azuredol.connection

Connection-layer for azuredol.

Owns the expensive resource (`BlobServiceClient`) and the credential cascade.
See `misc/docs/architecture.md` Layer A and `misc/docs/design_decisions.md` §6.

### Module Attributes

| [`CredentialLike`](_autosummary/azuredol.connection.html.md#azuredol.connection.CredentialLike)   | account-key string, connection string, SAS string, dict of kwargs, `azure.identity` credential object, or None (defer to env / DefaultAzureCredential).   |
|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|

### Functions

| [`resolve_credential`](_autosummary/azuredol.connection.html.md#azuredol.connection.resolve_credential)(\*[, credential, ...])   | Resolve a credential into a normalized form that can build a `BlobServiceClient`.   |
|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|

### Classes

| [`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection)([credential, ...])   | Holds a resolved credential and a lazy `BlobServiceClient`.   |
|---------------------------------------------------------------------------------------|---------------------------------------------------------------|

### *class* azuredol.connection.AzureConnection(credential=None, connection_string=None, account_url=None, account_key=None, client_kwargs=dict())

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Holds a resolved credential and a lazy `BlobServiceClient`.

This is the dependency-injection seam for the whole package. Tests construct one
pointing at Azurite without touching any store class.

* **Parameters:**
  * **credential** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – explicit credential object, key string, or SAS string.
  * **connection_string** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – full connection string (overrides `credential`).
  * **account_url** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – storage account URL (with or without credential).
  * **account_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – shared-key for the account.

All four args are optional; the credential cascade in
`resolve_credential` is consulted if none are provided.

#### blob_client(container, blob)

Cheap derivation of a `BlobClient` from the shared service client.

#### container_client(container)

Cheap derivation of a `ContainerClient` from the shared service client.

#### *classmethod* from_anything(source)

Convenience: build an `AzureConnection` from a thing-or-spec.

Accepts:

> - `AzureConnection` (returned as-is)
> - `BlobServiceClient` (wrapped without further resolution)
> - `str` (connection string)
> - `dict` (passed as kwargs)
> - `None` (defer to env / AAD)
* **Return type:**
  [`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection)

#### *property* service_client *: BlobServiceClient*

The lazily-constructed `BlobServiceClient`. Cached for the connection’s lifetime.

### azuredol.connection.CredentialLike

account-key string, connection string, SAS string, dict of kwargs,
`azure.identity` credential object, or None (defer to env / DefaultAzureCredential).

* **Type:**
  Any of

alias of [`str`](https://docs.python.org/3/builtins/stdtypes.html#str) | [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict) | [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/builtins/constants.html#None)

### azuredol.connection.resolve_credential(, credential=None, connection_string=None, account_url=None, account_key=None)

Resolve a credential into a normalized form that can build a `BlobServiceClient`.

Cascade (first hit wins):

1. Explicit `credential=`
2. Explicit `connection_string=`
3. Explicit `account_url=` + `account_key=` (or just `account_url=` + AAD)
4. Env var `AZURE_STORAGE_CONNECTION_STRING`
5. Env vars `AZURE_STORAGE_ACCOUNT_URL` + `AZURE_STORAGE_ACCOUNT_KEY`
6. Env var `AZURE_STORAGE_ACCOUNT_URL` alone + `DefaultAzureCredential`

* **Returns:**
  `{"conn_str": "..."}`                            # for from_connection_string
  `{"account_url": "...", "credential": <obj>}`    # for \_\_init_\_
* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)
* **Raises:**
  [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError) – if no source resolves.


# _autosummary/azuredol.errors.html.md

# azuredol.errors

Custom exceptions and error-translation decorator for azuredol.

All Azure SDK exception handling for the Mapping-shaped methods on close-to-metal stores
funnels through `translate_azure_errors` so the auth-error vs not-found distinction
stays auditable from one place. See `misc/docs/design_decisions.md` §4.

### Functions

| [`translate_azure_errors`](_autosummary/azuredol.errors.html.md#azuredol.errors.translate_azure_errors)(\*[, key_arg, ...])   | Decorator: translate Azure SDK exceptions into `KeyError` subclasses.   |
|-----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|

### Exceptions

| [`BlobAlreadyExistsError`](_autosummary/azuredol.errors.html.md#azuredol.errors.BlobAlreadyExistsError)      | Raised on strict-create write attempts when the blob already exists.   |
|------------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`BlobNotFoundError`](_autosummary/azuredol.errors.html.md#azuredol.errors.BlobNotFoundError)           | Raised when a blob does not exist.                                     |
| [`ContainerAlreadyExistsError`](_autosummary/azuredol.errors.html.md#azuredol.errors.ContainerAlreadyExistsError) | Raised on strict-create attempts when the container already exists.    |
| [`ContainerNotEmptyError`](_autosummary/azuredol.errors.html.md#azuredol.errors.ContainerNotEmptyError)      | Raised on `del account_store[name]` when the container has blobs.      |
| [`ContainerNotFoundError`](_autosummary/azuredol.errors.html.md#azuredol.errors.ContainerNotFoundError)      | Raised when a container does not exist.                                |

### *exception* azuredol.errors.BlobAlreadyExistsError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised on strict-create write attempts when the blob already exists.

`KeyError` subclass for symmetry with `BlobNotFoundError` — both signal a
key-vs-store mismatch.

### *exception* azuredol.errors.BlobNotFoundError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised when a blob does not exist. `KeyError` subclass so `Mapping` consumers work.

### *exception* azuredol.errors.ContainerAlreadyExistsError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised on strict-create attempts when the container already exists.

### *exception* azuredol.errors.ContainerNotEmptyError

Bases: [`RuntimeError`](https://docs.python.org/3/builtins/exceptions.html#RuntimeError)

Raised on `del account_store[name]` when the container has blobs.

The user must call `azuredol.delete_container(account_store, name, force=True)` to acknowledge the
cascading delete. See `misc/docs/design_decisions.md` §12.

### *exception* azuredol.errors.ContainerNotFoundError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised when a container does not exist.

### azuredol.errors.translate_azure_errors(\*, key_arg=0, not_found_cls=<class 'azuredol.errors.BlobNotFoundError'>, exists_cls=<class 'azuredol.errors.BlobAlreadyExistsError'>)

Decorator: translate Azure SDK exceptions into `KeyError` subclasses.

Auth errors (`ClientAuthenticationError`) and all other Azure errors propagate
untouched — they are *never* swallowed as “key absent”. See
`misc/docs/design_decisions.md` §4.

* **Parameters:**
  * **key_arg** ([`int`](https://docs.python.org/3/builtins/functions.html#int) | [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Position (int) or name (str) of the key argument in the wrapped
    method’s signature. Used to populate `KeyError(key)`. The receiver
    `self` is at index 0, so the user-facing key is typically at index 1
    (the default).
  * **not_found_cls** ([`type`](https://docs.python.org/3/builtins/functions.html#type)[[`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)]) – Exception class to raise on `ResourceNotFoundError`.
  * **exists_cls** ([`type`](https://docs.python.org/3/builtins/functions.html#type)[[`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)]) – Exception class to raise on `ResourceExistsError`.
* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)


# _autosummary/azuredol.functions.html.md

# azuredol.functions

Azure functions tools

### Functions

| [`azure_func_service`](_autosummary/azuredol.functions.html.md#azuredol.functions.azure_func_service)(rootfolder[, extra_args, ...])   | Context manager to start an Azure Function host using `func start` in the specified folder.   |
|------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|

### azuredol.functions.azure_func_service(rootfolder, extra_args='', , verbose=True, wait_for_log=None, timeout=30, print_output=True)

Context manager to start an Azure Function host using `func start` in the specified folder.

* **Parameters:**
  * **rootfolder** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – The directory containing the Azure Function App.
  * **extra_args** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – Additional command-line arguments for the `func start` command.
  * **wait_for_log** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – A substring or regular expression pattern that indicates when the service is ready.
    If provided, the context manager waits until a matching log line is detected.
  * **timeout** ([*int*](https://docs.python.org/3/builtins/functions.html#int)) – Maximum time in seconds to wait for the ready log message.
  * **print_output** ([*bool*](https://docs.python.org/3/builtins/functions.html#bool)) – If True, prints the process output to stdout.
* **Yields:**
  *subprocess.Popen* – The process object representing the running Azure Functions host.

Usage Example:
: with azure_func_service(‘/path/to/azure_func’, extra_args=”–verbose”, wait_for_log=r’Host started’) as proc:
  : # Place code here to test the HTTP service.
    …


# _autosummary/azuredol.html.md

# azuredol

Access Azure Blob Storage through a Mapping interface.

`azuredol` exposes Azure Blob Storage as `dol`-style `Mapping` /
`MutableMapping` interfaces.

Quick start:

```default
from azuredol import azure_store

# Uses connection_string env var or Azurite (UseDevelopmentStorage=true)
store = azure_store(
    'mycontainer',
    connection_string='UseDevelopmentStorage=true',
    create_container_if_missing=True,
)

store['k1'] = b'hello world'
store['k1']               # → b'hello world'
'k1' in store             # → True
del store['k1']
```

See `misc/docs/architecture.md` for the layered design.

### Functions

| [`resolve_credential`](_autosummary/azuredol.html.md#azuredol.resolve_credential)(\*[, credential, ...])         | Resolve a credential into a normalized form that can build a `BlobServiceClient`.               |
|----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|
| [`translate_azure_errors`](_autosummary/azuredol.html.md#azuredol.translate_azure_errors)(\*[, key_arg, ...])        | Decorator: translate Azure SDK exceptions into `KeyError` subclasses.                           |
| [`azure_store`](_autosummary/azuredol.html.md#azuredol.azure_store)(container, \*[, prefix, ...])         | Build a ready-to-use `ContainerStore` (or codec-wrapped variant) in one call.                   |
| [`typed_store`](_autosummary/azuredol.html.md#azuredol.typed_store)(decode, encode, \*[, base])           | A `base` (default `ContainerStore`) class with values `decode(bytes)` / `encode(obj) -> bytes`. |
| [`typed_codec`](_autosummary/azuredol.html.md#azuredol.typed_codec)(decode, encode)                       | `typed_store` as a class decorator: the shape `azure_store(value_codec=...)` takes.             |
| [`delete_container`](_autosummary/azuredol.html.md#azuredol.delete_container)(store, name, \*[, force])        | Delete container `name` (a key of `store`); with `force=True` cascade-delete its blobs.         |
| [`walk_container`](_autosummary/azuredol.html.md#azuredol.walk_container)(store[, delimiter])                | Hierarchical walk (`BlobProperties` / `BlobPrefix` nodes) of `store`'s own scope.               |
| [`substore`](_autosummary/azuredol.html.md#azuredol.substore)(store, key)                              | The sub-store of `store` under `key` (a key ending in `'/'`), as the caller sees it.            |
| [`azure_func_service`](_autosummary/azuredol.html.md#azuredol.azure_func_service)(rootfolder[, extra_args, ...]) | Context manager to start an Azure Function host using `func start` in the specified folder.     |

### Classes

| [`AzureConnection`](_autosummary/azuredol.html.md#azuredol.AzureConnection)([credential, ...])                | Holds a resolved credential and a lazy `BlobServiceClient`.                             |
|----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| [`AccountCollection`](_autosummary/azuredol.html.md#azuredol.AccountCollection)([connection, ...])              | Mapping over container names in an account (iter / contains / len).                     |
| [`AccountReader`](_autosummary/azuredol.html.md#azuredol.AccountReader)([connection, ...])                  | Adds `__getitem__` returning a `ContainerStore` (or configured subclass).               |
| [`AccountStore`](_autosummary/azuredol.html.md#azuredol.AccountStore)([connection, ...])                   | Read-write Mapping over containers in an account.                                       |
| [`BlobHandle`](_autosummary/azuredol.html.md#azuredol.BlobHandle)(container, blob, \*[, connection])     | Thin facade over one `BlobClient`.                                                      |
| [`ContainerCollection`](_autosummary/azuredol.html.md#azuredol.ContainerCollection)(container, \*[, prefix, ...]) | Iteration / membership / cardinality (`__len__` deliberately omitted) over a container. |
| [`ContainerReader`](_autosummary/azuredol.html.md#azuredol.ContainerReader)(container, \*[, prefix, ...])     | Adds `__getitem__` (returns bytes) over `ContainerCollection`.                          |
| [`ContainerStore`](_autosummary/azuredol.html.md#azuredol.ContainerStore)(container, \*[, prefix, ...])      | The primary read-write Mapping over an Azure container.                                 |
| [`AzureJsonStore`](_autosummary/azuredol.html.md#azuredol.AzureJsonStore)                                    |                                                                                         |
| [`AzurePickleStore`](_autosummary/azuredol.html.md#azuredol.AzurePickleStore)                                  |                                                                                         |
| [`AzureTextStore`](_autosummary/azuredol.html.md#azuredol.AzureTextStore)                                    |                                                                                         |

### Exceptions

| [`BlobAlreadyExistsError`](_autosummary/azuredol.html.md#azuredol.BlobAlreadyExistsError)      | Raised on strict-create write attempts when the blob already exists.   |
|------------------------------------------------------------------------------|------------------------------------------------------------------------|
| [`BlobNotFoundError`](_autosummary/azuredol.html.md#azuredol.BlobNotFoundError)           | Raised when a blob does not exist.                                     |
| [`ContainerAlreadyExistsError`](_autosummary/azuredol.html.md#azuredol.ContainerAlreadyExistsError) | Raised on strict-create attempts when the container already exists.    |
| [`ContainerNotEmptyError`](_autosummary/azuredol.html.md#azuredol.ContainerNotEmptyError)      | Raised on `del account_store[name]` when the container has blobs.      |
| [`ContainerNotFoundError`](_autosummary/azuredol.html.md#azuredol.ContainerNotFoundError)      | Raised when a container does not exist.                                |

### *class* azuredol.AccountCollection(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: `_AccountStoreBase`, `KvReader`

Mapping over container names in an account (iter / contains / len).

### *class* azuredol.AccountReader(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: [`AccountCollection`](_autosummary/azuredol.base.html.md#azuredol.base.AccountCollection)

Adds `__getitem__` returning a `ContainerStore` (or configured subclass).

### *class* azuredol.AccountStore(connection=None, , container_store_cls=None, container_store_kwargs=None)

Bases: [`AccountReader`](_autosummary/azuredol.base.html.md#azuredol.base.AccountReader), `KvPersister`

Read-write Mapping over containers in an account.

`__setitem__` creates a container; the value is ignored except when it’s a
Mapping (in which case it is treated as an initial bulk-load).

`__delitem__` refuses non-empty containers — call `azuredol.ops.delete_container(store, name, force=True)`
to acknowledge a cascading delete. See `misc/docs/design_decisions.md` §12.

### *class* azuredol.AzureConnection(credential=None, connection_string=None, account_url=None, account_key=None, client_kwargs=dict())

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Holds a resolved credential and a lazy `BlobServiceClient`.

This is the dependency-injection seam for the whole package. Tests construct one
pointing at Azurite without touching any store class.

* **Parameters:**
  * **credential** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – explicit credential object, key string, or SAS string.
  * **connection_string** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – full connection string (overrides `credential`).
  * **account_url** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – storage account URL (with or without credential).
  * **account_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – shared-key for the account.

All four args are optional; the credential cascade in
`resolve_credential` is consulted if none are provided.

#### blob_client(container, blob)

Cheap derivation of a `BlobClient` from the shared service client.

#### container_client(container)

Cheap derivation of a `ContainerClient` from the shared service client.

#### *classmethod* from_anything(source)

Convenience: build an `AzureConnection` from a thing-or-spec.

Accepts:

> - `AzureConnection` (returned as-is)
> - `BlobServiceClient` (wrapped without further resolution)
> - `str` (connection string)
> - `dict` (passed as kwargs)
> - `None` (defer to env / AAD)
* **Return type:**
  [`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection)

#### *property* service_client *: BlobServiceClient*

The lazily-constructed `BlobServiceClient`. Cached for the connection’s lifetime.

### azuredol.AzureJsonStore

alias of [`ContainerStore`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerStore)

### azuredol.AzurePickleStore

alias of [`ContainerStore`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerStore)

### azuredol.AzureTextStore

alias of [`ContainerStore`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerStore)

### *exception* azuredol.BlobAlreadyExistsError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised on strict-create write attempts when the blob already exists.

`KeyError` subclass for symmetry with `BlobNotFoundError` — both signal a
key-vs-store mismatch.

### *class* azuredol.BlobHandle(container, blob, , connection=None)

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object)

Thin facade over one `BlobClient`. Not a Mapping.

Use when you need the full Azure-blob surface for a single blob: metadata,
properties, conditional writes, leases, copy, append, SAS URL generation,
streaming downloads.

* **Parameters:**
  * **container** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), `ContainerClient`]) – An existing `ContainerClient` or a container name string.
  * **blob** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – The blob name (relative to the container root; full path including ‘/’).
  * **connection** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection), `BlobServiceClient`, [`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – Ignored if `container` is a `ContainerClient`. Otherwise
    resolved via `AzureConnection.from_anything`.

#### acquire_lease(lease_duration=-1)

Acquire a lease (15-60s, or -1 for infinite). Returns a `BlobLeaseClient`.

#### append(data)

Append bytes to an append-blob (creating it if absent).

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

#### copy_from(source_url, , requires_sync=None)

Server-side copy from a URL. Same-account = sync; cross-account = async (poll).

#### create(data, , overwrite=False, \*\*kwargs)

Strict-create variant of `write`; raises `BlobAlreadyExistsError` on conflict.

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

#### download_stream(, chunk_size=None)

Return a streaming downloader. Iterate chunks via `.chunks()` or `.readinto(fp)`.

#### properties()

Return `BlobProperties` (size, last_modified, etag, content_settings, metadata, …).

#### read(, offset=None, length=None)

Download (possibly a range) and return bytes.

* **Return type:**
  [`bytes`](https://docs.python.org/3/builtins/stdtypes.html#bytes)

#### url(, expires_in=None)

Return the blob URL.

If `expires_in` is set and the underlying credential is a shared-key, a SAS
URL with read permission is generated. Otherwise the plain blob URL is returned
(which is only useful for public containers or pre-shared SAS contexts).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

#### write(data, , blob_type=BlobType.BLOCKBLOB, overwrite=True, content_type=None, metadata=None, \*\*kwargs)

Upload data; default overwrite=True for `MutableMapping` symmetry.

* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### *exception* azuredol.BlobNotFoundError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised when a blob does not exist. `KeyError` subclass so `Mapping` consumers work.

### *exception* azuredol.ContainerAlreadyExistsError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised on strict-create attempts when the container already exists.

### *class* azuredol.ContainerCollection(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: `_ContainerStoreBase`, `KvReader`

Iteration / membership / cardinality (`__len__` deliberately omitted) over a container.

`__len__` is intentionally NOT implemented — see
`misc/docs/design_decisions.md` §2. Pagination cost is unbounded; users wanting
a count call `sum(1 for _ in store)`.

#### walk_ids(delimiter='/')

Hierarchical walk of the *leaf’s* prefix, yielding `BlobProperties` / `BlobPrefix` nodes.

Thin pass-through to `ContainerClient.walk_blobs`. The scope is the leaf’s own
`prefix` and each node’s `.name` is an absolute blob id (never a store key), so
under a `dol` key codec it disagrees with `__iter__`. For a scope that follows
the caller’s (possibly wrapped) store use `azuredol.ops.walk(store)`.

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]

### *exception* azuredol.ContainerNotEmptyError

Bases: [`RuntimeError`](https://docs.python.org/3/builtins/exceptions.html#RuntimeError)

Raised on `del account_store[name]` when the container has blobs.

The user must call `azuredol.delete_container(account_store, name, force=True)` to acknowledge the
cascading delete. See `misc/docs/design_decisions.md` §12.

### *exception* azuredol.ContainerNotFoundError

Bases: [`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)

Raised when a container does not exist.

### *class* azuredol.ContainerReader(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: [`ContainerCollection`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerCollection)

Adds `__getitem__` (returns bytes) over `ContainerCollection`.

The trailing-slash sub-store convention lives here: `store['sub/']` returns a new
`ContainerReader` with extended prefix and zero round-trips. This works on a bare store
and on typed-store classes, but not through every wrapper stack (a `dol` wrapper placed
on an instance is not carried into the sub-store); [`azuredol.substore()`](_autosummary/azuredol.html.md#azuredol.substore) is the portable
form and should be preferred (i2mint/azuredol#9).

### *class* azuredol.ContainerStore(container, , prefix='', connection=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, upload_kwargs=None, download_kwargs=None)

Bases: [`ContainerReader`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerReader), `KvPersister`

The primary read-write Mapping over an Azure container.

Doctest below requires Azurite (or live Azure). It is shown but not auto-run.

Example (requires Azurite):

```pycon
>>> from azuredol import ContainerStore
>>> s = ContainerStore(
...     'my-test-container',
...     connection='UseDevelopmentStorage=true',
...     create_container_if_missing=True,
... )
>>> s['k1'] = b'v1'
>>> s['k1']
b'v1'
>>> 'k1' in s
True
>>> del s['k1']
```

For unit tests without Azurite, prototype with `dol`’s in-memory pattern:
`wrap_kvs(dict(), ...)`.

### azuredol.azure_func_service(rootfolder, extra_args='', , verbose=True, wait_for_log=None, timeout=30, print_output=True)

Context manager to start an Azure Function host using `func start` in the specified folder.

* **Parameters:**
  * **rootfolder** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – The directory containing the Azure Function App.
  * **extra_args** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – Additional command-line arguments for the `func start` command.
  * **wait_for_log** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str)) – A substring or regular expression pattern that indicates when the service is ready.
    If provided, the context manager waits until a matching log line is detected.
  * **timeout** ([*int*](https://docs.python.org/3/builtins/functions.html#int)) – Maximum time in seconds to wait for the ready log message.
  * **print_output** ([*bool*](https://docs.python.org/3/builtins/functions.html#bool)) – If True, prints the process output to stdout.
* **Yields:**
  *subprocess.Popen* – The process object representing the running Azure Functions host.

Usage Example:
: with azure_func_service(‘/path/to/azure_func’, extra_args=”–verbose”, wait_for_log=r’Host started’) as proc:
  : # Place code here to test the HTTP service.
    …

### azuredol.azure_store(container, , prefix='', connection=None, credential=None, connection_string=None, account_url=None, account_key=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, value_codec=None)

Build a ready-to-use `ContainerStore` (or codec-wrapped variant) in one call.

This is the “simple things simple” entry point. For complex configurations construct
`AzureConnection` and `ContainerStore` directly.

* **Parameters:**
  * **container** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Container name.
  * **prefix** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Blob-name prefix to scope all keys.
  * **connection** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection), [`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – An `AzureConnection` (or anything `AzureConnection.from_anything`
    accepts) to reuse a service client. Mutually exclusive with the explicit
    `credential` / `connection_string` / `account_*` kwargs.
  * **credential** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **connection_string** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **account_url** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **account_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **create_container_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Create the container on first use if absent.
  * **blob_type** (`BlobType`) – Default blob type for writes.
  * **value_codec** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)]) – A decorator that, given a class, returns a wrapped class. Typically
    `typed_codec(decode, encode)`. A bare `dol.wrap_kvs(...)` breaks the
    trailing-slash sub-store (i2mint/azuredol#4). When None (default), bytes pass
    through.
* **Returns:**
  A `ContainerStore` instance, possibly codec-wrapped.

### azuredol.delete_container(store, name, , force=False)

Delete container `name` (a key of `store`); with `force=True` cascade-delete its blobs.

The deletion is `del store[name]` on the caller’s own store, so a key codec maps
`name`, a read-only wrapper refuses, and a scoped view cannot reach out of scope.

* **Raises:**
  * [**ContainerNotFoundError**](_autosummary/azuredol.html.md#azuredol.ContainerNotFoundError) – if `name` is not a container of `store`
  * [**ContainerNotEmptyError**](_autosummary/azuredol.html.md#azuredol.ContainerNotEmptyError) – if the container has blobs and `force` is false
* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### azuredol.resolve_credential(, credential=None, connection_string=None, account_url=None, account_key=None)

Resolve a credential into a normalized form that can build a `BlobServiceClient`.

Cascade (first hit wins):

1. Explicit `credential=`
2. Explicit `connection_string=`
3. Explicit `account_url=` + `account_key=` (or just `account_url=` + AAD)
4. Env var `AZURE_STORAGE_CONNECTION_STRING`
5. Env vars `AZURE_STORAGE_ACCOUNT_URL` + `AZURE_STORAGE_ACCOUNT_KEY`
6. Env var `AZURE_STORAGE_ACCOUNT_URL` alone + `DefaultAzureCredential`

* **Returns:**
  `{"conn_str": "..."}`                            # for from_connection_string
  `{"account_url": "...", "credential": <obj>}`    # for \_\_init_\_
* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)
* **Raises:**
  [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError) – if no source resolves.

### azuredol.substore(store, key)

The sub-store of `store` under `key` (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; prefer `substore` everywhere else.

`substore(store, 'a/')[k]` is `store['a/' + k]` for every wrapper stack on `store` (up to the key limits below).
On a bare `ContainerStore` it is the cheap, server-scoped `store['a/']` (listing only
`a/`’s blobs). On anything wrapped (a `dol` key/value codec or scope, including the
classes `typed_store`/`AzureJsonStore` build) it is a `KeyCodecs.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 under `key`. (`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 keys

gets the view). Attribute lookups on the view fall through to the wrapped store, so
`.prefix` and `.walk_ids()` of a view describe the parent’s scope: use
`walk()` on it. Needs `dol>=0.3.75` (its prefix view skips out-of-scope keys when
iterating).

* **Parameters:**
  * **store** – a `ContainerReader`/`ContainerStore`, wrapped or not
  * **key** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – a key ending in `'/'`, without a leading `'/'` or an inner `'//'`

### azuredol.translate_azure_errors(\*, key_arg=0, not_found_cls=<class 'azuredol.errors.BlobNotFoundError'>, exists_cls=<class 'azuredol.errors.BlobAlreadyExistsError'>)

Decorator: translate Azure SDK exceptions into `KeyError` subclasses.

Auth errors (`ClientAuthenticationError`) and all other Azure errors propagate
untouched — they are *never* swallowed as “key absent”. See
`misc/docs/design_decisions.md` §4.

* **Parameters:**
  * **key_arg** ([`int`](https://docs.python.org/3/builtins/functions.html#int) | [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Position (int) or name (str) of the key argument in the wrapped
    method’s signature. Used to populate `KeyError(key)`. The receiver
    `self` is at index 0, so the user-facing key is typically at index 1
    (the default).
  * **not_found_cls** ([`type`](https://docs.python.org/3/builtins/functions.html#type)[[`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)]) – Exception class to raise on `ResourceNotFoundError`.
  * **exists_cls** ([`type`](https://docs.python.org/3/builtins/functions.html#type)[[`KeyError`](https://docs.python.org/3/builtins/exceptions.html#KeyError)]) – Exception class to raise on `ResourceExistsError`.
* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)

### azuredol.typed_codec(decode, encode)

`typed_store` as a class decorator: the shape `azure_store(value_codec=...)` takes.

```pycon
>>> import json
>>> codec = typed_codec(json.loads, lambda o: json.dumps(o).encode())
>>> callable(codec)
True
```

* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)

### azuredol.typed_store(decode, encode, \*, base=<class 'azuredol.base.ContainerStore'>)

A `base` (default `ContainerStore`) class with values `decode(bytes)` / `encode(obj) -> bytes`.

Unlike a bare `wrap_kvs(ContainerStore, obj_of_data=..., data_of_obj=...)`, the trailing-slash
sub-store convention keeps working: `store['2026/']` comes back as a sub-store of the
*same typed class*, instead of being fed to `decode` (i2mint/azuredol#4).

### azuredol.walk_container(store, delimiter='/')

Hierarchical walk (`BlobProperties` / `BlobPrefix` nodes) of `store`’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`; unlike `ContainerCollection.walk_ids`, which sees only the leaf’s prefix).

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]

### Modules

| [`base`](_autosummary/azuredol.base.html.md#module-azuredol.base)             | Close-to-metal Mapping stores over Azure Blob Storage.                                              |
|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|
| [`connection`](_autosummary/azuredol.connection.html.md#module-azuredol.connection) | Connection-layer for azuredol.                                                                      |
| [`errors`](_autosummary/azuredol.errors.html.md#module-azuredol.errors)         | Custom exceptions and error-translation decorator for azuredol.                                     |
| [`functions`](_autosummary/azuredol.functions.html.md#module-azuredol.functions)   | Azure functions tools                                                                               |
| [`ops`](_autosummary/azuredol.ops.html.md#module-azuredol.ops)               | Key-taking and scope-wide operations, as free functions over the caller's (possibly wrapped) store. |
| [`recipes`](_autosummary/azuredol.recipes.html.md#module-azuredol.recipes)       | Convenience wrappers and factories for azuredol.                                                    |
| [`testing`](_autosummary/azuredol.testing.html.md#module-azuredol.testing)       | Testing helpers for azuredol — Azurite fixture and convenience builders.                            |


# _autosummary/azuredol.ops.html.md

# 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()`](_autosummary/azuredol.ops.html.md#azuredol.ops.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()`](_autosummary/azuredol.ops.html.md#azuredol.ops.walk) `(store, delimiter)`: `walk_blobs` over the prefix the *caller’s* empty
  key resolves to (leaf prefix + any key codec).
- [`substore()`](_autosummary/azuredol.ops.html.md#azuredol.ops.substore) `(store, key)`: the sub-store `store['2026/']` is meant to be, built
  through the caller’s own store (i2mint/azuredol#6): `substore(store, 'a/')[k]` is always
  `store['a/' + k]`, whatever wrappers (key or value codecs, scopes) sit on `store`.

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()`](_autosummary/azuredol.ops.html.md#azuredol.ops.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`](_autosummary/azuredol.ops.html.md#azuredol.ops.delete_container)(store, name, \*[, force])   | Delete container `name` (a key of `store`); with `force=True` cascade-delete its blobs.   |
|-----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| [`substore`](_autosummary/azuredol.ops.html.md#azuredol.ops.substore)(store, key)                         | The sub-store of `store` under `key` (a key ending in `'/'`), as the caller sees it.      |
| [`walk`](_autosummary/azuredol.ops.html.md#azuredol.ops.walk)(store[, delimiter])                     | Hierarchical walk (`BlobProperties` / `BlobPrefix` nodes) of `store`'s own scope.         |

### azuredol.ops.delete_container(store, name, , force=False)

Delete container `name` (a key of `store`); with `force=True` cascade-delete its blobs.

The deletion is `del store[name]` on the caller’s own store, so a key codec maps
`name`, a read-only wrapper refuses, and a scoped view cannot reach out of scope.

* **Raises:**
  * [**ContainerNotFoundError**](_autosummary/azuredol.html.md#azuredol.ContainerNotFoundError) – if `name` is not a container of `store`
  * [**ContainerNotEmptyError**](_autosummary/azuredol.html.md#azuredol.ContainerNotEmptyError) – if the container has blobs and `force` is false
* **Return type:**
  [`None`](https://docs.python.org/3/builtins/constants.html#None)

### azuredol.ops.substore(store, key)

The sub-store of `store` under `key` (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; prefer `substore` everywhere else.

`substore(store, 'a/')[k]` is `store['a/' + k]` for every wrapper stack on `store` (up to the key limits below).
On a bare `ContainerStore` it is the cheap, server-scoped `store['a/']` (listing only
`a/`’s blobs). On anything wrapped (a `dol` key/value codec or scope, including the
classes `typed_store`/`AzureJsonStore` build) it is a `KeyCodecs.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 under `key`. (`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 keys

gets the view). Attribute lookups on the view fall through to the wrapped store, so
`.prefix` and `.walk_ids()` of a view describe the parent’s scope: use
[`walk()`](_autosummary/azuredol.ops.html.md#azuredol.ops.walk) on it. Needs `dol>=0.3.75` (its prefix view skips out-of-scope keys when
iterating).

* **Parameters:**
  * **store** – a `ContainerReader`/`ContainerStore`, wrapped or not
  * **key** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – a key ending in `'/'`, without a leading `'/'` or an inner `'//'`

### azuredol.ops.walk(store, delimiter='/')

Hierarchical walk (`BlobProperties` / `BlobPrefix` nodes) of `store`’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`; unlike `ContainerCollection.walk_ids`, which sees only the leaf’s prefix).

* **Return type:**
  [`Iterator`](https://docs.python.org/3/library/typing.html#typing.Iterator)[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]


# _autosummary/azuredol.recipes.html.md

# azuredol.recipes

Convenience wrappers and factories for azuredol.

Layer C of the architecture. Built only by composition over Layer B (`base.py`).
See `misc/docs/architecture.md` Layer C.

### Module Attributes

| [`AzureTextStore`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.AzureTextStore)   | Text-typed values (str ↔ bytes via UTF-8).                            |
|-------------------------------------------------------------------|-----------------------------------------------------------------------|
| [`AzureJsonStore`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.AzureJsonStore)   | JSON-typed values (dict/list/scalar ↔ bytes via `json`).              |
| [`AzurePickleStore`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.AzurePickleStore) | Pickle-typed values (Python objects ↔ bytes via `pickle`).            |
| [`AppendBlobStore`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.AppendBlobStore)  | `ContainerStore` whose `__setitem__` creates append blobs by default. |

### Functions

| [`azure_store`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.azure_store)(container, \*[, prefix, ...])   | Build a ready-to-use `ContainerStore` (or codec-wrapped variant) in one call.                   |
|----------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|
| [`typed_codec`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.typed_codec)(decode, encode)                 | `typed_store` as a class decorator: the shape `azure_store(value_codec=...)` takes.             |
| [`typed_store`](_autosummary/azuredol.recipes.html.md#azuredol.recipes.typed_store)(decode, encode, \*[, base])     | A `base` (default `ContainerStore`) class with values `decode(bytes)` / `encode(obj) -> bytes`. |

### azuredol.recipes.AppendBlobStore *= functools.partial(<class 'azuredol.base.ContainerStore'>, blob_type=<BlobType.APPENDBLOB: 'AppendBlob'>)*

`ContainerStore` whose `__setitem__` creates append blobs by default.

Recall the Mapping caveat: `store[k] = v` on an append blob still creates a new
blob (`overwrite=True`) — it does NOT append to an existing blob. For incremental
appends use `BlobHandle(container, blob).append(data)`.

### azuredol.recipes.AzureJsonStore

JSON-typed values (dict/list/scalar ↔ bytes via `json`).

### azuredol.recipes.AzurePickleStore

Pickle-typed values (Python objects ↔ bytes via `pickle`).

### azuredol.recipes.AzureTextStore

Text-typed values (str ↔ bytes via UTF-8).

### azuredol.recipes.azure_store(container, , prefix='', connection=None, credential=None, connection_string=None, account_url=None, account_key=None, create_container_if_missing=False, blob_type=BlobType.BLOCKBLOB, value_codec=None)

Build a ready-to-use `ContainerStore` (or codec-wrapped variant) in one call.

This is the “simple things simple” entry point. For complex configurations construct
`AzureConnection` and `ContainerStore` directly.

* **Parameters:**
  * **container** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Container name.
  * **prefix** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Blob-name prefix to scope all keys.
  * **connection** ([`Union`](https://docs.python.org/3/library/typing.html#typing.Union)[[`AzureConnection`](_autosummary/azuredol.connection.html.md#azuredol.connection.AzureConnection), [`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict), [`None`](https://docs.python.org/3/builtins/constants.html#None)]) – An `AzureConnection` (or anything `AzureConnection.from_anything`
    accepts) to reuse a service client. Mutually exclusive with the explicit
    `credential` / `connection_string` / `account_*` kwargs.
  * **credential** ([`Any`](https://docs.python.org/3/library/typing.html#typing.Any)) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **connection_string** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **account_url** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **account_key** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Forwarded to
    `AzureConnection` when `connection` is None.
  * **create_container_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Create the container on first use if absent.
  * **blob_type** (`BlobType`) – Default blob type for writes.
  * **value_codec** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)]) – A decorator that, given a class, returns a wrapped class. Typically
    `typed_codec(decode, encode)`. A bare `dol.wrap_kvs(...)` breaks the
    trailing-slash sub-store (i2mint/azuredol#4). When None (default), bytes pass
    through.
* **Returns:**
  A `ContainerStore` instance, possibly codec-wrapped.

### azuredol.recipes.typed_codec(decode, encode)

`typed_store` as a class decorator: the shape `azure_store(value_codec=...)` takes.

```pycon
>>> import json
>>> codec = typed_codec(json.loads, lambda o: json.dumps(o).encode())
>>> callable(codec)
True
```

* **Return type:**
  [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)

### azuredol.recipes.typed_store(decode, encode, \*, base=<class 'azuredol.base.ContainerStore'>)

A `base` (default `ContainerStore`) class with values `decode(bytes)` / `encode(obj) -> bytes`.

Unlike a bare `wrap_kvs(ContainerStore, obj_of_data=..., data_of_obj=...)`, the trailing-slash
sub-store convention keeps working: `store['2026/']` comes back as a sub-store of the
*same typed class*, instead of being fed to `decode` (i2mint/azuredol#4).


# _autosummary/azuredol.testing.html.md

# azuredol.testing

Testing helpers for azuredol — Azurite fixture and convenience builders.

The Azurite-backed pieces require Docker to be available locally. Unit tests that don’t
need a live container should prototype with `dict()` per the dol convention.

### Functions

| [`azurite`](_autosummary/azuredol.testing.html.md#azuredol.testing.azurite)([container_name, wait])         | Context manager that ensures Azurite is running for the duration.       |
|------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|
| [`azurite_is_running`](_autosummary/azuredol.testing.html.md#azuredol.testing.azurite_is_running)()                    | Return True if Azurite's blob endpoint (port 10000) is reachable.       |
| [`docker_available`](_autosummary/azuredol.testing.html.md#azuredol.testing.docker_available)()                      | Return True if the `docker` CLI is on PATH.                             |
| [`mk_test_store`](_autosummary/azuredol.testing.html.md#azuredol.testing.mk_test_store)([container, prefix, ...]) | Build a `ContainerStore` pointing at Azurite, ready for ad-hoc testing. |
| [`pytest_azurite_connection`](_autosummary/azuredol.testing.html.md#azuredol.testing.pytest_azurite_connection)()             | Importable as a pytest fixture body. Use it like::.                     |

### azuredol.testing.azurite(container_name=None, , wait=5.0)

Context manager that ensures Azurite is running for the duration.

If Azurite is already up (port 10000 reachable), do nothing on enter/exit.
Otherwise start it via `docker run` and stop it on exit.

* **Parameters:**
  * **container_name** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Docker container name. Random by default.
  * **wait** ([`float`](https://docs.python.org/3/builtins/functions.html#float)) – Max seconds to wait for the blob port to come up.
* **Yields:**
  The Azurite connection string.
* **Raises:**
  [**RuntimeError**](https://docs.python.org/3/builtins/exceptions.html#RuntimeError) – if Docker is unavailable and Azurite is not already running.

### azuredol.testing.azurite_is_running()

Return True if Azurite’s blob endpoint (port 10000) is reachable.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### azuredol.testing.docker_available()

Return True if the `docker` CLI is on PATH.

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

### azuredol.testing.mk_test_store(container=None, , prefix='', create_container_if_missing=True)

Build a `ContainerStore` pointing at Azurite, ready for ad-hoc testing.

Requires Azurite to be running. Use the `azurite(...)` context manager to ensure it.

* **Parameters:**
  * **container** ([`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]) – Container name. Defaults to a random `azuredol-test-*` name.
  * **prefix** ([`str`](https://docs.python.org/3/builtins/stdtypes.html#str)) – Optional key prefix to scope the store.
  * **create_container_if_missing** ([`bool`](https://docs.python.org/3/builtins/functions.html#bool)) – Create the container on first use.
* **Return type:**
  [`ContainerStore`](_autosummary/azuredol.base.html.md#azuredol.base.ContainerStore)

### azuredol.testing.pytest_azurite_connection()

Importable as a pytest fixture body. Use it like:

```default
import pytest
from azuredol.testing import pytest_azurite_connection

@pytest.fixture(scope='session')
def azurite_connection():
    yield from pytest_azurite_connection()
```

Skips the test session if Azurite cannot be started.


# about-this-build.html.md

<!-- generated by epythet -->

# About this build

This documentation was built on **2026-10-30 07:53 UTC** from commit <a href="https://github.com/i2mint/azuredol/commit/5dd2358d588e9baf2ab7ab17aa26d47134486316"><code>5dd2358</code></a> on branch <code>master</code>, for **azuredol 0.1.17** (from <code>pyproject.toml</code>).

#### WARNING
The documentation and the package may be misaligned:

- The documented version (0.1.17) is behind the latest release on PyPI (0.1.18): `pip install azuredol` gives newer code than these docs describe.

## Source

|                     |                                                                                                                                                        |
|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Commit              | <a href="https://github.com/i2mint/azuredol/commit/5dd2358d588e9baf2ab7ab17aa26d47134486316"><code>5dd2358d588e9baf2ab7ab17aa26d47134486316</code></a> |
| Branch              | <code>master</code>                                                                                                                                    |
| Tags at this commit | none                                                                                                                                                   |
| Working tree        | clean                                                                                                                                                  |
| Remote              | <code>https://github.com/i2mint/azuredol</code>                                                                                                        |

## Continuous integration

|              |                                                                                            |
|--------------|--------------------------------------------------------------------------------------------|
| Repository   | <code>i2mint/azuredol</code>                                                               |
| Run          | <a href="https://github.com/i2mint/azuredol/actions/runs/41022754540">41022754540</a>      |
| Ref          | <code>refs/heads/master</code>                                                             |
| Event commit | <code>5dd2358d588e9baf2ab7ab17aa26d47134486316</code> (in the history of the built commit) |

## Tools

|          |         |
|----------|---------|
| epythet  | 0.2.22  |
| Sphinx   | 9.1.1   |
| docutils | 0.22.4  |
| Python   | 3.12.15 |

## Configuration as resolved

|               |                                                                  |
|---------------|------------------------------------------------------------------|
| theme         | <code>auto</code> (Sphinx theme <code>shibuya</code>)            |
| accent        | <code>#466400</code>                                             |
| api_generator | <code>autosummary</code>                                         |
| ignore        | <code>tests/</code>, <code>scrap/</code>, <code>examples/</code> |
| agent_outputs | <code>true</code>                                                |
| aggregates    | <code>md</code>                                                  |
| ai_artifacts  | <code>true</code>                                                |

## Package on PyPI

Latest release: <a href="https://pypi.org/project/azuredol/0.1.18/">0.1.18</a>, newer than the documented version (0.1.17).

## Reproduce

```bash
git clone https://github.com/i2mint/azuredol && cd azuredol
git checkout 5dd2358d588e9baf2ab7ab17aa26d47134486316
pip install "epythet==0.2.22"
epythet quickstart . --ignore tests/ scrap/ examples/
```

The same data, for machines: <a href="build_info.json"><code>build_info.json</code></a> (schema version 1).


# ai-agents.html.md

<!-- generated by epythet -->

# For AI agents

`azuredol` ships artifacts for coding agents alongside its code. This page lists
them, says where each lives in the repository, and points at the
machine-readable copies of this documentation.

## Skills

Skills are folders holding a `SKILL.md` (the [Agent Skills](https://agentskills.io) format): a description that tells an agent when to use it and a body with the procedure. Install one into your agent with `gh skill` (any host: `--agent claude-code`, `copilot`, `cursor`, `codex`, `gemini`), or use the copy bundled in the wheel.

### `azuredol`

Use when developing, reviewing, or extending the azuredol package (Azure Blob Storage as dol Mapping interfaces). Triggers on edits under i/azuredol/, on imports of `azuredol`, when adding new blob-store wrappers, value codecs, or credential paths, when writing tests against Azurite, when reviewing PRs against azuredol, and when designing sibling packages like azuredatalakedol.

Source: [`.claude/skills/azuredol`](https://github.com/i2mint/azuredol/tree/HEAD/.claude/skills/azuredol).

## Machine-readable documentation

This site publishes the same documentation in forms that fit an agent’s context window:

- [`llms.txt`](https://i2mint.github.io/azuredol/llms.txt): an index of every page with a one-line description ([llms.txt](https://llmstxt.org) format)
- [`azuredol.md`](https://i2mint.github.io/azuredol/azuredol.md): the whole documentation as one Markdown file
- `<page>.html.md`: a rendered Markdown twin of every page, advertised from each page’s `<head>` with `<link rel="alternate" type="text/markdown">`
- [`objects.inv`](https://i2mint.github.io/azuredol/objects.inv): the Sphinx inventory: a symbol-to-URL index (`sphobjinv convert plain objects.inv -`)


# api.html.md

# API reference

| [`azuredol`](_autosummary/azuredol.html.md#module-azuredol)   | Access Azure Blob Storage through a Mapping interface.   |
|-----------------------------------------------------------------------------|----------------------------------------------------------|


