# Batches and Arenas

> UStore for Python

### Receivers & Deferred Calls

A receiver carries what every argument struct of the C ABI puts before its inputs: the view, the executor and the completion.
A `Database`, `Transaction` or `Snapshot` runs its calls on the calling thread, `on(executor)` answers a `ustore.On` whose calls block on that executor, and `deferred(executor)` answers a `ustore.DeferredOn` whose calls submit there and answer a `ustore.Deferred`.
The receiver's type alone chooses the completion, so all three offer the same verbs with the same arguments, and receivers never change after they are made, so threads share them freely.
Constructors address no database yet, so no receiver offers them: `open_ram`, `open_rocksdb`, `view_rocksdb` and `open_leveldb` take an `executor=` keyword and block on it, as they block on the calling thread without one.
In a coroutine, `await` a deferred call; anywhere else, `wait()` blocks the thread with its state detached:

```python
import asyncio

async def main(directory, keys, key, payloads):
    with ustore.Executor.for_ram(8) as executor:
        database = ustore.Database.open_rocksdb(directory, executor=executor)  # blocks on the executor
        arena = ustore.Arena(executor)                       # placed where the executor computes
        values = database.on(executor).read(keys, arena, collection="movies")  # blocking, on the calling thread
        poster = database.on(executor)["movies"].blobs[key]  # shorthand, copied out of a one-off arena

        later = database.deferred(executor)
        reading = later.read(keys, arena, collection="movies")  # ustore.Deferred, submitted now, holding the arena
        reading.status                                       # ustore.Status.DEFERRED until final
        values = await reading                               # or: reading.wait()
        poster = await later["movies"].blobs[key]            # one call at a time; a missing key raises KeyError

        transaction = database.transaction(ustore.Watch.KEYS)
        await transaction.deferred(executor).write(keys, payloads, collection="movies")
        peek = transaction.unwatched().read(keys, arena, collection="movies")  # recorded for no conflict
        read_stamp = transaction.stage()
        commit_stamp = await transaction.deferred(executor).commit(ustore.Durability.FLUSHED)
        transaction.close()

        with database.snapshot() as snapshot:
            old = snapshot.read(keys, arena, collection="movies")
            old_poster = snapshot["movies"].blobs[key]
            snapshot.read_stamp                              # sees every commit stamp at or below it
        executor.drain(ustore.Mood.SPINNING)
        database.close()
```

`await` hands `wait()` to `loop.run_in_executor`, so the thread it blocks belongs to asyncio, and `status` polls through `ustore_outcome_status` without waiting.
Arguments the binding refuses raise at the call, while the engine's refusals raise at `await` or `wait()`, as many times as they are asked.
A collection name resolves on the calling thread when the call is made, and a mapping view creates a missing collection there too, so a deferred call never waits behind earlier ones to learn its collection.
Python's `in` must answer a bool, an assignment and `del` discard what they answer, and the table view and most graph methods chain several calls, so through a deferred view they raise `TypeError` naming the verb to call instead, such as `contains` for `in`.

```python
async def fan_out(database, executors, keys, key, sources, targets):
    first, second, third = (database.deferred(executor) for executor in executors)  # one call per executor at once
    types = [ustore.FieldType.STRING, ustore.FieldType.I64]
    gathering = first.docs_gather(keys, ["name", "tweets"], types, ustore.Arena(executors[0]), collection="people")
    linking = second.graph_write_edges(sources, targets, collection="follows")
    present = third.contains(key, collection="movies")       # Deferred[bool], since `key in ...` must answer a bool
    gathered, linked, found = await gathering, await linking, await present
    document = await first["people"].docs[key]               # the parsed document
    edges = await second["follows"].graph.read_edges(keys)   # Neighborhoods over a one-off arena
    return gathered, linked, found, document, edges
```

A `Deferred` keeps the outcome, the inputs the library borrows, the output slots and its arena, since submission copies the argument struct and lets it go.
It holds its arena as a blocking call does, until it is waited on or dropped, and dropping an unfinished one waits for its call.
The collector frees a cycle through a finished one, and leaves a cycle through an unfinished one for a later collection, never clearing what the library still reads.
An executor, a transaction and an arena each serve one call at a time, so a second call while a deferred one runs raises `ContendedError` once awaited.
Closing a database, transaction or snapshot, or dropping an arena, waits in C for the deferred calls naming it.

### Executors

An executor owns host threads, and a database owns its data, so one executor serves any number of databases.
`Executor.for_ram(threads=0, *, memory_domains=None)` spawns the threads of the RAM, RocksDB and LevelDB engines near the NUMA nodes `memory_domains` names, every node the process may allocate on for `None`.
It keeps the scratch of each thread on that thread's node and every arena it makes on the first node named, and refuses a node no machine carries with `InvalidArgumentError`.
Zero threads take 7/8 of the cores those nodes carry, leaving the rest to blocking calls, which run on their callers' threads, and to the engines' own background flushes and compactions:

```python
executor = ustore.Executor.for_ram(8, memory_domains=[0])
executor.drain(ustore.Mood.SPINNING)                    # waits, then keeps idle threads hot
arena = ustore.Arena(executor)                          # outputs of calls on this executor land here
```

`Executor.on_pool(pool, /, *, memory_domains=None)` borrows a ForkUnion `fu_pool_t` another library already runs, given as the integer address `ctypes` or `cffi` hands over, so one process keeps one set of threads; the pool must outlive the executor.
`Executor.for_nvme(threads=0, *, transport=Transport.AUTOMATIC, **sizes)` makes the I/O rings of the NVMe engine, and tells every database `open_nvme` opens on it how to move bytes: the transport, the channels and their buffers, each size keyword naming a field of `ustore_nvme_options_t`.
`Executor.for_vram(device, *, scratch_limit=0, gds=Gds.AUTOMATIC)` drives one CUDA device through one stream every call queues on, whose merges `Database.open_nvme(..., compactions=...)` takes, and raises `UnsupportedError` in a build without CUDA.

An executor serves one call at a time: a call submitted while another holds it finishes with `Status.CONTENDED` and raises `ContendedError` once awaited.
A deferred call runs on the executor's first thread in the caller's place, so polling `status` alone finishes it, and progress callbacks run on the executor's threads, taking the GIL as they enter Python.
Used as a context manager, an executor waits for its calls and closes on exit, after which a receiver naming it raises `UninitializedError`.
Calling `ustore.Executor()` raises a `TypeError` naming the factories, since what an executor spawns cannot be derived from nothing.

The extension declares `Py_MOD_GIL_NOT_USED`, so free-threaded builds run without the interpreter lock.
Critical sections fence the few fields the binding mutates: an arena's exports and generation, a closed executor's handle, a cursor's handle while a pull holds it, a deferred call's answer, and the identifier a collection resolved.
A ragged input that is not already a tape is borrowed into views the call holds before it is submitted, so the accessor the executor's threads call reads those views alone, never a Python container the caller may change meanwhile.

### Progress & Cancellation

`scan`, `scan_batch`, a cursor's `next`, `compact` and a snapshot's `save` take `progress=`, a callable of the units the call finished and the units it finishes in all.
The units are the verb's own: scans for a scan, one pull for a cursor, bytes of keys and values for a save, and bytes or collections for a compaction, as the engine measures them.
The library calls it from whichever thread runs the call, never two at once and never after the call is final, so a deferred call reports from the executor's threads, and the binding attaches the interpreter there itself, taking the GIL where there is one.
An answer of `None` or a truthy one carries on, and any other falsy answer cancels: the call unwinds, publishes nothing and raises `CancelledError`.
A cancelled save removes what it wrote, a cancelled pull leaves its cursor where it was, and a cancelled compaction stops between collections, keeping what it compacted.
An exception inside the callable cancels the call the same way, and re-raises from it in place of `CancelledError`, or from `wait()` and `await` for a deferred call.

```python
stop = threading.Event()

def report(finished: int, total: int) -> bool:
    print(f"{finished} of {total}")
    return not stop.is_set()

database.compact(progress=report)
with database.snapshot() as snapshot:
    snapshot.save(directory, progress=report)           # reports on the calling thread
    snapshot.deferred(executor).save(elsewhere, progress=report).wait()  # and here from the executor's
```

### Arenas

Every output whose length only the call knows, such as values, keys, columns, edges, degrees, bounds and names, lands in a `ustore.Arena` you pass, and the verb answers a view over it without copying.
`ustore.Arena(executor)` places it where that executor computes, decided once, and `ustore.Arena()` makes host pages for calls on the calling thread.
Each call rewinds its arena, so the previous call's views go stale and a steady loop allocates once.
To keep a result past the next call, or to read one while making the next, pass that call another arena.
An arena serves one call at a time, so each deferred call needs its own.
A NumPy array or `memoryview` over an output pins its arena as a `memoryview` pins a `bytearray`, so the next call naming that arena raises `ContendedError` until the export is released.
A stale result raises `UninitializedError` when indexed, exported or asked for its `lengths`, `counts` or `degrees`.
`Values`, `Keys`, `Page` and `Neighborhoods` export DLPack too, so `numpy.from_dlpack(keys)` and `torch.from_dlpack(keys)` read the arena in place, and `__dlpack_device__` reports where the library placed it.
Python reads every answer on the host, so a verb handed an arena in device memory raises `DeviceError` before it runs.
A batch of keys is taken from `__dlpack__` before the buffer protocol: packed 16-byte keys pass as they are from host, CUDA, ROCm or managed memory, and 64-bit integers convert where the host reads them.

```python
arena = ustore.Arena()
for batch in batches:
    values = database.read(batch, arena, collection="movies")  # rewinds: the last batch's values are gone
    total += sum(length or 0 for length in values.lengths)
held = database.read(keys, arena, collection="movies")[0]  # a memoryview, pinning the arena
database.read(keys, ustore.Arena(), collection="movies")  # another arena serves the next call meanwhile
held.release()                                          # and this one serves calls again
```

`read` and `docs_read` answer `ustore.Values`, `scan`, `scan_batch`, `sample` and `sample_batch` answer `ustore.Keys`, a cursor's `next` answers a `ustore.Page`, `docs_gather` answers `ustore.Columns`, and `graph_read_edges` answers `ustore.Neighborhoods`.
`measure`, `docs_gist`, `graph_degrees`, `collection_find`, `collection_list` and `collection_names` take an arena too, and copy their small answers out of it.

Shorthand has no place for an arena, so it makes a one-off arena through `ustore_arena_init` for every call, copies what it read into Python objects and frees the arena with the call.
That covers `get`, `contains`, `key in view[name].blobs`, `view[name].blobs[key]`, `.docs[key]` and `.docs_json[key]`, `Collection.sample`, and the NetworkX and Pandas views.
Each such call pays for an arena and a copy, so a loop reaches for the verbs with an arena of its own instead.

`import ustore`

`from ustore import Executor, Deferred, GPUDevice, …`

## Mood

What an executor's threads do once it next goes idle, valued as `ustore_mood_t`.

```python
class Mood(IntEnum)
```

- `PARKED` = `0`
- `SPINNING` = `1`

## CPUClass

The CPU generation a database confines its waits, atomics and string kernels to, valued as `ustore_cpu_class_t`.

```python
class CPUClass(IntEnum)
```

- `AUTOMATIC` = `0`
- `SERIAL` = `1`
- `INTEL_HASWELL` = `2`
- `INTEL_SIERRA` = `3`
- `INTEL_SKYLAKE` = `4`
- `INTEL_ICELAKE` = `5`
- `AWS_G2` = `6`
- `APPLE_M2` = `7`
- `AWS_G5` = `8`
- `ALIBABA_C930` = `9`
- `MONOVERSIONED` = `10`

## Transport

How the NVMe engine moves bytes between its files and memory, valued as `ustore_transport_t`.

```python
class Transport(IntEnum)
```

- `AUTOMATIC` = `0`
- `BLOCKING` = `1`
- `LINUX_URING` = `2`
- `LINUX_AIO` = `3`
- `LINUX_SPDK` = `4`

## Gds

How an executor of [`Executor.for_vram`](#for_vram) moves bytes between the drives and its device, valued as `ustore_gds_t`.

```python
class Gds(IntEnum)
```

- `AUTOMATIC` = `0`
- `DIRECT` = `1`
- `COMPATIBILITY` = `2`

## GPUVendor

The vendor whose runtime drives a GPU, valued as `ustore_gpu_vendor_t`.

```python
class GPUVendor(IntEnum)
```

- `NVIDIA` = `1`
- `AMD` = `2`

## GPUClass

The generation of a GPU, valued as `ustore_gpu_class_t`.

```python
class GPUClass(IntEnum)
```

- `NVIDIA_AMPERE` = `1`
- `NVIDIA_ADA` = `2`
- `NVIDIA_HOPPER` = `3`
- `NVIDIA_BLACKWELL` = `4`
- `NVIDIA_BLACKWELLRTX` = `5`
- `AMD_CDNA3` = `6`
- `AMD_CDNA4` = `7`
- `AMD_CDNA5` = `8`

## Arena

The memory every output whose length scales with a call lands in, rewound by the next call handed it.

```python
class Arena
```

Every verb whose outputs scale with the call takes one as its last positional argument and answers results
viewing it. A buffer exported over its outputs pins it, so the next call naming it raises [`ContendedError`](https://www.unum.cloud/docs/ustore/python/errors.md#ContendedError) until
the buffer is released, and a result read after a later call rewound it raises [`UninitializedError`](https://www.unum.cloud/docs/ustore/python/errors.md#UninitializedError). A deferred
call holds it until it is waited on or dropped.

## Progress

Called with the units a call finished and the units it finishes in all, from whichever thread runs it but never two at once; None or a truthy answer carries on, any other falsy one cancels, and a raise cancels and re-raises.

```python
type Progress = Callable[[int, int], bool | None]
```

## Executor

The threads that run calls, shared by any number of databases.

```python
class Executor
```

## for_ram

Host threads for the RAM, RocksDB and LevelDB engines near `memory_domains`, every NUMA node for None, where zero threads take 7/8 of the cores those nodes carry.

```python
@classmethod
def for_ram(
    threads: int = 0,
    *,
    memory_domains: Sequence[int] | None = None,
    deferred_limit: int = 0,
) -> Self
```

Calls `ustore_executor_for_ram`.

## on_pool

The threads of a ForkUnion `fu_pool_t` at address `pool`, which another library runs and which must outlive the executor.

```python
@classmethod
def on_pool(
    pool: int,
    /,
    *,
    memory_domains: Sequence[int] | None = None,
    deferred_limit: int = 0,
) -> Self
```

Calls `ustore_executor_on_pool`.

## for_nvme

Threads each driving an I/O ring for the NVMe engine, telling every database [`Database.open_nvme`](https://www.unum.cloud/docs/ustore/python/quickstart.md#open_nvme) opens on it how to move bytes, where every zero size keeps the engine's default.

```python
@classmethod
def for_nvme(
    threads: int = 0,
    *,
    transport: Transport = Transport.AUTOMATIC,
    deferred_limit: int = 0,
    shared_io_channels: int = 0,
    queue_depth: int = 0,
    request_buffer_bytes: int = 0,
    request_buffers_count: int = 0,
    stream_buffer_bytes: int = 0,
    stream_buffers_count: int = 0,
) -> Self
```

Calls `ustore_executor_for_nvme`.

## for_vram

One stream on `device`, a [`GPUDevice.ordinal`](#ordinal) of either vendor, every call queues on, fed by one host thread, which [`Database.open_nvme`](https://www.unum.cloud/docs/ustore/python/quickstart.md#open_nvme) takes as its `compactions` on an NVIDIA device, refused with [`DeviceError`](https://www.unum.cloud/docs/ustore/python/errors.md#DeviceError) for an ordinal no device carries; zero `scratch_limit` lets scratch grow as calls ask.

```python
@classmethod
def for_vram(
    device: int,
    *,
    scratch_limit: int = 0,
    gds: Gds = Gds.AUTOMATIC,
    deferred_limit: int = 0,
) -> Self
```

Calls `ustore_executor_for_vram`.

## drain

Waits for every call submitted before the drain began, setting what the threads do once idle.

```python
def drain(mood: Mood = Mood.PARKED) -> None
```

## close

Waits for every submitted call, then frees the threads.

```python
def close() -> None
```

## Deferred

A call a deferred view submitted, which answers once it finishes, holding its arena until then.

```python
class Deferred[T]
```

## __class_getitem__

Names what `wait()` answers, as `Deferred[Values]`.

```python
def __class_getitem__(item: Any, /) -> GenericAlias
```

## wait

Blocks the thread until the call finishes, answering or raising what the blocking verb would.

```python
def wait() -> T
```

## __await__

Runs `wait()` on the running event loop's default executor, suspending the task meanwhile.

```python
def __await__() -> Generator[Any, None, T]
```

## status

The status of the call, [`Status.DEFERRED`](https://www.unum.cloud/docs/ustore/python/errors.md#DEFERRED) until it finishes, polled through `ustore_outcome_status`.

```python
status: Status
```

## GPUDevice

One GPU this process can drive, as `gpu_devices()` lists it.

```python
class GPUDevice(structseq[Any], tuple[int, GPUVendor, int, GPUClass, int, int, str])
```

## ordinal

The ordinal [`Executor.for_vram`](#for_vram) names the device by, its position in `gpu_devices()`.

```python
ordinal: int
```

## vendor

The vendor whose runtime drives the device.

```python
vendor: GPUVendor
```

## vendor_ordinal

The device's ordinal in its vendor's runtime, as `nvidia-smi` or `rocm-smi` list it.

```python
vendor_ordinal: int
```

## gpu_class

The class of the device.

```python
gpu_class: GPUClass
```

## compute_units

Streaming multiprocessors or compute units.

```python
compute_units: int
```

## memory_bytes

Device memory in bytes.

```python
memory_bytes: int
```

## name

The vendor's own name for the device.

```python
name: str
```

## On

What a database, transaction or snapshot addresses, with the executor its calls block on.

```python
class On
```

## watched

A view of the same transaction whose calls record the keys they touch for conflicts.

```python
def watched() -> On
```

## unwatched

A view of the same transaction whose calls record nothing.

```python
def unwatched() -> On
```

## ingest_arrow

Lands every batch of an Arrow stream as one commit of its own at the head, answering the rows landed; a view of a transaction raises TypeError.

```python
def ingest_arrow(
    source: ArrowSource,
    *,
    collection: CollectionLike,
    order: IngestOrder = 'sorted',
    durability: Durability | None = None,
) -> int
```

## commit

Commits the transaction on the executor, answering the commit stamp.

```python
def commit(durability: Durability = Durability.BUFFERED) -> int
```

## stage

Stages the transaction on the executor, answering the read stamp.

```python
def stage() -> int
```

## save

Saves the snapshot on the executor, refusing a view of anything else.

```python
def save(
    path: PathLikeOrStr,
    /,
    *,
    progress: Progress | None = None,
) -> None
```

## clear

Clears the database on the executor, refusing a view of a transaction or a snapshot.

```python
def clear(mode: DropMode, /) -> None
```

## compact

Compacts the database on the executor, refusing a view of a transaction or a snapshot.

```python
def compact(*, progress: Progress | None = None) -> None
```

## flush

Flushes the database on the executor, refusing a view of a transaction or a snapshot.

```python
def flush() -> None
```

## describe

Describes the database on the executor, refusing a view of a transaction or a snapshot.

```python
def describe() -> Description
```

## collection_find

The collection ID the name addresses, at the snapshot of a snapshot and at the head otherwise.

```python
def collection_find(name: str, arena: Arena, /) -> UUID
```

## collection_list

The IDs of every collection, at the snapshot of a snapshot and at the head otherwise.

```python
def collection_list(arena: Arena, /) -> tuple[UUID, ...]
```

## database

```python
database: Database
```

## executor

The executor the view's calls run on, where an arena for them belongs, or None for the calling thread.

```python
executor: Executor | None
```

## write

Upserts a batch of binary values in one call.

```python
def write(
    keys: KeysLike,
    values: Sequence[ValueLike] | ValueLike | TapeLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

Every value is borrowed for the length of the call rather than copied, so a memory-mapped buffer reaches the engine untouched.

Raises:
TypeError: A value is None or exports no buffer.
Error: Whatever the engine reported.

- `keys`: The keys to write.
- `values`: One value per key, a tape of
them, or a single bytes-like object broadcast to every key. A tape is an Arrow
`binary`, `large_binary`, `string` or `large_string` array, such as [`Values`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#Values), or
a `(data, offsets)` tuple of buffers with unsigned 32-bit or 64-bit offsets, and
passes without a copy. None is refused, since [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) removes keys.
- `collection`: The collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## set

Upserts one binary value.

```python
def set(
    key: KeyLike,
    value: ValueLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

Raises:
TypeError: The value is None or exports no buffer.

- `key`: The key to write.
- `value`: The bytes to store, borrowed rather than copied.
- `collection`: The collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## remove

Removes keys with their values, or every key of a range up to its key in `ends`.

```python
def remove(
    keys: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    ends: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## docs_write

Writes a batch of JSON documents, or one field inside each of them.

```python
def docs_write(
    keys: KeysLike | None,
    documents: Sequence[DocumentLike] | DocumentLike | TapeLike,
    *,
    collection: CollectionLike,
    field: str | None = None,
    modification: Modification = Modification.UPSERT,
    type: FieldType = FieldType.JSON,
    id_field: str | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

Every document is borrowed for the length of the call rather than copied.

Raises:
TypeError: A document is None.
MalformedError: A document does not parse, or its `id_field` holds no integer.
NotFoundError: A field is written inside a document that does not exist.
AlreadyExistsError: An insert names a document that already exists.

- `keys`: The keys to write; None reads every key from
`id_field` of its document.
- `documents`: One
document per key, a tape of them, or one document broadcast to every key. Text,
bytes and a tape, as [`write`](https://www.unum.cloud/docs/ustore/python/transactions.md#write) takes one, are JSON already, while a dict, a list or a
number inside a sequence is serialized. None is refused: [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) removes whole
documents, and a merge with a JSON null removes a field. Under a fixed-width `type`,
a contiguous buffer of one scalar per key is a column, which reaches the store
without being printed as JSON and parsed back.
- `collection`: The collection, by identifier or by name.
- `field`: A top-level key or a JSON Pointer such as '/user/name' to
write inside every document; None writes whole documents.
- `modification`: An upsert, update or insert, an RFC 6902
[`Modification.PATCH`](https://www.unum.cloud/docs/ustore/python/documents.md#PATCH) or an RFC 7386 [`Modification.MERGE`](https://www.unum.cloud/docs/ustore/python/documents.md#MERGE).
- `type`: How every document is spelled: [`FieldType.JSON`](https://www.unum.cloud/docs/ustore/python/platform-notes.md#JSON),
[`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) for a plain string, [`FieldType.NULL`](https://www.unum.cloud/docs/ustore/python/documents.md#NULL), or the raw bytes of
[`FieldType.BOOL`](https://www.unum.cloud/docs/ustore/python/documents.md#BOOL), [`FieldType.F64`](https://www.unum.cloud/docs/ustore/python/documents.md#F64), [`FieldType.F32`](https://www.unum.cloud/docs/ustore/python/documents.md#F32), [`FieldType.I64`](https://www.unum.cloud/docs/ustore/python/documents.md#I64) through
[`FieldType.U8`](https://www.unum.cloud/docs/ustore/python/documents.md#U8).
- `id_field`: The field holding every key when [`keys`](https://www.unum.cloud/docs/ustore/python/scans.md#keys) is None.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## docs_remove

Removes whole documents, or every document of a range up to its key in `ends`.

```python
def docs_remove(
    keys: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    ends: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## strings_*_write

Upserts strings and the keys they map onto, one key per string.

```python
def strings__write(
    strings: TextsLike,
    keys: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## strings_*_remove

Removes strings with their keys.

```python
def strings__remove(
    strings: TextsLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## pages_*_import

Replaces whole pages with parsed markup, minting a key for every element.

```python
def pages__import(
    keys: KeyLike | KeysLike,
    markup: TextsLike,
    *,
    collection: CollectionLike,
    encoding: PageEncoding = PageEncoding.XML,
    durability: Durability = Durability.BUFFERED,
    progress: Progress | None = None,
) -> None
```

## import_arrow

Writes every batch of an Arrow stream through the writes of the collection's modality, answering the rows written.

```python
def import_arrow(
    source: ArrowSource,
    *,
    collection: CollectionLike,
    durability: Durability | None = None,
) -> int
```

## pages_*_insert

Parses fragments into elements under `parents` after `anchors`, the root and the front where None, answering the key every element ended up with, given in `elements` or minted.

```python
def pages__insert(
    keys: KeyLike | KeysLike,
    fragments: TextsLike,
    *,
    collection: CollectionLike,
    elements: KeyLike | KeysLike | None = None,
    parents: KeyLike | KeysLike | None = None,
    anchors: KeyLike | KeysLike | None = None,
    encoding: PageEncoding = PageEncoding.XML,
    durability: Durability = Durability.BUFFERED,
) -> tuple[UUID, ...]
```

## pages_*_remove

Removes elements with their subtrees, where the page key or no elements removes the whole page, and every page of a range up to its key in `ends`.

```python
def pages__remove(
    keys: KeyLike | KeysLike,
    elements: KeyLike | KeysLike | None = None,
    *,
    collection: CollectionLike,
    ends: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## pages_*_move

Moves elements with their subtrees under `parents` after `anchors`, keeping their keys.

```python
def pages__move(
    keys: KeyLike | KeysLike,
    elements: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    parents: KeyLike | KeysLike | None = None,
    anchors: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## pages_*_splice

Replaces [`lengths`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#lengths) bytes of the text of every element from `starts` on with `texts`.

```python
def pages__splice(
    keys: KeyLike | KeysLike,
    elements: KeyLike | KeysLike,
    starts: LengthsLike,
    lengths: LengthsLike,
    texts: TextsLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## pages_set_*_set_attributes

Sets one attribute of an element per task, adding the ones it lacks.

```python
def pages_set__set_attributes(
    keys: KeyLike | KeysLike,
    elements: KeyLike | KeysLike,
    fields: TextsLike,
    values: TextsLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## pages_remove_*_remove_attributes

Removes one attribute of an element per task.

```python
def pages_remove__remove_attributes(
    keys: KeyLike | KeysLike,
    elements: KeyLike | KeysLike,
    fields: TextsLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

## graph_write_edges

Inserts a batch of edges, creating the vertices they connect.

```python
def graph_write_edges(
    sources: KeysLike,
    targets: KeysLike,
    *,
    edges: KeysLike | None = None,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

An edge already present is kept, so writing the same batch twice changes nothing.

- `sources`: The vertex every edge leaves.
- `targets`: The vertex every edge enters.
- `edges`: The identifier of every edge, which tells
apart several edges between one pair; None gives every edge [`edge_id_default`](https://www.unum.cloud/docs/ustore/python/graphs.md#edge_id_default).
- `collection`: The graph collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_remove_edges

Removes a batch of edges and keeps the vertices they connected, even once isolated.

```python
def graph_remove_edges(
    sources: KeysLike,
    targets: KeysLike,
    *,
    edges: KeysLike | None = None,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

- `sources`: The vertex every edge leaves.
- `targets`: The vertex every edge enters.
- `edges`: The identifier of every edge; None removes
the edges that were given [`edge_id_default`](https://www.unum.cloud/docs/ustore/python/graphs.md#edge_id_default).
- `collection`: The graph collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_write_vertices

Inserts a batch of vertices without edges, keeping those already present.

```python
def graph_write_vertices(
    vertices: KeysLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> None
```

- `vertices`: The vertices to insert.
- `collection`: The graph collection, by identifier or name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_remove_vertices

Removes a batch of vertices together with every edge they take part in.

```python
def graph_remove_vertices(
    vertices: KeysLike,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
    ends: KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> None
```

With `ends`, every vertex starts a range removed up to its end, as [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) takes them.

- `vertices`: The vertices to remove, or the first vertex of
every range.
- `role`: The role every vertex plays, which only a joining graph between
two collections needs; [`Role.ANY`](https://www.unum.cloud/docs/ustore/python/graphs.md#ANY) otherwise.
- `collection`: The graph collection, by identifier or by name.
- `ends`: The vertex every range stops before, one
per vertex.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## __getitem__

The collection [`name`](#name) addresses.

```python
def __getitem__(name: str) -> Collection
```

## read

Reads a batch of binary values in one call, which no sequence of single reads matches for throughput.

```python
def read(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    offset: int = 0,
    limit: int | None = None,
) -> Values
```

Nothing is copied: the tape sits in the arena, and indexing the answer gives a memoryview over the stored bytes, or None for an absent key.

Returns:
Values: One entry per key, in the order they were asked for.
Raises:
ContendedError: The arena serves another call or exports a buffer.
Error: Whatever the engine reported.

- `keys`: The keys to read, as a sequence, a contiguous
buffer of 16-byte keys, which is read in place, or one of 64-bit integers.
- `arena`: Where the tape lands, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `offset`: Byte of every value the read starts at, where an offset
past the end reads empty.
- `limit`: Most bytes of every value to read from the offset, or None
for the rest of it.

## get

Copies one value out of a one-off arena, which [`read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#read) with an arena of yours avoids.

```python
def get(
    key: KeyLike,
    *,
    collection: CollectionLike,
) -> bytes | None
```

## contains

Reads one presence into a one-off arena.

```python
def contains(
    key: KeyLike,
    *,
    collection: CollectionLike,
) -> bool
```

## cursor

A walk over the keys of one collection from `start`, reading nothing until its first pull, whose every pull blocks as this receiver's calls do.

```python
def cursor(
    start: KeyLike | None = None,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    patterns: Sequence[str | bytes] | None = None,
    pattern_kind: PatternKind = PatternKind.REGEX,
    sensitivity: CaseSensitivity = CaseSensitivity.CASED,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Cursor
```

Calls `ustore_blobs_cursor_init`.

## docs_cursor

A walk over documents, keeping those `filter` matches.

```python
def docs_cursor(
    start: KeyLike | None = None,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    filter: str | bytes | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Cursor
```

Calls `ustore_docs_cursor_init`.

## pages_cursor

A walk over pages, keeping those holding a node of the XPath `filter`, whose pulls render whole pages into `outputs_encoding` when asked.

```python
def pages_cursor(
    start: KeyLike | None = None,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    filter: str | bytes | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
    outputs_encoding: PageEncoding = PageEncoding.XML,
) -> Cursor
```

Calls `ustore_pages_cursor_init`.

## graph_vertices_cursor

A walk over the vertices of one graph collection.

```python
def graph_vertices_cursor(
    start: KeyLike | None = None,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Cursor
```

Calls `ustore_graph_vertices_cursor_init`.

## scan

Lists up to `wanted` keys from `start` towards `end`.

```python
def scan(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    patterns: Sequence[str | bytes] | None = None,
    pattern_kind: PatternKind = PatternKind.REGEX,
    sensitivity: CaseSensitivity = CaseSensitivity.CASED,
    weights: Sequence[float] | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Keys
```

Values are not exported, so a read follows the scan, or a `cursor()` walks a collection with its values instead.

Returns:
Keys: One run of keys, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first key the scan may return, or None for the first
key in its direction.
- `wanted`: Most keys the scan returns.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `end`: The key the scan stops before, or None for no bound.
- `direction`: [`ScanDirection.DESCENDING`](https://www.unum.cloud/docs/ustore/python/scans.md#DESCENDING) walks down from
`start`, largest key first.
- `mode`: [`ScanMode.UNORDERED`](https://www.unum.cloud/docs/ustore/python/scans.md#UNORDERED) lets keys come out of order,
removed or repeated, to speed up the read after the scan; no engine uses it yet.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## scan_batch

One scan per start, reporting the scans finished to `progress`.

```python
def scan_batch(
    starts: KeysLike,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    ends: KeysLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    patterns: Sequence[str | bytes] | None = None,
    pattern_kind: PatternKind = PatternKind.REGEX,
    sensitivity: CaseSensitivity = CaseSensitivity.CASED,
    weights: Sequence[float] | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Keys
```

## sample

Draws keys uniformly at random from one collection, which is how a workload picks entries it has no list of.

```python
def sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Keys
```

Returns:
Keys: One run of keys, in no particular order.

- `wanted`: Most keys to draw.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The collection, by identifier or by name.

## sample_batch

`count` samples of up to `wanted` keys each, all drawn from the one collection named.

```python
def sample_batch(
    count: int,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Keys
```

## measure

Estimates what a key range holds without walking it, so the answers are bounds rather than counts.

```python
def measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Measurement
```

Returns:
Measurement: The lower and upper bounds on the entries, the bytes of their values,
and the space they take on disk.

- `start`: First key of the range, or None for the first key in the
direction.
- `end`: The key the range stops before, or None for no bound.
- `arena`: Where the bounds land before they are copied out, rewound by this
call.
- `collection`: The collection, by identifier or by name.
- `direction`: [`ScanDirection.DESCENDING`](https://www.unum.cloud/docs/ustore/python/scans.md#DESCENDING) ranges down from
`start`.

## docs_read

Reads whole documents, or one field of each, as JSON text or as printed strings.

```python
def docs_read(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    field: str | None = None,
    outputs_type: FieldType = FieldType.JSON,
) -> Values
```

Whole documents read as JSON pass straight through from the engine, so nothing is parsed.

Returns:
Values: One entry per key, None where the document or the field is absent.

- `keys`: The keys to read.
- `arena`: Where the tape lands, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `field`: A top-level key or a JSON Pointer to read inside every
document; None reads whole documents.
- `outputs_type`: [`FieldType.JSON`](https://www.unum.cloud/docs/ustore/python/platform-notes.md#JSON) for JSON text, or
[`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) to print scalars as text.

## docs_gist

Lists every distinct path to a leaf across the requested documents, in the order they were first met, which is how a table learns the columns its documents hold.

```python
def docs_gist(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> tuple[str, ...]
```

Returns:
tuple[str, ...]: One JSON Pointer per leaf, such as '/user/name'.

- `keys`: The documents to inspect.
- `arena`: Where the paths land before they are copied out, rewound by this
call.
- `collection`: The collection, by identifier or by name.

## docs_gather

Reads every field of every document into typed columns, converting each value on a best-effort basis and recording what was found, converted, or could not be.

```python
def docs_gather(
    keys: KeysLike,
    fields: Sequence[str],
    outputs_types: FieldType | Sequence[FieldType],
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Columns
```

Returns:
Columns: One column per field, each holding one entry per document.

- `keys`: The documents, the rows of every column.
- `fields`: Top-level keys or JSON Pointers, the columns of the result.
- `outputs_types`: One type per field, or one for
every field: a fixed-width scalar from [`FieldType.BOOL`](https://www.unum.cloud/docs/ustore/python/documents.md#BOOL) to [`FieldType.U8`](https://www.unum.cloud/docs/ustore/python/documents.md#U8),
[`FieldType.UUID`](https://www.unum.cloud/docs/ustore/python/documents.md#UUID), [`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) or [`FieldType.BINARY`](https://www.unum.cloud/docs/ustore/python/documents.md#BINARY). A [`FieldType.F16`](https://www.unum.cloud/docs/ustore/python/documents.md#F16)
column exports as a half-precision view NumPy reads as float16, and a
[`FieldType.UUID`](https://www.unum.cloud/docs/ustore/python/documents.md#UUID) column as sixteen bytes per document.
- `arena`: Where the columns land, rewound by this call.
- `collection`: The collection, by identifier or by name.

## docs_scan

Lists up to `wanted` document keys from `start` towards `end`, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) lists the keys of blobs.

```python
def docs_scan(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    filter: str | bytes | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Keys
```

Documents are not exported, so a [`docs_read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_read) follows the scan.

Returns:
Keys: One run of keys, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first key the scan may return, or None for the first
key in its direction.
- `wanted`: Most keys the scan returns.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The docs collection, by identifier or by name.
- `end`: The key the scan stops before, or None for no bound.
- `direction`: Which way the scan walks, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `mode`: In what order the keys come, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## docs_sample

Up to `wanted` document keys drawn at random, which a [`docs_read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_read) or a [`docs_gather`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_gather) follows.

```python
def docs_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Keys
```

## docs_measure

Bounds on what a range of document keys holds, as [`measure`](https://www.unum.cloud/docs/ustore/python/snapshots.md#measure) reads them for blobs.

```python
def docs_measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Measurement
```

## strings_read

the key of every string, or None for a string the strings collection does not hold.

```python
def strings_read(
    strings: TextsLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> tuple[UUID | None, ...]
```

## strings_scan

up to `wanted` strings starting with `prefix`, in the order of their bytes.

```python
def strings_scan(
    prefix: str | bytes | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    start: str | bytes | None = None,
    end: str | bytes | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> tuple[str, ...]
```

## strings_sample

up to `wanted` strings drawn at random.

```python
def strings_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> tuple[str, ...]
```

## strings_measure

bounds on what a range of strings holds.

```python
def strings_measure(
    start: str | bytes | None,
    end: str | bytes | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Measurement
```

## pages_*_read

Renders whole pages, or the subtrees of `elements`, one per task, None where a page or an element is absent.

```python
def pages__read(
    keys: KeyLike | KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    elements: KeyLike | KeysLike | None = None,
    outputs_encoding: PageEncoding = PageEncoding.XML,
) -> Values
```

## pages_*_scan

Up to `wanted` page keys from `start`, keeping those holding a node of the XPath `filter`.

```python
def pages__scan(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    filter: str | bytes | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Keys
```

## pages_sample

Up to `wanted` page keys drawn at random, which a [`pages_read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#pages_read) follows.

```python
def pages_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Keys
```

## pages_measure

Bounds on what a range of page keys holds, as [`measure`](https://www.unum.cloud/docs/ustore/python/snapshots.md#measure) reads them for blobs.

```python
def pages_measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Measurement
```

## graph_read_edges

Reads every edge a batch of vertices takes part in.

```python
def graph_read_edges(
    vertices: KeysLike,
    arena: Arena,
    /,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
) -> Neighborhoods
```

The edges of one vertex come sorted by neighbour; with both roles the outgoing ones precede the incoming ones.

Returns:
Neighborhoods: One run of (source, target, edge) triples per vertex, None where it is
absent.

- `vertices`: The vertices whose edges are read.
- `arena`: Where the degrees and the edges land, rewound by this call.
- `role`: [`Role.SOURCE`](https://www.unum.cloud/docs/ustore/python/graphs.md#SOURCE) for the edges a vertex leaves by, [`Role.TARGET`](https://www.unum.cloud/docs/ustore/python/graphs.md#TARGET)
for those it is entered by, or [`Role.ANY`](https://www.unum.cloud/docs/ustore/python/graphs.md#ANY) for both, which is how an undirected
graph asks.
- `collection`: The graph collection, by identifier or by name.

## graph_degrees

Counts the edges of a batch of vertices without exporting them.

```python
def graph_degrees(
    vertices: KeysLike,
    arena: Arena,
    /,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
) -> tuple[int | None, ...]
```

Returns:
tuple[int | None, ...]: The degree of every vertex, None where it is absent.

- `vertices`: The vertices whose edges are counted.
- `arena`: Where the degrees land before they are copied out, rewound by this
call.
- `role`: The role of every vertex, as [`graph_read_edges`](https://www.unum.cloud/docs/ustore/python/snapshots.md#graph_read_edges) takes it.
- `collection`: The graph collection, by identifier or by name.

## graph_contains

Whether the vertex is present, read as its degree through a one-off arena.

```python
def graph_contains(
    vertex: KeyLike,
    /,
    *,
    collection: CollectionLike,
) -> bool
```

## graph_scan_vertices

Lists up to `wanted` vertices from `start` towards `end`, those without edges included.

```python
def graph_scan_vertices(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Keys
```

Edges are not exported, so a [`graph_read_edges`](https://www.unum.cloud/docs/ustore/python/snapshots.md#graph_read_edges) follows the scan.

Returns:
Keys: One run of vertices, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first vertex the scan may return, or None for the first
vertex in its direction.
- `wanted`: Most vertices the scan returns.
- `arena`: Where the vertices land, rewound by this call.
- `collection`: The graph collection, by identifier or by name.
- `end`: The vertex the scan stops before, or None for no bound.
- `direction`: Which way the scan walks, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `mode`: In what order the vertices come, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## graph_sample_vertices

Up to `wanted` vertices drawn at random, those without edges included.

```python
def graph_sample_vertices(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Keys
```

## graph_measure_vertices

Bounds on what a range of vertices holds, as [`measure`](https://www.unum.cloud/docs/ustore/python/snapshots.md#measure) reads them for blobs.

```python
def graph_measure_vertices(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Measurement
```

## on

A view whose calls block on [`executor`](#executor), after every call submitted to it before.

```python
def on(executor: Executor) -> On
```

## deferred

A view whose calls [`executor`](#executor) runs while each verb answers a [`Deferred`](#Deferred) at once.

```python
def deferred(executor: Executor) -> DeferredOn
```

## DeferredOn

What a database, transaction or snapshot addresses, with the executor its calls go to, each verb answering a [`Deferred`](#Deferred) at once.

```python
class DeferredOn
```

Every pull of a cursor blocks, so it opens none.

## __getitem__

The collection [`name`](#name) addresses, whose `blobs[key]` and `docs[key]` answer a [`Deferred`](#Deferred).

```python
def __getitem__(name: str) -> Collection
```

## on

on(executor) answers an On whose calls block on the executor.

```python
def on(executor: Executor) -> On
```

Every call runs after the ones submitted to the executor before it finishes, so a read
through it sees what earlier deferred writes wrote.

- `executor`: The threads that run the calls.

## deferred

deferred(executor) answers a DeferredOn whose calls the executor runs meanwhile.

```python
def deferred(executor: Executor) -> DeferredOn
```

Every verb of it submits its call and answers a Deferred at once.

- `executor`: The threads that run the calls.

## watched

watched() answers a view of the transaction whose calls record the keys they touch for conflicts.

```python
def watched() -> DeferredOn
```

## unwatched

unwatched() answers a view of the transaction whose calls record nothing, so they never fail its commit.

```python
def unwatched() -> DeferredOn
```

## read

read(keys, arena, *, collection, offset=0, limit=None) answers a Values tape.

```python
def read(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    offset: int = 0,
    limit: int | None = None,
) -> Deferred[Values]
```

Reads a batch of binary values in one call, which no sequence of single reads
matches for throughput. Nothing is copied: the tape sits in the arena, and indexing
the answer gives a memoryview over the stored bytes, or None for an absent key.

Returns:
Values: One entry per key, in the order they were asked for.
Raises:
ContendedError: The arena serves another call or exports a buffer.
Error: Whatever the engine reported.

- `keys`: The keys to read, as a sequence, a contiguous
buffer of 16-byte keys, which is read in place, or one of 64-bit integers.
- `arena`: Where the tape lands, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `offset`: Byte of every value the read starts at, where an offset
past the end reads empty.
- `limit`: Most bytes of every value to read from the offset, or None
for the rest of it.

## get

The [`Deferred`](#Deferred) of a copy of one value, owning the one-off arena it reads into.

```python
def get(
    key: KeyLike,
    *,
    collection: CollectionLike,
) -> Deferred[bytes | None]
```

## contains

The [`Deferred`](#Deferred) of one presence, owning the one-off arena it reads into.

```python
def contains(
    key: KeyLike,
    *,
    collection: CollectionLike,
) -> Deferred[bool]
```

## scan

scan(start, wanted, arena, *, collection, end=None, direction=ScanDirection.ASCENDING, mode=ScanMode.ORDERED, progress=None) answers a Keys tape.

```python
def scan(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    patterns: Sequence[str | bytes] | None = None,
    pattern_kind: PatternKind = PatternKind.REGEX,
    sensitivity: CaseSensitivity = CaseSensitivity.CASED,
    weights: Sequence[float] | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Deferred[Keys]
```

Lists up to `wanted` keys from `start` towards `end`. Values are not exported, so a
read follows the scan, or a `cursor()` walks a collection with its values instead.

Returns:
Keys: One run of keys, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first key the scan may return, or None for the first
key in its direction.
- `wanted`: Most keys the scan returns.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `end`: The key the scan stops before, or None for no bound.
- `direction`: [`ScanDirection.DESCENDING`](https://www.unum.cloud/docs/ustore/python/scans.md#DESCENDING) walks down from
`start`, largest key first.
- `mode`: [`ScanMode.UNORDERED`](https://www.unum.cloud/docs/ustore/python/scans.md#UNORDERED) lets keys come out of order,
removed or repeated, to speed up the read after the scan; no engine uses it yet.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## scan_batch

The [`Deferred`](#Deferred) of one scan per start, whose `progress` runs on the executor's threads.

```python
def scan_batch(
    starts: KeysLike,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    ends: KeysLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    patterns: Sequence[str | bytes] | None = None,
    pattern_kind: PatternKind = PatternKind.REGEX,
    sensitivity: CaseSensitivity = CaseSensitivity.CASED,
    weights: Sequence[float] | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Deferred[Keys]
```

## sample

sample(wanted, arena, *, collection) answers a Keys tape.

```python
def sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Keys]
```

Draws keys uniformly at random from one collection, which is how a workload picks
entries it has no list of.

Returns:
Keys: One run of keys, in no particular order.

- `wanted`: Most keys to draw.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The collection, by identifier or by name.

## sample_batch

sample_batch(count, wanted, arena, *, collection) answers a Keys tape.

```python
def sample_batch(
    count: int,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Keys]
```

Draws `count` independent samples in one call, all from the one collection named,
which is how a workload builds several random batches without paying for a call each.

Returns:
Keys: One run of keys per sample, in no particular order.

- `count`: Samples to draw.
- `wanted`: Most keys every sample draws.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The one collection every sample draws from, by
identifier or by name.

## measure

measure(start, end, arena, *, collection, direction=ScanDirection.ASCENDING) answers a Measurement.

```python
def measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[Measurement]
```

Estimates what a key range holds without walking it, so the answers are bounds
rather than counts.

Returns:
Measurement: The lower and upper bounds on the entries, the bytes of their values,
and the space they take on disk.

- `start`: First key of the range, or None for the first key in the
direction.
- `end`: The key the range stops before, or None for no bound.
- `arena`: Where the bounds land before they are copied out, rewound by this
call.
- `collection`: The collection, by identifier or by name.
- `direction`: [`ScanDirection.DESCENDING`](https://www.unum.cloud/docs/ustore/python/scans.md#DESCENDING) ranges down from
`start`.

## docs_read

docs_read(keys, arena, *, collection, field=None, outputs_type=FieldType.JSON) answers a Values tape.

```python
def docs_read(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    field: str | None = None,
    outputs_type: FieldType = FieldType.JSON,
) -> Deferred[Values]
```

Reads whole documents, or one field of each, as JSON text or as printed strings. Whole
documents read as JSON pass straight through from the engine, so nothing is parsed.

Returns:
Values: One entry per key, None where the document or the field is absent.

- `keys`: The keys to read.
- `arena`: Where the tape lands, rewound by this call.
- `collection`: The collection, by identifier or by name.
- `field`: A top-level key or a JSON Pointer to read inside every
document; None reads whole documents.
- `outputs_type`: [`FieldType.JSON`](https://www.unum.cloud/docs/ustore/python/platform-notes.md#JSON) for JSON text, or
[`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) to print scalars as text.

## docs_gist

docs_gist(keys, arena, *, collection) answers a tuple of JSON Pointers.

```python
def docs_gist(
    keys: KeysLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[tuple[str, ...]]
```

Lists every distinct path to a leaf across the requested documents, in the order they
were first met, which is how a table learns the columns its documents hold.

Returns:
tuple[str, ...]: One JSON Pointer per leaf, such as '/user/name'.

- `keys`: The documents to inspect.
- `arena`: Where the paths land before they are copied out, rewound by this
call.
- `collection`: The collection, by identifier or by name.

## docs_gather

docs_gather(keys, fields, outputs_types, arena, *, collection) answers Columns.

```python
def docs_gather(
    keys: KeysLike,
    fields: Sequence[str],
    outputs_types: FieldType | Sequence[FieldType],
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Columns]
```

Reads every field of every document into typed columns, converting each value on a
best-effort basis and recording what was found, converted, or could not be.

Returns:
Columns: One column per field, each holding one entry per document.

- `keys`: The documents, the rows of every column.
- `fields`: Top-level keys or JSON Pointers, the columns of the result.
- `outputs_types`: One type per field, or one for
every field: a fixed-width scalar from [`FieldType.BOOL`](https://www.unum.cloud/docs/ustore/python/documents.md#BOOL) to [`FieldType.U8`](https://www.unum.cloud/docs/ustore/python/documents.md#U8),
[`FieldType.UUID`](https://www.unum.cloud/docs/ustore/python/documents.md#UUID), [`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) or [`FieldType.BINARY`](https://www.unum.cloud/docs/ustore/python/documents.md#BINARY). A [`FieldType.F16`](https://www.unum.cloud/docs/ustore/python/documents.md#F16)
column exports as a half-precision view NumPy reads as float16, and a
[`FieldType.UUID`](https://www.unum.cloud/docs/ustore/python/documents.md#UUID) column as sixteen bytes per document.
- `arena`: Where the columns land, rewound by this call.
- `collection`: The collection, by identifier or by name.

## docs_scan

docs_scan(start, wanted, arena, *, collection, end=None, direction=ScanDirection.ASCENDING, mode=ScanMode.ORDERED, progress=None) answers a Keys tape.

```python
def docs_scan(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    filter: str | bytes | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Deferred[Keys]
```

Lists up to `wanted` document keys from `start` towards `end`, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) lists the
keys of blobs. Documents are not exported, so a [`docs_read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_read) follows the scan.

Returns:
Keys: One run of keys, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first key the scan may return, or None for the first
key in its direction.
- `wanted`: Most keys the scan returns.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The docs collection, by identifier or by name.
- `end`: The key the scan stops before, or None for no bound.
- `direction`: Which way the scan walks, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `mode`: In what order the keys come, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## docs_sample

docs_sample(wanted, arena, *, collection) answers a Keys tape.

```python
def docs_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Keys]
```

Draws document keys uniformly at random from one collection, as [`sample`](https://www.unum.cloud/docs/ustore/python/snapshots.md#sample) draws the keys
of blobs. Documents are not exported, so a [`docs_read`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_read) or a [`docs_gather`](https://www.unum.cloud/docs/ustore/python/snapshots.md#docs_gather) follows.

Returns:
Keys: One run of keys, in no particular order.

- `wanted`: Most keys to draw.
- `arena`: Where the keys land, rewound by this call.
- `collection`: The docs collection, by identifier or by name.

## docs_measure

The [`Deferred`](#Deferred) of bounds on what a range of document keys holds.

```python
def docs_measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[Measurement]
```

## strings_read

The [`Deferred`](#Deferred) of the key of every string, or None for a string the strings collection does not hold.

```python
def strings_read(
    strings: TextsLike,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[tuple[UUID | None, ...]]
```

## strings_scan

The [`Deferred`](#Deferred) of up to `wanted` strings starting with `prefix`, in the order of their bytes.

```python
def strings_scan(
    prefix: str | bytes | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    start: str | bytes | None = None,
    end: str | bytes | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[tuple[str, ...]]
```

## strings_sample

The [`Deferred`](#Deferred) of up to `wanted` strings drawn at random.

```python
def strings_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[tuple[str, ...]]
```

## strings_measure

The [`Deferred`](#Deferred) of bounds on what a range of strings holds.

```python
def strings_measure(
    start: str | bytes | None,
    end: str | bytes | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[Measurement]
```

## pages_sample

The [`Deferred`](#Deferred) of up to `wanted` page keys drawn at random.

```python
def pages_sample(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Keys]
```

## pages_measure

The [`Deferred`](#Deferred) of bounds on what a range of page keys holds.

```python
def pages_measure(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[Measurement]
```

## graph_read_edges

graph_read_edges(vertices, arena, *, role=Role.ANY, collection) answers Neighborhoods.

```python
def graph_read_edges(
    vertices: KeysLike,
    arena: Arena,
    /,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
) -> Deferred[Neighborhoods]
```

Reads every edge a batch of vertices takes part in. The edges of one vertex come sorted
by neighbour; with both roles the outgoing ones precede the incoming ones.

Returns:
Neighborhoods: One run of (source, target, edge) triples per vertex, None where it is
absent.

- `vertices`: The vertices whose edges are read.
- `arena`: Where the degrees and the edges land, rewound by this call.
- `role`: [`Role.SOURCE`](https://www.unum.cloud/docs/ustore/python/graphs.md#SOURCE) for the edges a vertex leaves by, [`Role.TARGET`](https://www.unum.cloud/docs/ustore/python/graphs.md#TARGET)
for those it is entered by, or [`Role.ANY`](https://www.unum.cloud/docs/ustore/python/graphs.md#ANY) for both, which is how an undirected
graph asks.
- `collection`: The graph collection, by identifier or by name.

## graph_degrees

graph_degrees(vertices, arena, *, role=Role.ANY, collection) answers a tuple.

```python
def graph_degrees(
    vertices: KeysLike,
    arena: Arena,
    /,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
) -> Deferred[tuple[int | None, ...]]
```

Counts the edges of a batch of vertices without exporting them.

Returns:
tuple[int | None, ...]: The degree of every vertex, None where it is absent.

- `vertices`: The vertices whose edges are counted.
- `arena`: Where the degrees land before they are copied out, rewound by this
call.
- `role`: The role of every vertex, as [`graph_read_edges`](https://www.unum.cloud/docs/ustore/python/snapshots.md#graph_read_edges) takes it.
- `collection`: The graph collection, by identifier or by name.

## graph_contains

graph_contains(vertex, *, collection) answers a bool.

```python
def graph_contains(
    vertex: KeyLike,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[bool]
```

Whether a vertex is present, read as its degree through a one-off arena, which a
loop avoids with [`graph_degrees`](https://www.unum.cloud/docs/ustore/python/snapshots.md#graph_degrees) and an arena of its own.

Returns:
bool: Whether the vertex is present.

- `vertex`: The vertex to look for.
- `collection`: The graph collection, by identifier or by name.

## graph_scan_vertices

graph_scan_vertices(start, wanted, arena, *, collection, end=None, direction=ScanDirection.ASCENDING, mode=ScanMode.ORDERED, progress=None) answers a Keys tape.

```python
def graph_scan_vertices(
    start: KeyLike | None,
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    end: KeyLike | None = None,
    direction: ScanDirection = ScanDirection.ASCENDING,
    mode: ScanMode = ScanMode.ORDERED,
    progress: Progress | None = None,
    predicate: Predicate | None = None,
    predicate_cost: PredicateCost = PredicateCost.CHEAP,
) -> Deferred[Keys]
```

Lists up to `wanted` vertices from `start` towards `end`, those without edges included.
Edges are not exported, so a [`graph_read_edges`](https://www.unum.cloud/docs/ustore/python/snapshots.md#graph_read_edges) follows the scan.

Returns:
Keys: One run of vertices, in the order of the direction.
Raises:
CancelledError: The progress callable stopped the scan.

- `start`: The first vertex the scan may return, or None for the first
vertex in its direction.
- `wanted`: Most vertices the scan returns.
- `arena`: Where the vertices land, rewound by this call.
- `collection`: The graph collection, by identifier or by name.
- `end`: The vertex the scan stops before, or None for no bound.
- `direction`: Which way the scan walks, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `mode`: In what order the vertices come, as [`scan`](https://www.unum.cloud/docs/ustore/python/snapshots.md#scan) takes it.
- `progress`: Called with the scans
finished and the scans in all; a falsy answer other than None cancels the call.

## graph_sample_vertices

The [`Deferred`](#Deferred) of up to `wanted` vertices drawn at random.

```python
def graph_sample_vertices(
    wanted: int,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
) -> Deferred[Keys]
```

## graph_measure_vertices

The [`Deferred`](#Deferred) of bounds on what a range of vertices holds.

```python
def graph_measure_vertices(
    start: KeyLike | None,
    end: KeyLike | None,
    arena: Arena,
    /,
    *,
    collection: CollectionLike,
    direction: ScanDirection = ScanDirection.ASCENDING,
) -> Deferred[Measurement]
```

## collection_find

collection_find(name, arena) answers the identifier the name addresses.

```python
def collection_find(
    name: str,
    arena: Arena,
    /,
) -> Deferred[UUID]
```

Reads the name at the snapshot of a snapshot, and at the head otherwise, since a
transaction never creates or drops collections.

Returns:
UUID: The identifier addressing the collection.
Raises:
NotFoundError: No collection carries the name.

- `name`: The name to resolve.
- `arena`: Where the lookup lands before it is copied out, rewound by this
call.

## collection_list

collection_list(arena) answers the identifiers of every collection.

```python
def collection_list(
    arena: Arena,
    /,
) -> Deferred[tuple[UUID, ...]]
```

Lists the collections at the snapshot of a snapshot, and at the head otherwise.
System collections are never listed, and collection_names answers the names.

Returns:
tuple[UUID, ...]: One identifier per collection.

- `arena`: Where the listing lands before it is copied out, rewound by this
call.

## save

save(path, *, progress=None) answers None.

```python
def save(
    path: PathLikeOrStr,
    /,
    *,
    progress: Progress | None = None,
) -> Deferred[None]
```

Writes the snapshot out as a new database of the same engine, holding exactly the
collections and names the snapshot records, which that engine's open then serves.
RocksDB and LevelDB create the directory, the RAM engine writes its image into the
directory the path names, and NVMe takes the path as the new database's manifest.
Calls `ustore_snapshot_save`.

Raises:
CancelledError: The progress callable stopped the save.
UnsupportedError: The engine saves no snapshots.

- `path`: The directory the saved database lands in, or its
manifest on NVMe.
- `progress`: Called with the bytes of the
keys and values saved and the bytes in all. A falsy answer other than None stops
the save, which removes what it wrote.

## clear

clear(mode) answers None.

```python
def clear(mode: DropMode, /) -> Deferred[None]
```

Empties every collection at once at the head, as [`collection_drop`](https://www.unum.cloud/docs/ustore/python/quickstart.md#collection_drop) empties one. Calls
`ustore_database_clear`.

Raises:
InvalidArgumentError: The RAM and RocksDB engines drop no collection while a
snapshot is open, since the snapshot belongs to its holder.
ReadOnlyError: The database was opened read-only.

- `mode`: [`DropMode.PAIRS`](https://www.unum.cloud/docs/ustore/python/collections.md#PAIRS) removes every key and value and keeps the
collections, [`DropMode.COLLECTION`](https://www.unum.cloud/docs/ustore/python/collections.md#COLLECTION) drops every collection with its name, and
[`DropMode.VALUES`](https://www.unum.cloud/docs/ustore/python/collections.md#VALUES) empties every value and keeps the keys.

## compact

compact(*, progress=None) answers None.

```python
def compact(
    *,
    progress: Progress | None = None,
) -> Deferred[None]
```

Reclaims the space overwritten and removed data still takes, one collection at a time:
RocksDB and LevelDB flush and compact their trees, and the RAM engine frees the
versions no reader needs and rewrites its image. Calls `ustore_database_compact`.

Raises:
CancelledError: The progress callable stopped the compaction.
ReadOnlyError: The database was opened read-only.

- `progress`: Called with the units
compacted and the units in all, bytes where the engine measures them, as RocksDB
does, and collections elsewhere. A falsy answer other than None stops between
collections, keeping what was compacted.

## flush

flush() answers None.

```python
def flush() -> Deferred[None]
```

Makes every commit that returned before this call durable, as if each had asked for
[`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED). LevelDB syncs only its current log, so a commit in a log it
already rotated stays unsynced until its compaction lands. Calls `ustore_database_flush`.

Raises: - [`ReadOnlyError`](https://www.unum.cloud/docs/ustore/python/errors.md#ReadOnlyError): The database was opened read-only.

## describe

describe() answers a Description.

```python
def describe() -> Deferred[Description]
```

Reports the engine serving the database, what it supports, its isolation, and the
keys, memory and disk it holds, every size the engine's estimate and zero where it
keeps none. Calls `ustore_database_describe`.

## write

write(keys, values, *, collection, durability=Durability.BUFFERED) answers None.

```python
def write(
    keys: KeysLike,
    values: Sequence[ValueLike] | ValueLike | TapeLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Upserts a batch of binary values in one call. Every value is borrowed for the
length of the call rather than copied, so a memory-mapped buffer reaches the engine
untouched.

Raises:
TypeError: A value is None or exports no buffer.
Error: Whatever the engine reported.

- `keys`: The keys to write.
- `values`: One value per key, a tape of
them, or a single bytes-like object broadcast to every key. A tape is an Arrow
`binary`, `large_binary`, `string` or `large_string` array, such as [`Values`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#Values), or
a `(data, offsets)` tuple of buffers with unsigned 32-bit or 64-bit offsets, and
passes without a copy. None is refused, since [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) removes keys.
- `collection`: The collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## set

set(key, value, *, collection, durability=Durability.BUFFERED) answers None.

```python
def set(
    key: KeyLike,
    value: ValueLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Upserts one binary value.

Raises:
TypeError: The value is None or exports no buffer.

- `key`: The key to write.
- `value`: The bytes to store, borrowed rather than copied.
- `collection`: The collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## remove

remove(keys, *, collection, ends=None, durability=Durability.BUFFERED) answers None.

```python
def remove(
    keys: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    ends: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Removes a batch of keys with their values, or one key given on its own, while
[`docs_remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#docs_remove) removes documents. With `ends`, every key starts a range reaching up to
its end, and every key of the range goes, all in one atomic call.

- `keys`: The keys to remove, or the first key
of every range.
- `collection`: The collection, by identifier or by name.
- `ends`: The key every range stops
before, one per key.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## docs_write

docs_write(keys, documents, *, collection, field=None, modification=Modification.UPSERT, type=FieldType.JSON, id_field=None, durability=Durability.BUFFERED) answers None.

```python
def docs_write(
    keys: KeysLike | None,
    documents: Sequence[DocumentLike] | DocumentLike | TapeLike,
    *,
    collection: CollectionLike,
    field: str | None = None,
    modification: Modification = Modification.UPSERT,
    type: FieldType = FieldType.JSON,
    id_field: str | None = None,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Writes a batch of JSON documents, or one field inside each of them. Every document is
borrowed for the length of the call rather than copied.

Raises:
TypeError: A document is None.
MalformedError: A document does not parse, or its `id_field` holds no integer.
NotFoundError: A field is written inside a document that does not exist.
AlreadyExistsError: An insert names a document that already exists.

- `keys`: The keys to write; None reads every key from
`id_field` of its document.
- `documents`: One
document per key, a tape of them, or one document broadcast to every key. Text,
bytes and a tape, as [`write`](https://www.unum.cloud/docs/ustore/python/transactions.md#write) takes one, are JSON already, while a dict, a list or a
number inside a sequence is serialized. None is refused: [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) removes whole
documents, and a merge with a JSON null removes a field. Under a fixed-width `type`,
a contiguous buffer of one scalar per key is a column, which reaches the store
without being printed as JSON and parsed back.
- `collection`: The collection, by identifier or by name.
- `field`: A top-level key or a JSON Pointer such as '/user/name' to
write inside every document; None writes whole documents.
- `modification`: An upsert, update or insert, an RFC 6902
[`Modification.PATCH`](https://www.unum.cloud/docs/ustore/python/documents.md#PATCH) or an RFC 7386 [`Modification.MERGE`](https://www.unum.cloud/docs/ustore/python/documents.md#MERGE).
- `type`: How every document is spelled: [`FieldType.JSON`](https://www.unum.cloud/docs/ustore/python/platform-notes.md#JSON),
[`FieldType.STRING`](https://www.unum.cloud/docs/ustore/python/documents.md#STRING) for a plain string, [`FieldType.NULL`](https://www.unum.cloud/docs/ustore/python/documents.md#NULL), or the raw bytes of
[`FieldType.BOOL`](https://www.unum.cloud/docs/ustore/python/documents.md#BOOL), [`FieldType.F64`](https://www.unum.cloud/docs/ustore/python/documents.md#F64), [`FieldType.F32`](https://www.unum.cloud/docs/ustore/python/documents.md#F32), [`FieldType.I64`](https://www.unum.cloud/docs/ustore/python/documents.md#I64) through
[`FieldType.U8`](https://www.unum.cloud/docs/ustore/python/documents.md#U8).
- `id_field`: The field holding every key when [`keys`](https://www.unum.cloud/docs/ustore/python/scans.md#keys) is None.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## docs_remove

docs_remove(keys, *, collection, ends=None, durability=Durability.BUFFERED) answers None.

```python
def docs_remove(
    keys: KeyLike | KeysLike,
    *,
    collection: CollectionLike,
    ends: KeyLike | KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Removes a batch of whole documents, or one given on its own; a patch or a merge removes
fields inside them instead. With `ends`, every key starts a range of documents removed
up to its end, as [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) takes them.

- `keys`: The keys of the documents to remove, or
the first key of every range.
- `collection`: The docs collection, by identifier or by name.
- `ends`: The key every range stops
before, one per key.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## import_arrow

Writes every batch of an Arrow stream through the writes of the collection's modality.

```python
def import_arrow(
    source: ArrowSource,
    *,
    collection: CollectionLike,
    durability: Durability | None = None,
) -> Deferred[int]
```

## ingest_arrow

Lands every batch of an Arrow stream as one commit of its own at the head, refused through a transaction.

```python
def ingest_arrow(
    source: ArrowSource,
    *,
    collection: CollectionLike,
    order: IngestOrder = 'sorted',
    durability: Durability | None = None,
) -> Deferred[int]
```

## graph_write_edges

graph_write_edges(sources, targets, *, edges=None, collection, durability=Durability.BUFFERED) answers None.

```python
def graph_write_edges(
    sources: KeysLike,
    targets: KeysLike,
    *,
    edges: KeysLike | None = None,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Inserts a batch of edges, creating the vertices they connect. An edge already present
is kept, so writing the same batch twice changes nothing.

- `sources`: The vertex every edge leaves.
- `targets`: The vertex every edge enters.
- `edges`: The identifier of every edge, which tells
apart several edges between one pair; None gives every edge [`edge_id_default`](https://www.unum.cloud/docs/ustore/python/graphs.md#edge_id_default).
- `collection`: The graph collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_remove_edges

graph_remove_edges(sources, targets, *, edges=None, collection, durability=Durability.BUFFERED) answers None.

```python
def graph_remove_edges(
    sources: KeysLike,
    targets: KeysLike,
    *,
    edges: KeysLike | None = None,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Removes a batch of edges and keeps the vertices they connected, even once isolated.

- `sources`: The vertex every edge leaves.
- `targets`: The vertex every edge enters.
- `edges`: The identifier of every edge; None removes
the edges that were given [`edge_id_default`](https://www.unum.cloud/docs/ustore/python/graphs.md#edge_id_default).
- `collection`: The graph collection, by identifier or by name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_write_vertices

graph_write_vertices(vertices, *, collection, durability=Durability.BUFFERED) answers None.

```python
def graph_write_vertices(
    vertices: KeysLike,
    *,
    collection: CollectionLike,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Inserts a batch of vertices without edges, keeping those already present.

- `vertices`: The vertices to insert.
- `collection`: The graph collection, by identifier or name.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## graph_remove_vertices

graph_remove_vertices(vertices, *, role=Role.ANY, collection, ends=None, durability=Durability.BUFFERED) answers None.

```python
def graph_remove_vertices(
    vertices: KeysLike,
    *,
    role: Role = Role.ANY,
    collection: CollectionLike,
    ends: KeysLike | None = None,
    durability: Durability = Durability.BUFFERED,
) -> Deferred[None]
```

Removes a batch of vertices together with every edge they take part in. With `ends`,
every vertex starts a range removed up to its end, as [`remove`](https://www.unum.cloud/docs/ustore/python/transactions.md#remove) takes them.

- `vertices`: The vertices to remove, or the first vertex of
every range.
- `role`: The role every vertex plays, which only a joining graph between
two collections needs; [`Role.ANY`](https://www.unum.cloud/docs/ustore/python/graphs.md#ANY) otherwise.
- `collection`: The graph collection, by identifier or by name.
- `ends`: The vertex every range stops before, one
per vertex.
- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## commit

commit(durability=Durability.BUFFERED) answers the commit stamp.

```python
def commit(
    durability: Durability = Durability.BUFFERED,
) -> Deferred[int]
```

Applies every staged change, or none of them. The contents are kept whatever the
outcome, so a rejected transaction can be inspected or replayed.

Returns:
int: The commit stamp, this commit's position in commit order, which every snapshot
whose read stamp is at or above it sees.
Raises:
ConflictError: A concurrent writer touched what this transaction watched.

- `durability`: [`Durability.FLUSHED`](https://www.unum.cloud/docs/ustore/python/reads-and-writes.md#FLUSHED) reaches the drive before
returning.

## stage

stage() answers the read stamp.

```python
def stage() -> Deferred[int]
```

Runs the first phase of a two-phase commit, after which a commit publishes the
work. Staging reserves no position in commit order.

## database

```python
database: Database
```

## executor

The executor the view's calls go to, where an arena for them belongs.

```python
executor: Executor | None
```

## gpu_devices

Every GPU this process can drive, NVIDIA devices first, then AMD, each at the ordinal [`Executor.for_vram`](#for_vram) names it by; empty on a machine without GPUs or their runtimes.

```python
def gpu_devices() -> tuple[GPUDevice, ...]
```

Calls `ustore_gpu_devices`.

