dpmxl.ast¶
The expression tree: frozen node classes with source spans. Language names the node each construct parses to.
dpmxl.ast
¶
Abstract syntax tree for DPM-XL expressions.
Every node keeps the half-open source span it was parsed from, so callers
can show the original operand text next to an evaluated value without
re-printing the expression.
Span
module-attribute
¶
Half-open (start, end) character offsets into the parsed source.
AxisName
module-attribute
¶
Name of a closed axis field of SelectionSpec.
AXIS_PREFIXES
module-attribute
¶
AXIS_PREFIXES: dict[str, AxisName] = {
"r": "rows",
"c": "columns",
"s": "sheets",
}
Axis letter (r, c, s) to its SelectionSpec field name.
AXIS_KEYS
module-attribute
¶
AXIS_KEYS: dict[AxisName, str] = {
"rows": "r",
"columns": "c",
"sheets": "s",
}
SelectionSpec axis field name to the record key it produces.
MISSING
module-attribute
¶
Marker for a default that was not written; it is falsy and differs from
a written default: null.
AxisSelector
dataclass
¶
AxisSelector(
wildcard: bool = False,
parts: tuple[str | tuple[str, str], ...] = (),
*,
span: Span = (0, 0),
spans: tuple[Span, ...] = (),
)
Selected coordinates on one table axis.
parts holds single codes ("0010") and inclusive ranges
(("0010", "0050")) as written, without the axis prefix. A range may
repeat the axis letter before its upper bound: r0010-r0050 is
("0010", "0050"). The letter is dropped only when the lower bound
does not start with it, so a code that does is read as written:
rr1-rr10 is ("r1", "rr10"); write rr1-r10 for ("r1",
"r10").
A parsed selector keeps its source positions; like node spans they take
no part in equality, hashing or repr, and selectors built directly
have none.
Attributes:
-
wildcard(bool) –Whether the selector is
*(every coordinate). -
parts(tuple[str | tuple[str, str], ...]) –Single codes and
(low, high)ranges. -
span(Span) –Source span of the whole selector, such as
r0010-0050or(r0010, r0020);(0, 0)when built directly. -
spans(tuple[Span, ...]) –Source span of each part, in the order of
parts; empty for a wildcard or a selector built directly.
Examples:
>>> from dpmxl import parse_selection
>>> rows = parse_selection("tT, (r0010, r0020-0050)").rows
>>> rows.parts, rows.span, rows.spans
(('0010', ('0020', '0050')), (4, 23), ((5, 10), (12, 22)))
span
class-attribute
instance-attribute
¶
span: Span = field(
default=(0, 0), compare=False, repr=False, kw_only=True
)
spans
class-attribute
instance-attribute
¶
spans: tuple[Span, ...] = field(
default=(), compare=False, repr=False, kw_only=True
)
text
¶
Render the selector in DPM-XL syntax.
Returns:
-
str(str) –For example
r*,r0010or(r0010, r0020-0050).
SelectionSpec
dataclass
¶
SelectionSpec(
table: str | None = None,
rows: AxisSelector | None = None,
columns: AxisSelector | None = None,
sheets: AxisSelector | None = None,
default: Literal_ | SetLiteral | _Missing = MISSING,
interval: bool | None = None,
table_group: str | None = None,
operation: str | None = None,
*,
source_span: Span = (0, 0),
)
Source, axis and option components of a {...} selection.
The source is one of table (tC_01.00), table_group
(gG_01) or operation (o_v1234, another operation's result);
the others are None.
Attributes:
-
table(str | None) –Table code, such as
C_01.00. -
rows(AxisSelector | None) –Row selector, or
Nonewhen not written. -
columns(AxisSelector | None) –Column selector, or
None. -
sheets(AxisSelector | None) –Sheet selector, or
None. -
default(Literal_ | SetLiteral | _Missing) –The
default:literal, orMISSINGwhen not written. -
interval(bool | None) –The
interval:option, orNonewhen not written. -
table_group(str | None) –Table group code of a
{g_...}selection. -
operation(str | None) –Operation code of an
{o_...}reference. -
source_span(Span) –Source span of the table, table group or operation reference, such as
tC_01.00;(0, 0)when there is none or the selection was built directly. Like the selectors' spans it takes no part in equality, hashing orrepr, andmerged_intokeeps the span of the source it keeps.
source_span
class-attribute
instance-attribute
¶
source_span: Span = field(
default=(0, 0), compare=False, repr=False, kw_only=True
)
merged_into
¶
merged_into(context: SelectionSpec) -> SelectionSpec
Return this selection completed by an inherited with context.
Returns:
-
SelectionSpec(SelectionSpec) –Components written here win over the context; a
-
SelectionSpec–source written here replaces the context's source.
Examples:
axis
¶
axis(name: AxisName) -> AxisSelector | None
Return the selector for one axis.
Returns:
-
AxisSelector | None–AxisSelector | None:
Nonewhen the axis was not written.
text
¶
Node
dataclass
¶
Node(*, span: Span = (0, 0))
Base class for expression nodes.
Every node has a public span: the half-open (start, end) character
offsets of its source in the parsed expression, so expression[start:end]
is the node's text. A parenthesized operand's span includes the
parentheses; a clause's span runs from its operand to the closing ].
Spans take no part in equality or hashing. Nodes built directly default to
(0, 0).
Literal_
dataclass
¶
Literal_(
value: Decimal | str | bool | date | Item | None,
kind: Literal[
"number",
"string",
"boolean",
"date",
"item",
"null",
],
*,
span: Span = (0, 0),
)
Item
dataclass
¶
An enumerated item literal such as [eba_qEC:qx01].
category is the namespace part without the eba_ prefix; it is
None for a bare legacy element reference such as [ei86].
Attributes:
-
category(str | None) –Category without
eba_, such asqEC, orNone. -
code(str) –Item code, such as
qx01.
parse
classmethod
¶
parse(text: str) -> Item
Parse prefix:code or a bare code.
Returns:
-
Item(Item) –Normalized item identity; the
eba_prefix is dropped.
Examples:
matches
¶
matches(other: Item) -> bool
Compare two items, ignoring a category missing on either side.
Returns:
-
bool(bool) –Whether both name the same item.
__str__
¶
Render category:code or the bare code.
Returns:
-
str(str) –The item text.
Selection
dataclass
¶
Selection(spec: SelectionSpec, *, span: Span = (0, 0))
Bases: Node
A {...} cell selection.
Attributes:
-
spec(SelectionSpec) –The selection's components as written (without the
withcontext; seereferences).
TypedParameter
dataclass
¶
TypedParameter(
name: str,
type: str,
default: Literal_ | SetLiteral | _Missing = MISSING,
*,
span: Span = (0, 0),
)
Bases: Node
{p_Name, type[, default: value]}: a typed report parameter.
type is one of PARAMETER_TYPES in lower case.
Attributes:
-
name(str) –Parameter name without the
p_prefix. -
type(str) –The declared type.
-
default(Literal_ | SetLiteral | _Missing) –The
default:value, orMISSING.
SetLiteral
dataclass
¶
Unary
dataclass
¶
In
dataclass
¶
Call
dataclass
¶
Call(
name: str,
args: tuple[Node, ...],
group_by: tuple[str, ...] | None = None,
*,
span: Span = (0, 0),
)
WindowBound
dataclass
¶
WindowBound(
kind: Literal[
"unbounded preceding",
"preceding",
"current data point",
"following",
"unbounded following",
],
offset: int = 0,
period: str | None = None,
)
One end of an analytic window.
kind is unbounded preceding, preceding, current data
point, following or unbounded following; offset counts
data points, or for a range window units of the order key, or of
period (A, S, Q, M, W, D) for a date key.
Attributes:
Window
dataclass
¶
Window(
unit: Literal["data points", "range"],
start: WindowBound,
end: WindowBound,
)
data points|range between start and end.
Attributes:
-
unit(Literal['data points', 'range']) –data pointsorrange. -
start(WindowBound) –The lower bound.
-
end(WindowBound) –The upper bound.
Analytic
dataclass
¶
Analytic(
name: str,
operand: Node,
partition_by: tuple[str, ...] = (),
order_by: tuple[tuple[str, bool], ...] = (),
window: Window | None = None,
*,
span: Span = (0, 0),
)
Bases: Node
name(operand over (partition by … order by … window)).
name is rank or an aggregate's call name (sum, count,
avg, max, min, median). order_by pairs each key with
whether it sorts descending. The result keeps the operand's records.
Attributes:
-
name(str) –rankor the aggregate's call name. -
operand(Node) –The aggregated expression.
-
partition_by(tuple[str, ...]) –Partition key names.
-
order_by(tuple[tuple[str, bool], ...]) –(key, descending)pairs. -
window(Window | None) –The window clause, or
Nonewhen not written.
Where
dataclass
¶
Get
dataclass
¶
Sub
dataclass
¶
Rename
dataclass
¶
With
dataclass
¶
With(
context: SelectionSpec,
body: Node,
condition: Node | None = None,
*,
span: Span = (0, 0),
)
Bases: Node
with {context} [where condition]: body.
The optional condition filters every selection evaluated in the body.
Attributes:
Assignment
dataclass
¶
PersistentAssignment
dataclass
¶
Program
dataclass
¶
Bases: Node
Statements separated by ;; the last one gives the result.
parse_program returns one;
parse returns a single expression instead.
Attributes:
-
statements(tuple[Node, ...]) –The statements in order.
children
¶
walk
¶
Return the node and all descendants in pre-order.
Returns:
-
list[Node]–list[Node]: Every node of the tree.
Examples:
>>> from dpmxl import parse
>>> expression = "with {tT, default: 0}: {r0010} > {r0020} * 1.1"
>>> [type(node).__name__ for node in walk(parse(expression))]
['With', 'Literal_', 'Binary', 'Selection', 'Binary', 'Selection', 'Literal_']
>>> [
... expression[slice(*node.span)]
... for node in walk(parse(expression))
... if type(node).__name__ == "Selection"
... ]
['{r0010}', '{r0020}']