ursa._query_types

Public Pydantic types returned by :meth:DataInterface.query.

Extracted from the former ursa.query module as part of ENG-1120: the query() function and its helpers were inlined into

mod:

ursa.data_interface, but the result-shape types stay public so callers can from ursa import QueryResult, QueryResultList, QuerySpec.

The leading underscore on the module name is intentional — the types themselves are public, but the module path is internal. Always import from the top-level ursa namespace.

Module Contents

Classes

QueryResult

One recording matched by :meth:DataInterface.query.

QueryResultList

List of :class:QueryResult with notebook/DataFrame rendering.

QuerySpec

Pydantic spec for :meth:DataInterface.query.

Functions

_aggregate_ingestion_status

Aggregate ingestion_status across a recording’s modalities for the DataFrame projection. None (rendered as NaN in pandas) when the modality set is empty — preserves the distinction between “no modality rows” and “all processed” that :class:QueryResult’s docstring calls out.

Data

API

ursa._query_types.__all__

[‘QueryResult’, ‘QueryResultList’, ‘QuerySpec’]

class ursa._query_types.QueryResult(/, **data: typing.Any)[source]

Bases: pydantic.BaseModel

One recording matched by :meth:DataInterface.query.

Named after the verb that produced it: query() is the single selection surface, and get() / download() (ENG-890) consume a QueryResult without further narrowing arguments.

Phase 1a carries catalog projections only — no array bytes, no temporaldata.Data. ModalityRow.raw_storage_uri is the cold-bucket pointer :meth:~ursa.DataInterface.get reads from (originally ENG-890, inlined in ENG-1119). ENG-899 (M3) replaces the modalities values with array-bearing temporaldata subclasses once the processed store exists.

.modalities is narrowed to the modalities=[...] argument passed to

Meth:

DataInterface.query. With modalities=None every modality registered for the recording is present (an empty .modalities dict here means the catalog has no modality rows for this recording — surfaced as-is rather than hidden). When a non-None filter is passed, the dict keys are a non-empty subset of the requested list: recordings whose intersection with the filter is empty are dropped from the result list rather than returned with an empty .modalities dict.

Frozen for accidental-mutation safety; not hashable (the dict/list fields prevent it). Use recording_hash as the cache key.

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config

‘ConfigDict(…)’

recording_hash: ursa.catalog.schemas.CatalogID

None

participant_ids: list[ursa.catalog.schemas.CatalogID]

None

start_time: ursa.catalog.schemas.EpochNs

None

duration: datetime.timedelta

None

device_info: ursa.catalog.schemas.MetadataDict

None

metadata: ursa.catalog.schemas.MetadataDict

None

modalities: dict[ursa.catalog.schemas.ModalityName, ursa.catalog.schemas.ModalityRow]

None

property start_time_dt: datetime.datetime

Aware UTC datetime view of start_time (µs-lossy).

__repr__() str[source]
__str__() str[source]
_to_row_dict() dict[str, Any][source]

Single source-of-truth row projection used by both _repr_html_ and :meth:QueryResultList.to_dataframe. Keeping it on the model guarantees the two renderers never drift.

_repr_html_() str[source]
ursa._query_types._aggregate_ingestion_status(modalities: dict[ursa.catalog.schemas.ModalityName, ursa.catalog.schemas.ModalityRow]) str | None[source]

Aggregate ingestion_status across a recording’s modalities for the DataFrame projection. None (rendered as NaN in pandas) when the modality set is empty — preserves the distinction between “no modality rows” and “all processed” that :class:QueryResult’s docstring calls out.

ursa._query_types._DATAFRAME_COLUMNS: tuple[str, ...]

(‘recording_hash’, ‘participant_ids’, ‘start_time’, ‘duration’, ‘ingestion_status’, ‘modalities’)

class ursa._query_types.QueryResultList[source]

Bases: list[ursa._query_types.QueryResult]

List of :class:QueryResult with notebook/DataFrame rendering.

Returned by :meth:DataInterface.query. Subclasses :class:list so existing list[QueryResult] annotations and isinstance(x, list) checks keep working unchanged. Slicing (results[:5]), concatenation (results + more), :py:meth:copy, and multiplication preserve the subtype so the render methods stay reachable.

sorted(results, ...) is the one common path that drops back to a plain

Class:

list (CPython implementation detail). Wrap with QueryResultList(sorted(results, ...)) if you need .to_dataframe() on a sorted view.

Initialization

Initialize self. See help(type(self)) for accurate signature.

to_dataframe() pandas.DataFrame[source]

Return a :class:pandas.DataFrame with one row per result.

Columns mirror :class:QueryResult attribute names so df.modalities and qr.modalities read the same. The ingestion_status column is aggregated across each recording’s modalities — "raw" if any are raw, else "processed", NaN if the recording has no modality rows.

_repr_html_() str[source]
__repr__() str[source]
__getitem__(key: SupportsIndex | slice) ursa._query_types.QueryResult | ursa._query_types.QueryResultList[source]
__add__(other: list[ursa._query_types.QueryResult]) ursa._query_types.QueryResultList[source]
__radd__(other: list[ursa._query_types.QueryResult]) ursa._query_types.QueryResultList[source]
__mul__(n: SupportsIndex) ursa._query_types.QueryResultList[source]
copy() ursa._query_types.QueryResultList[source]
class ursa._query_types.QuerySpec(/, **data: typing.Any)[source]

Bases: pydantic.BaseModel

Pydantic spec for :meth:DataInterface.query.

Phase 1a — implemented over the raw catalog: participants, modalities, recording_hash, metadata.

Phase 1a — accepted at the signature level, raising

Class:

NotImplementedError (referencing ENG-1082) when a matched modality has ingestion_status="raw": time_range, pipeline_version, time_filters, metadata_filters, derived.

The complex-list fields use list[Any] as a deliberate forward-compat escape hatch; ENG-1082 will replace each with a typed model (AroundEvent | TimeWindow, Filter, DerivedSelector).

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config

‘ConfigDict(…)’

participants: list[ursa.catalog.schemas.CatalogID] | None

None

modalities: list[ursa.catalog.schemas.ModalityName] | None

None

recording_hash: ursa.catalog.schemas.CatalogID | None

None

metadata: ursa.catalog.schemas.MetadataDict | None

None

time_range: tuple[ursa.catalog.schemas.EpochNs, ursa.catalog.schemas.EpochNs] | None

None

pipeline_version: str | None

None

time_filters: list[Any]

‘Field(…)’

metadata_filters: list[Any]

‘Field(…)’

derived: list[Any]

‘Field(…)’

_validate() typing_extensions.Self[source]
has_processed_kwarg() bool[source]

True iff any kwarg requiring the processed store is set.