---
sidebar:
  hidden: true
title: roboto.formats.mcap.accessor
---
## Module Contents

### Accessor

```python
roboto.formats.mcap.accessor.Accessor
```

`from roboto.formats.mcap import Accessor`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L136-L136)

Reads one path's value out of a decoded message and writes it into an [`Accumulator`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.Accumulator).

The accessor is compiled once per `fields` set and reused for every subsequent message in the same read pass. Compilation resolves time-field name remapping and sequence boundaries against a sample message, so per-call work is just attribute access plus accumulator writes.

### AccessorCache

```python
class roboto.formats.mcap.accessor.AccessorCache
```

`from roboto.formats.mcap.accessor import AccessorCache`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L149-L179)

Holds compiled [`Accessor`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.Accessor) callables for the lifetime of a single read pass.

The cache lives on the reader rather than at module scope so that two readers projecting the same paths against differently-shaped messages (e.g. a time field present in one topic and absent in another) cannot pollute each other.

#### AccessorCache.get_or_compile()

```python
def get_or_compile(
    fields: collections.abc.Sequence[FieldSelection],
    sample: Any,
    getter: AttrGetter,
) -> list[Accessor]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L160-L179)

Return accessors for these fields, compiling against `sample` on first call.

Compilations that hit an empty sequence in the sample are speculative — the inner shape past the empty point can't be observed — and are returned without caching so a later message with a non-empty sequence triggers a fresh, complete compile.

**Parameters**

- **fields** (`collections.abc.Sequence[FieldSelection]`)
- **sample** (`Any`)
- **getter** (`AttrGetter`)

**Returns**

- `list[Accessor]`

### Accumulator

```python
roboto.formats.mcap.accessor.Accumulator
```

`from roboto.formats.mcap.accessor import Accumulator`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L133-L133)

Output dict the accessors write into. Nested keys materialize as nested dicts.

### AttrGetter

```python
class roboto.formats.mcap.accessor.AttrGetter
```

`from roboto.formats.mcap.accessor import AttrGetter`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L32-L89)

Bases: `abc.ABC`

Abstract base class for reading attributes from a decoded message.

Decoded MCAP messages are dictionaries -- JSON and the shared `mcap_codec` decoder both materialize to `dict` -- so [`DictAttrGetter`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.DictAttrGetter) is the only implementation. The abstraction is kept so the accessor compiler takes a getter rather than hard-coding dict access.

#### AttrGetter.get_attribute()

```python
@staticmethod
@abstractmethod
def get_attribute(value, attribute) -> Any
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L55-L64)

Get the value of a specific attribute from the given value.

**Parameters**

- **value**: The decoded message value to access.
- **attribute**: Name of the attribute to retrieve.

**Returns**

- `Any`: The value of the specified attribute.

#### AttrGetter.get_attribute_names()

```python
@staticmethod
@abstractmethod
def get_attribute_names(value) -> collections.abc.Sequence[str]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L43-L51)

Get the names of all attributes available in the given value.

**Parameters**

- **value**: The decoded message value to inspect.

**Returns**

- `collections.abc.Sequence[str]`: Sequence of attribute names available in the value.

#### AttrGetter.has_attribute()

```python
@staticmethod
@abstractmethod
def has_attribute(value, attribute: str) -> bool
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L68-L77)

Check if the given value has a specific attribute.

**Parameters**

- **value**: The decoded message value to inspect.
- **attribute** (`str`): Name of the attribute to check for.

**Returns**

- `bool`: True if the value has the specified attribute, False otherwise.

#### AttrGetter.has_sub_attributes()

```python
@staticmethod
@abstractmethod
def has_sub_attributes(value) -> bool
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L81-L89)

Check if the given value has nested attributes that can be accessed.

**Parameters**

- **value**: The decoded message value to inspect.

**Returns**

- `bool`: True if the value has nested attributes, False otherwise.

### DictAttrGetter

```python
class roboto.formats.mcap.accessor.DictAttrGetter
```

`from roboto.formats.mcap.accessor import DictAttrGetter`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L92-L116)

Bases: [`AttrGetter`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.AttrGetter)

Attribute getter for decoded messages represented as dictionaries.

Both JSON and the shared `mcap_codec` decoder materialize messages and their nested structs as plain dicts. The `isinstance` guards let a non-dict value -- a JSON `null`, scalar, or list message, or a scalar leaf reached mid-walk -- resolve to "no such attribute" instead of raising, so the accessor compiler simply stops descending.

#### DictAttrGetter.get_attribute()

```python
@staticmethod
def get_attribute(value, attribute)
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L107-L108)

Get the value of a specific attribute from the given value.

**Parameters**

- **value**: The decoded message value to access.
- **attribute**: Name of the attribute to retrieve.

**Returns**

- The value of the specified attribute.

#### DictAttrGetter.get_attribute_names()

```python
@staticmethod
def get_attribute_names(value)
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L103-L104)

Get the names of all attributes available in the given value.

**Parameters**

- **value**: The decoded message value to inspect.

**Returns**

- Sequence of attribute names available in the value.

#### DictAttrGetter.has_attribute()

```python
@staticmethod
def has_attribute(value, attribute: str) -> bool
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L111-L112)

Check if the given value has a specific attribute.

**Parameters**

- **value**: The decoded message value to inspect.
- **attribute** (`str`): Name of the attribute to check for.

**Returns**

- `bool`: True if the value has the specified attribute, False otherwise.

#### DictAttrGetter.has_sub_attributes()

```python
@staticmethod
def has_sub_attributes(value)
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L115-L116)

Check if the given value has nested attributes that can be accessed.

**Parameters**

- **value**: The decoded message value to inspect.

**Returns**

- True if the value has nested attributes, False otherwise.

### PathInSchema

```python
roboto.formats.mcap.accessor.PathInSchema
```

`from roboto.formats.mcap.accessor import PathInSchema`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L145-L145)

One field's path through a message schema, e.g. `("header", "stamp", "sec")`.

### Resolution

```python
roboto.formats.mcap.accessor.Resolution
```

`from roboto.formats.mcap import Resolution`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L228-L228)

A resolved accessor path: a no-op, a simple attribute chain, or a per-element sequence crossing.

Build one with [`none_resolution()`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.none_resolution), [`simple_resolution()`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.simple_resolution), or [`sequence_resolution()`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.sequence_resolution), then compile it with [`build_accessor()`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.build_accessor).

### build_accessor()

```python
def roboto.formats.mcap.accessor.build_accessor(resolution: Resolution) -> Accessor
```

`from roboto.formats.mcap import build_accessor`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L393-L406)

Compile a resolution into an [`Accessor`](/reference/python-sdk/roboto/formats/mcap/accessor#roboto.formats.mcap.accessor.Accessor) that reads its path into an accumulator.

The resolution carries the (possibly time-remapped) structure; this only selects the matching runtime walk. It does not sample, so a caller that built the resolution from a schema can compile without a message in hand.

**Parameters**

- **resolution** (`Resolution`)

**Returns**

- `Accessor`

### compile_accessors()

```python
def roboto.formats.mcap.accessor.compile_accessors(
    fields: collections.abc.Sequence[FieldSelection],
    sample: Any,
    getter: AttrGetter,
) -> tuple[list[Accessor], bool]
```

`from roboto.formats.mcap import compile_accessors`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L182-L201)

Compile one accessor per field. Does not cache; callers manage caching.

Returns a tuple of `(accessors, fully_resolved)`. `fully_resolved` is `False` if any path traversed an empty sequence in `sample` and the inner shape past it had to be guessed. Callers maintaining a cross-message cache should not cache speculative compilations, since the next message may need a different shape.

**Parameters**

- **fields** (`collections.abc.Sequence[FieldSelection]`)
- **sample** (`Any`)
- **getter** (`AttrGetter`)

**Returns**

- `tuple[list[Accessor], bool]`

### getter_for()

```python
def roboto.formats.mcap.accessor.getter_for(message: Any) -> AttrGetter
```

`from roboto.formats.mcap import getter_for`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L124-L130)

The shared attribute getter for a decoded message.

Every decoder materializes messages as dicts (and the dict getter resolves a non-dict JSON payload to no attributes), so one getter serves every message.

**Parameters**

- **message** (`Any`)

**Returns**

- `AttrGetter`

### is_codec_time_value()

```python
def roboto.formats.mcap.accessor.is_codec_time_value(val: Any) -> bool
```

`from roboto.formats.mcap.accessor import is_codec_time_value`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L18-L29)

Whether `val` is a ROS2 `Time` / `Duration` decoded by the shared `mcap_codec` decoder.

The codec surfaces ROS2 `Time` / `Duration` with the schema's own member names -- a plain `{"sec", "nanosec"}` dict, no marker type -- so the match is structural. Recognizing it lets the accessor remap a legacy `nsec` path component (how topics ingested before the move to wire-true field names recorded the sub-second leaf) onto the codec's `nanosec` key; without the remap the nanosecond component is silently dropped. ROS1's `Time` is natively `{"sec", "nsec"}` and JSON time values likewise use `nsec`, so neither matches here nor needs a remap.

**Parameters**

- **val** (`Any`)

**Returns**

- `bool`

### none_resolution()

```python
def roboto.formats.mcap.accessor.none_resolution() -> Resolution
```

`from roboto.formats.mcap import none_resolution`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L236-L238)

A resolution whose accessor is a no-op (the path is absent on a message).

**Returns**

- `Resolution`

### remap_time_fields()

```python
def roboto.formats.mcap.accessor.remap_time_fields(
    resolution: Resolution,
    sample: Any,
    getter: AttrGetter,
) -> tuple[Resolution, bool]
```

`from roboto.formats.mcap import remap_time_fields`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L251-L275)

Substitute the decoder's runtime time-field name into `resolution`, observed against `sample`.

A legacy topic's message paths address a ROS2 time struct's sub-second leaf as `nsec` (how it was recorded before the move to wire-true field names), but the shared `mcap_codec` decoder now materializes that value as a `{"sec", "nanosec"}` dict. This walks `sample` along the resolution and rewrites a trailing `nsec` past any such time value to `nanosec`, so the built accessor reads the right key.

Returns `(remapped, time_resolved)`. `time_resolved` is `False` only when a time-bearing leaf sits past a sequence that is empty in `sample` — its element cannot be observed, so the runtime names stay a guess and the caller should re-resolve against a later, non-empty message. A resolution with no time component is returned unchanged with `True`. Paths that already name the leaf `nanosec` (ROS2 wire-true), ROS1 `nsec`, and JSON `nsec` values are all no-ops.

**Parameters**

- **resolution** (`Resolution`)
- **sample** (`Any`)
- **getter** (`AttrGetter`)

**Returns**

- `tuple[Resolution, bool]`

### sequence_resolution()

```python
def roboto.formats.mcap.accessor.sequence_resolution(
    pre_path: collections.abc.Sequence[str],
    sub: Resolution,
) -> Resolution
```

`from roboto.formats.mcap import sequence_resolution`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L246-L248)

A resolution that crosses the sequence at `pre_path`, applying `sub` per element.

**Parameters**

- **pre_path** (`collections.abc.Sequence[str]`)
- **sub** (`Resolution`)

**Returns**

- `Resolution`

### simple_resolution()

```python
def roboto.formats.mcap.accessor.simple_resolution(
    path: collections.abc.Sequence[str],
) -> Resolution
```

`from roboto.formats.mcap import simple_resolution`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/formats/mcap/accessor.py#L241-L243)

A resolution for a straight attribute chain (no sequence crossing).

**Parameters**

- **path** (`collections.abc.Sequence[str]`)

**Returns**

- `Resolution`
