Filter

Parse and evaluate Haystack filter expressions. parse() produces an AST, evaluate() tests against dicts, evaluate_grid() filters grids.

Haystack filter expression parser and evaluator.

Parse filter strings into AST nodes, then evaluate them against entity dicts or grids.

Usage:

from hs_py.filter import parse, evaluate, evaluate_grid

ast = parse("point and sensor")
assert evaluate(ast, {"point": MARKER, "sensor": MARKER})

filtered = evaluate_grid(ast, grid)

AST

Filter AST nodes: Has, Missing, Cmp, And, Or, Path.

Filter expression AST node types.

Defines the abstract syntax tree produced by the filter parser. Each node is a frozen dataclass for immutability and pattern matching.

See: https://project-haystack.org/doc/docHaystack/Filters

class hs_py.filter.ast.And(left, right)[source]

Bases: object

Logical AND of two filter nodes.

Parameters:
left: Has | Missing | Cmp | And | Or

Left operand.

right: Has | Missing | Cmp | And | Or

Right operand.

class hs_py.filter.ast.Cmp(path, op, val)[source]

Bases: object

Comparison of a tag path to a literal value.

Parameters:
path: Path

Left-hand tag path.

op: CmpOp

Comparison operator.

val: Any

Right-hand literal value.

class hs_py.filter.ast.CmpOp(*values)[source]

Bases: Enum

Comparison operators for filter expressions.

EQ = '=='

Equal (==).

NE = '!='

Not equal (!=).

LT = '<'

Less than (<).

LE = '<='

Less than or equal (<=).

GT = '>'

Greater than (>).

GE = '>='

Greater than or equal (>=).

class hs_py.filter.ast.Has(path)[source]

Bases: object

Tag existence check (path).

Parameters:

path (Path)

path: Path

Tag path to test for presence.

class hs_py.filter.ast.Missing(path)[source]

Bases: object

Tag absence check (not path).

Parameters:

path (Path)

path: Path

Tag path to test for absence.

hs_py.filter.ast.Node = hs_py.filter.ast.Has | hs_py.filter.ast.Missing | hs_py.filter.ast.Cmp | hs_py.filter.ast.And | hs_py.filter.ast.Or

Union of all filter AST node types.

class hs_py.filter.ast.Or(left, right)[source]

Bases: object

Logical OR of two filter nodes.

Parameters:
left: Has | Missing | Cmp | And | Or

Left operand.

right: Has | Missing | Cmp | And | Or

Right operand.

class hs_py.filter.ast.Path(names)[source]

Bases: object

Tag path expression (e.g. equipRef->siteRef->dis).

Single-segment paths contain one name. Multi-segment paths use the -> dereference operator to navigate through Ref-valued tags.

Parameters:

names (tuple[str, ...])

names: tuple[str, ...]

Ordered path segments (at least one).

Lexer

Tokenizer for Haystack filter expressions.

Tokenizer for Haystack filter expressions.

Converts a filter string into a sequence of typed tokens for the parser.

class hs_py.filter.lexer.Lexer(text)[source]

Bases: object

Tokenizer for Haystack filter strings.

Parameters:

text (str)

tokenize()[source]

Tokenize the full input and return a list of Token instances.

Return type:

list[Token]

Returns:

Token list ending with an EOF token.

class hs_py.filter.lexer.Token(type, val, pos)[source]

Bases: object

A single token from the filter lexer.

Parameters:
type: TokenType

Token type discriminator.

val: Any

Token value (string, number tuple, boolean, or None).

pos: int

Character offset in the source text.

class hs_py.filter.lexer.TokenType(*values)[source]

Bases: Enum

Token types produced by the filter lexer.

IDENT = 1
BOOL = 2
STR = 3
NUMBER = 4
DATE = 5
TIME = 6
DATETIME = 7
URI = 8
REF = 9
SYMBOL = 10
AND = 11
OR = 12
NOT = 13
EQ = 14
NE = 15
LT = 16
LE = 17
GT = 18
GE = 19
LPAREN = 20
RPAREN = 21
ARROW = 22
EOF = 23

Parser

Recursive descent parser producing filter AST.

Recursive descent parser for Haystack filter expressions.

Parses a filter string into an AST of hs_py.filter.ast nodes with properly typed Haystack values.

Grammar:

filter   = condOr
condOr   = condAnd ("or" condAnd)*
condAnd  = term ("and" term)*
term     = "(" condOr ")" | "not" path | path [cmpOp val]
path     = name ("->" name)*
cmpOp    = "==" | "!=" | "<" | "<=" | ">" | ">="
val      = bool | str | number | date | time | dateTime | uri | ref | symbol

See: https://project-haystack.org/doc/docHaystack/Filters

exception hs_py.filter.parser.ParseError[source]

Bases: ValueError

Raised when a filter string cannot be parsed.

hs_py.filter.parser.parse(text)[source]

Parse a Haystack filter string into an AST.

Results are cached for repeated filter expressions.

Parameters:

text (str) – Filter expression string.

Return type:

Has | Missing | Cmp | And | Or

Returns:

Root AST node.

Raises:

ParseError – If the filter string is invalid or too long.

Evaluator

Evaluate filter AST against dicts and grids.

Evaluate Haystack filter AST nodes against entity dicts.

Supports single-segment and multi-segment (dereference) path expressions. Multi-segment paths require a resolver callback to look up Refs.

hs_py.filter.eval.Resolver

Callback type for resolving a Ref to an entity dict. Returns None if the Ref cannot be resolved.

alias of Callable[[Ref], dict[str, Any] | None]

hs_py.filter.eval.evaluate(node, entity, resolver=None)[source]

Evaluate a filter AST against an entity dict.

Parameters:
Return type:

bool

Returns:

True if the entity matches the filter.

hs_py.filter.eval.evaluate_grid(node, grid, resolver=None)[source]

Filter a grid, returning only rows that match the filter.

Parameters:
  • node (Has | Missing | Cmp | And | Or) – Root of the filter AST.

  • grid (Grid) – Grid to filter.

  • resolver (Callable[[Ref], dict[str, Any] | None] | None (default: None)) – Optional callback to resolve Refs for multi-segment paths. If not provided and the grid has an id column, an auto-resolver is created from the grid’s rows.

Return type:

Grid

Returns:

New Grid containing only matching rows.