# Snapshots

> UStore for Python

`from ustore import Snapshot`

## Snapshot

A point-in-time state of the whole database, whose read verbs see what it pinned.

```python
class Snapshot
```

## save

Writes the snapshot out as a new database of the same engine, holding exactly the collections it records, reporting the bytes of keys and values saved; a cancelled save removes what it wrote.

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

## collection_find

The collection ID the name addresses at this snapshot.

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

## collection_list

The IDs of every collection at this snapshot, never a system one.

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

## close

Releases the snapshot once its deferred calls finished, unpinning the versions only it kept.

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

## database

```python
database: Database
```

## read_stamp

The stamp the snapshot reads at: it sees every commit whose commit stamp is at or below it, and none above.

```python
read_stamp: int
```

## __getitem__

The collection [`name`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#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`](#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`](#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`](#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`](#scan) takes it.
- `mode`: In what order the keys come, as [`scan`](#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`](#docs_read) or a [`docs_gather`](#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`](#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`](#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`](#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`](#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`](#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`](#scan) takes it.
- `mode`: In what order the vertices come, as [`scan`](#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`](#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`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#executor), after every call submitted to it before.

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

## deferred

A view whose calls [`executor`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#executor) runs while each verb answers a [`Deferred`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#Deferred) at once.

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

