Skip to content
Roboto
Esc
↑↓navigate↵open⌘Jpreview
On this page

roboto.query.filters

Filter controls as a user built them, in a form that survives being saved.

A SavedFilters records what someone expressed in a filter UI — which field, which operator, which values — rather than the query that expression compiles to. Saved Views hold this, and rebuild an executable query from it on load.

Why this exists rather than a QuerySpecification. A query cannot be stored faithfully today, because Comparator has no way to say “the last 7 days”, “between these two dates”, or “any of these three”. Those get flattened at translation time — a relative window resolves to fixed instants, a range becomes two comparisons, a multi-select becomes an OR group — and the flattening has no inverse. A View storing the translated query would show the week it was saved, forever, presented as though it were live.

FilterOnlyComparator lists exactly what Comparator cannot express. Members leave it as Comparator grows to cover them; when it is empty, a saved filter is expressible as a plain QuerySpecification.

On the per-variant comparator lists below. They state what a filter control offers for a field type, which is narrower than what the query language accepts for the same field: a date filter presents <, > and BETWEEN where a query supports all six ordering and equality operators, and a boolean filter presents EQUALS alone.

Module Contents

BooleanFilter

class roboto.query.filters.BooleanFilter(/, **data)#View Source

Bases: _FilterBase

True or false, or unset.

Parameters

data Any

Attributes

BooleanFilter.type

type Literal['boolean'] = 'boolean' #

BooleanFilter.values

values list[bool] = None #

DateFilter

class roboto.query.filters.DateFilter(/, **data)#View Source

Bases: _FilterBase

Instants and ranges. Values are ISO 8601 strings.

The only variant offering relative windows, which is where the fidelity problem this whole model exists for actually bites.

Parameters

data Any

EnumFilter

class roboto.query.filters.EnumFilter(/, **data)#View Source

Bases: _FilterBase

Equality against a closed set of options.

Parameters

data Any

Attributes

EnumFilter.type

type Literal['enum'] = 'enum' #

EnumFilter.values

values list[str] = None #

FILTER_VARIANTS

roboto.query.filters.FILTER_VARIANTS: Final[dict[str, type[pydantic.BaseModel]]]#View Source

Every filter variant, keyed by its type discriminant.

Filter

type roboto.query.filters.Filter = typing.Annotated[typing.Union[StringFilter, NumericFilter, MetricFilter, DateFilter, BooleanFilter, SetFilter, EnumFilter, IdentityFilter], pydantic.Field(discriminator='type')]#View Source

One filter row. type selects the variant, and with it the operators on offer.

FilterMatchMode

class roboto.query.filters.FilterMatchMode#View Source

Bases: roboto.compat.StrEnum

How separate filters combine.

Attributes

FilterMatchMode.And

And = 'AND' #

Every filter must match.

FilterMatchMode.Or

Or = 'OR' #

At least one filter must match.

FilterOnlyComparator

class roboto.query.filters.FilterOnlyComparator#View Source

Bases: roboto.compat.StrEnum

Operators a saved filter needs that Comparator cannot express.

Every member is a gap in the query language, and this enum is the list of them. It is the complement of Comparator, never a superset: a member here that Comparator can express is a stale entry.

Members are removed one at a time as Comparator grows to cover them. The wire values do not change when that happens, so filters saved beforehand keep parsing.

Attributes

FilterOnlyComparator.Between

Between = 'BETWEEN' #

An inclusive range. Translates to GTE and LTE, which loses the fact that the author expressed one range rather than two independent bounds.

FilterOnlyComparator.Last24Hours

Last24Hours = 'LAST_24_HOURS' #

FilterOnlyComparator.Last30Days

Last30Days = 'LAST_30_DAYS' #

FilterOnlyComparator.Last3Hours

Last3Hours = 'LAST_3_HOURS' #

FilterOnlyComparator.Last7Days

Last7Days = 'LAST_7_DAYS' #

FilterOnlyComparator.Last8Hours

Last8Hours = 'LAST_8_HOURS' #

FilterOnlyComparator.Last90Days

Last90Days = 'LAST_90_DAYS' #

FilterOnlyComparator.ThisMonth

ThisMonth = 'THIS_MONTH' #

Relative windows, resolved against “now” when the filter runs.

These are the members that matter. The others cost fidelity; these cost correctness — a resolved window is wrong the day after it is saved, and nothing about the stored value says so.

FilterOnlyComparator.Today

Today = 'TODAY' #

IDENTITY_OPERATORS_BY_TYPE

roboto.query.filters.IDENTITY_OPERATORS_BY_TYPE: Final[dict[roboto.principal.RobotoPrincipalType, IdentityOperators]]#View Source

Which operators each principal type contributes, and the only statement of that pairing.

Exhaustive over RobotoPrincipalType rather than listing the types an audit column happens to hold today, so a new platform principal type is filterable as soon as it exists instead of being silently unaddressable. A test pins that.

IDENTITY_PRESET_COMPARATORS

roboto.query.filters.IDENTITY_PRESET_COMPARATORS: Final[frozenset[IdentityComparator]]#View Source

The IS_ANY_<TYPE> half. Valueless: the comparator alone carries the predicate.

IDENTITY_TYPES_BY_COMPARATOR

roboto.query.filters.IDENTITY_TYPES_BY_COMPARATOR: Final[dict[IdentityComparator, roboto.principal.RobotoPrincipalType]]#View Source

The principal type each identity operator addresses. Derived from the pairing above.

IdentityComparator

class roboto.query.filters.IdentityComparator#View Source

Bases: roboto.compat.StrEnum

Operators over a principal-valued field, where the operator names a principal type.

An audit column such as created_by stores a fully-qualified principal — user:<user_id>, device:<device_id>@<org_id>, invocation:<invocation_id> — so “created by a user” is a question about the type prefix and “created by this user” a question about the whole value. Putting the type in the operator is what lets a filter UI offer the matching directory to pick from, instead of asking for a hand-typed prefix.

Each type contributes two operators (see IDENTITY_OPERATORS_BY_TYPE): a value-bearing IS_<TYPE> and a valueless IS_ANY_<TYPE>.

Separate from FilterOnlyComparator because these are not gaps in the query language. Both halves are expressible as a query today — IS_<TYPE> as EQUALS against each picked principal, IS_ANY_<TYPE> as LIKE '<type>:%' — so they are never removed. They are a filter-control affordance, and they outlive the gap enum.

Attributes

IdentityComparator.IsAnyDevice

IsAnyDevice = 'IS_ANY_DEVICE' #

IdentityComparator.IsAnyIntegration

IsAnyIntegration = 'IS_ANY_INTEGRATION' #

IdentityComparator.IsAnyInvocation

IsAnyInvocation = 'IS_ANY_INVOCATION' #

IdentityComparator.IsAnyOrg

IsAnyOrg = 'IS_ANY_ORG' #

IdentityComparator.IsAnyUser

IsAnyUser = 'IS_ANY_USER' #

IdentityComparator.IsDevice

IsDevice = 'IS_DEVICE' #

IdentityComparator.IsIntegration

IsIntegration = 'IS_INTEGRATION' #

IdentityComparator.IsInvocation

IsInvocation = 'IS_INVOCATION' #

IdentityComparator.IsOrg

IsOrg = 'IS_ORG' #

IdentityComparator.IsUser

IsUser = 'IS_USER' #

IdentityFilter

class roboto.query.filters.IdentityFilter(/, **data)#View Source

Bases: _FilterBase

A principal-valued field, filtered by principal type.

Audit columns (created_by, modified_by) hold a fully-qualified principal string, so the operator names the type (IdentityComparator) and any values it takes are principals of that type — an IS_USER filter carrying a device: value is rejected, since it records an intent the picker cannot express and a query cannot satisfy.

Values are labeled options rather than bare strings: a principal id is not a name a reader can place, so the directory’s display name is captured alongside it at pick time.

Has no presence axis. Every write path stamps an audit principal, so the column is never null and a null check would be an operator that always answers the same way.

Parameters

data Any

Attributes

IdentityFilter.type

type Literal['identity'] = 'identity' #

IdentityFilter.values

values list[LabeledOption] = None #

IdentityOperators

class roboto.query.filters.IdentityOperators#View Source

Bases: NamedTuple

The operator pair one principal type contributes to an identity field’s menu.

Attributes

IdentityOperators.comparator

The value-bearing IS_<TYPE>.

IdentityOperators.preset

The valueless IS_ANY_<TYPE>.

LabeledOption

class roboto.query.filters.LabeledOption(/, **data)#View Source

Bases: pydantic.BaseModel

One option as it was picked: the value a query is built from, plus what the picker showed.

Both halves are stored because the label cannot be recovered later. An opaque value — user:usr_01J..., a tag id — renders as itself, and resolving it on load would mean a directory lookup per chip, against an org that whoever opens a shared View may not be able to read. Only value ever reaches a query.

Parameters

data Any

Attributes

LabeledOption.label

label str #

What the picker displayed when the author chose this option. Display only, never queried.

LabeledOption.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

LabeledOption.value

value str #

What the query is built from. A fully-qualified principal, for an identity filter.

METRIC_FIELD_PATTERN

roboto.query.filters.METRIC_FIELD_PATTERN: Final[str] = '^metric\\..+'#View Source

METRIC_FIELD_PREFIX

roboto.query.filters.METRIC_FIELD_PREFIX: Final[str] = 'metric.'#View Source

Prefix distinguishing a user-defined metric from an ordinary numeric property.

Metric filters store the prefixed form so that field means the same thing here as it does in a Condition, and translating a filter into a query copies the field across rather than special-casing it.

MetricField

type roboto.query.filters.MetricField = typing.Annotated[str, pydantic.StringConstraints(pattern=METRIC_FIELD_PATTERN)]#View Source

A metric’s dot-delimited path, carrying its metric. prefix.

MetricFilter

class roboto.query.filters.MetricFilter(/, **data)#View Source

Bases: _FilterBase

Ordering and equality over a user-defined metric.

Numeric in every respect except that field is a metric path. Kept a distinct variant so a client restoring a View knows to reopen the metric picker rather than the property form, which it cannot infer from the field name alone.

Carries the presence pair like any other scalar type. A session may simply have no such metric recorded, and the session query path answers that directly — it maps IS_NULL to a NOT EXISTS over the metrics table.

Parameters

data Any

Attributes

MetricFilter.field

The field being filtered, as the query layer addresses it.

MetricFilter.type

type Literal['metric'] = 'metric' #

MetricFilter.unit

unit str | None = None #

The metric’s unit, copied from its definition when the filter was built.

Denormalized for display: the filter chip renders it beside the value (“path_deviation > 1.5 m”) without looking the definition up. None when the definition declares no unit.

Being a copy, it goes stale if the definition’s unit later changes: a saved View renders the unit the filter was built with, not the current one.

MetricFilter.values

values list[float] = None #

NumericFilter

class roboto.query.filters.NumericFilter(/, **data)#View Source

Bases: _FilterBase

Ordering and equality over a numeric property.

Parameters

data Any

PRESENCE_COMPARATORS

roboto.query.filters.PRESENCE_COMPARATORS: Final[frozenset[roboto.query.conditions.Comparator]]#View Source

Null checks. Valueless: the comparator alone carries the question.

PRESET_COMPARATORS

roboto.query.filters.PRESET_COMPARATORS: Final[frozenset[FilterOnlyComparator]]#View Source

Relative windows. Valueless: the comparator alone carries the range.

SavedFilters

class roboto.query.filters.SavedFilters(/, **data)#View Source

Bases: pydantic.BaseModel

A complete set of filter controls, as saved.

Parameters

data Any

Attributes

SavedFilters.filters

filters list[Filter] = None #

The rows, in the order the author added them.

SavedFilters.match_mode

match_mode FilterMatchMode #

Whether the rows are combined with AND or OR.

Deliberately a single flag rather than a nested boolean expression. A Condition can express arbitrary nesting, but a filter UI cannot build one legibly, so this records the shape the UI actually offers.

SavedFilters.model_config

model_config #

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

SetFilter

class roboto.query.filters.SetFilter(/, **data)#View Source

Bases: _FilterBase

Membership in a collection-valued field, such as tags.

Has no presence axis: an empty collection is not the same as an absent one, and the UI offers no null check here.

Parameters

data Any

Attributes

SetFilter.type

type Literal['set'] = 'set' #

SetFilter.values

values list[str] = None #

StringFilter

class roboto.query.filters.StringFilter(/, **data)#View Source

comparators_by_type()

roboto.query.filters.comparators_by_type()#View Source

The operators each filter type offers, as wire values.

Derived from the models rather than restated, so it cannot fall out of step with what they actually accept. Two callers: anything building a filter that needs to know what is valid for a field type, and the drift check against the filter UI’s own copy of this vocabulary — there is no code generation between the two, so a test compares them.

Return type

dict[str, list[str]]

Was this page helpful?