# Scans

> UStore for Python

`import ustore`

`from ustore import Keys, Page, Cursor, …`

## ScanMode

In what order a scan hands its keys over, valued as `ustore_scan_mode_t`.

```python
class ScanMode(IntEnum)
```

- `ORDERED` = `0`
- `UNORDERED` = `1`

## ScanDirection

Which way a scan, a cursor or a measurement walks its range from the start key.

```python
class ScanDirection(IntEnum)
```

- `ASCENDING` = `0`
- `DESCENDING` = `1`

## PatternKind

What the patterns of a scan or a cursor are matched as, valued as `ustore_pattern_kind_t`.

```python
class PatternKind(IntEnum)
```

- `REGEX` = `0`
- `SUBSTRINGS` = `1`

## CaseSensitivity

Whether patterns compare bytes as they are or after Unicode case folding, valued as `ustore_case_sensitivity_t`.

```python
class CaseSensitivity(IntEnum)
```

- `CASED` = `0`
- `UNCASED` = `1`

## PredicateCost

Where a scan asks its predicate: before patterns and filters read values, or last, valued as `ustore_predicate_cost_t`.

```python
class PredicateCost(IntEnum)
```

- `CHEAP` = `0`
- `EXPENSIVE` = `1`

## ChangeKind

What one committed change did to its key.

```python
class ChangeKind(IntEnum)
```

- `WRITE` = `0`
- `REMOVAL` = `1`
- `CHANGE` = `2`

## Predicate

Called with the keys one page of a scan or a pull listed, from whichever thread runs it, answering one truthy item per key kept; a raise rejects the rest and re-raises once the call is final.

```python
type Predicate = Callable[[tuple[UUID, ...]], Sequence[object]]
```

## Keys

The keys one batch scan or sample wrote into an [`Arena`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#Arena), viewing it until it rewinds.

```python
class Keys
```

## __dlpack__*__dlpack__

A DLPack capsule over the memory the buffer protocol exports, pinning the arena until its consumer deletes it, so `numpy.from_dlpack` reads it in place.

```python
def __dlpack____dlpack__(
    *,
    stream: object | None = None,
    max_version: tuple[int, int] | None = None,
    dl_device: tuple[int, int] | None = None,
    copy: bool | None = None,
) -> object
```

## __dlpack_device__*__dlpack_device__

The DLPack device of the arena: (1, 0) for host pages, (2, ordinal) for NVIDIA, (10, ordinal) for AMD.

```python
def __dlpack_device____dlpack_device__() -> tuple[int, int]
```

## counts

```python
counts: tuple[int, ...]
```

## scores

```python
scores: tuple[float, ...] | None
```

## Page

The keys one pull of a [`Cursor`](#Cursor) wrote into an [`Arena`](https://www.unum.cloud/docs/ustore/python/batches-and-arenas.md#Arena), viewing it until it rewinds; empty, so falsy, once the walk ends.

```python
class Page
```

## __buffer__

The keys as an array of shape (keys, 16) bytes, pinning the arena until released.

```python
def __buffer__(flags: int) -> memoryview
```

## values

The values of the keys, every one present, when the pull asked for them, and None otherwise.

```python
values: Values | None
```

## Cursor

A walk over the keys of one collection, which every pull resumes past the last key the one before it handed out, so a key written behind the walk never comes and one written ahead of it does.

```python
class Cursor
```

A page shorter than `wanted` exhausts the walk for good, whatever is written since.

## next

The next page of up to `wanted` keys in `arena`, with their values when asked, blocking on the executor the cursor was opened through.

```python
def next(
    wanted: int,
    arena: Arena,
    /,
    *,
    values: bool = False,
    progress: Progress | None = None,
) -> Page
```

Calls `ustore_blobs_cursor_next`.

## close

Frees the walk with the holds it kept on its database and the transaction or snapshot it reads through.

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

## ChangesCursor

A feed of the changes committed to one collection after a stamp, oldest first, which pins that stamp and resumes every pull past the last change the pull before it handed out.

```python
class ChangesCursor
```

## next

The next up to `wanted` changes in `arena`, with the bytes every one carries when asked; an empty pull reached the newest commit.

```python
def next(
    wanted: int,
    arena: Arena,
    /,
    *,
    values: bool = False,
) -> Changes
```

## close

Frees the feed, releasing the stamp it pinned and the hold it kept on its database.

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

## Changes

The changes one pull of a ChangesCursor answers, oldest first.

```python
class Changes(structseq[Any], tuple[Page, Values | None, tuple[int, ...], tuple[ChangeKind, ...]])
```

## keys

The Page of the key of every change, oldest change first.

```python
keys: Page
```

## values

The Values of the bytes every change carries when the pull asked for them, or None.

```python
values: Values | None
```

## stamps

The stamp every change was committed at.

```python
stamps: tuple[int, ...]
```

## kinds

What every change did.

```python
kinds: tuple[ChangeKind, ...]
```

## Measurement

The bounds on what a key range holds, as `measure()` estimates them without walking it.

```python
class Measurement(structseq[int], tuple[int, int, int, int, int, int])
```

## min_cardinality

The fewest entries the range may hold.

```python
min_cardinality: int
```

## max_cardinality

The most entries the range may hold.

```python
max_cardinality: int
```

## min_value_bytes

The fewest bytes the values in the range may take.

```python
min_value_bytes: int
```

## max_value_bytes

The most bytes the values in the range may take.

```python
max_value_bytes: int
```

## min_space_usage

The fewest bytes the range may take on disk.

```python
min_space_usage: int
```

## max_space_usage

The most bytes the range may take on disk.

```python
max_space_usage: int
```

