# Arenas

> UForm for Python

Every output whose length only the call knows, the embeddings, the states and their offsets, lands in a `uform.Arena` you pass, and the verb answers views over it without copying.
`uform.Arena(executor)` places it where that executor computes, decided once, and `uform.Arena()` makes host pages for the calling thread.
Each call rewinds its arena, so the previous call's views die and a steady loop allocates once.
To keep a result past the next call, 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 output raises `InvalidArgumentError` when read.
An arena from a VRAM executor holds device memory: its views export `__cuda_array_interface__` for CuPy, PyTorch or Numba, and host reads raise `DeviceError`.

```python
arena = uform.Arena(executor)
for batch in batches:
    encoded = model.on(executor).text_encode(batch, arena)  # rewinds: the last batch's views are gone
    index.add(np.array(encoded.embeddings))  # a copy, so nothing pins the arena
```

`import uform`

`from uform import ArenaBuffer`

## Arena

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

```python
class Arena
```

## ArenaBuffer

One output a call left in an [`Arena`](#Arena), readable until a later call rewinds it.

```python
class ArenaBuffer
```

## __buffer__

Host memory only; device memory raises [`DeviceError`](https://www.unum.cloud/docs/uform/python/errors.md#DeviceError), a rewound arena [`InvalidArgumentError`](https://www.unum.cloud/docs/uform/python/errors.md#InvalidArgumentError).

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

## __len__

Rows.

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

Python-only.

## __dlpack__

A DLPack capsule over the output in place; the arena refuses to rewind until the consumer lets go.

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

## __dlpack_device__

The DLPack device type and ID the output lives on.

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

## __cuda_array_interface__

Version 3 of the CUDA Array Interface, present only over device memory.

```python
__cuda_array_interface__: dict[str, Any]
```

Python-only.

