dpmxl.provider¶
The data contract between the evaluator and a report. See Connect your data for a walkthrough of every method, optional hooks included.
dpmxl.provider
¶
Data access contract between the evaluator and a report.
The evaluator never reads report files. It asks a
DataProvider for the data points a selection covers and
for report-level facts such as filing indicators. A provider is responsible for:
- resolving table codes and axis selectors against the table definitions;
- returning every defined cell of a closed selection, with
value=Nonewhen the report has no fact for it, sodefaultandisnullwork; - returning one data point per reported key combination for open axes, with
the open key components in
DataPoint.keys.
MemoryProvider is a complete in-memory implementation
used by the tests and by tools that build reports programmatically.
CELL_TYPES
module-attribute
¶
Data types a TableLayout gives its cells.
CellQuery
dataclass
¶
CellQuery(
table: str,
rows: AxisSelector | None = None,
columns: AxisSelector | None = None,
sheets: AxisSelector | None = None,
)
A fully resolved selection: table plus optional axis selectors.
The evaluator passes one to
DataProvider.select after applying
the with context. Match coordinates with
axis_matcher.
Attributes:
-
table(str) –The table code, such as
C_01.00. -
rows(AxisSelector | None) –The row selector;
Nonewhen the selection names no rows, which selects every row. -
columns(AxisSelector | None) –The column selector, likewise.
-
sheets(AxisSelector | None) –The sheet selector, likewise.
DataPoint
dataclass
¶
DataPoint(
table: str,
row: str | None = None,
column: str | None = None,
sheet: str | None = None,
keys: Mapping[str, Value] = dict(),
value: Value = None,
ref: Hashable | None = None,
)
One selected cell, and for open tables one reported key combination.
ref is an opaque provider identity (for example a cell ID) that is
passed back in evaluation results so callers can highlight the cell.
Attributes:
-
table(str) –The table code.
-
row(str | None) –The row code, or
Nonefor a table without rows. -
column(str | None) –The column code, or
None. -
sheet(str | None) –The sheet code, or
None. -
keys(Mapping[str, Value]) –Open key components by name (such as
{"qCPI": "LEI-A"}); empty for closed tables. -
value(Value) –The reported value, or
Nonewhen nothing was reported. -
ref(Hashable | None) –Any hashable identity of the cell; points read by
time_shiftfrom another report carry anEarlierRef.
DataProvider
¶
Bases: Protocol
Source of report data for one evaluation.
Three methods are required. select resolves a
CellQuery against the table definitions
(axis_matcher and
normalize_code implement range and
code matching) and returns:
- for a closed table, every defined cell the selection covers, with
value=Nonewhere the report has no fact, sodefaultandisnullwork; - for an open table, one point per reported key combination (times the
selected closed coordinates), with the key components in
DataPoint.keys;
and raises LookupError for a table the release does not define (the
rule's status is then error). table_reported answers {v_TABLE}
and parameter answers {vName} and {p_Name, type}.
A provider may also define these optional methods:
open_keys(table: str) -> Sequence[str]: the open key names of a table. Without it, an open table with no reported rows yields a selection without keys; with it, the selection keeps the table's key structure and is empty, as the specification requires.table_group(code: str) -> Sequence[str] | None: the table codes of a table group, for{g_Group, ...}selections.operation(code: str) -> str | None: the expression of another operation, for{o_Code, ...}references.earlier_report(period: str, count: int) -> DataProvider | None: the reportcountperiods earlier (later when negative), whereperiodisA,S,Q,M,WorD, fortime_shift.
Without the optional method, or when it returns None, rules that need
it are unsupported. DataProvider is runtime_checkable:
isinstance checks the three required methods only.
A provider shared by several threads must be safe to read concurrently.
select
¶
Return the data points covered by a selection.
Raises:
-
LookupError–If the table does not exist in the release.
table_reported
¶
Return whether the report's filing indicators include table.
table is the code written in {v_...}, usually a template code
such as C_01.00. Returns None when the provider cannot tell,
which makes {v_...} null.
EarlierRef
dataclass
¶
The ref of a data point that time_shift read from another report.
It wraps the earlier report's own ref with the shift, so the point
stays distinct from the current report's cell with the same ref.
Attributes:
EarlierReport
¶
EarlierReport(
provider: DataProvider, period: str, count: int
)
The report time_shift reads, marking its points' refs.
Every data point it selects carries an EarlierRef
instead of the provider's ref (points without a ref keep None); every
other method, optional ones included, is the wrapped provider's.
Wrap a provider.
Parameters:
-
provider(DataProvider) –The earlier report.
-
period(str) –The
time_shiftperiod, such asQ. -
count(int) –The number of periods.
select
¶
Return the earlier report's points with marked refs.
Returns:
-
Sequence[DataPoint]–Sequence[DataPoint]: The points.
table_reported
¶
Return the earlier report's filing indicator.
Returns:
-
bool | None–bool | None: Filing-indicator state.
__getattr__
¶
Delegate optional provider methods.
Returns:
-
Any(Any) –The wrapped provider's attribute.
AxisMatcher
dataclass
¶
AxisMatcher(
codes: frozenset[str],
numeric_ranges: tuple[tuple[int, int], ...],
text_ranges: tuple[tuple[str, str], ...],
wildcard: bool = False,
)
A compiled axis selector: exact codes plus inclusive ranges.
Build one with axis_matcher and call it
with a coordinate code.
Attributes:
-
codes(frozenset[str]) –Normalized single codes.
-
numeric_ranges(tuple[tuple[int, int], ...]) –Inclusive ranges with numeric bounds.
-
text_ranges(tuple[tuple[str, str], ...]) –Inclusive ranges with text bounds, compared as text.
-
wildcard(bool) –Whether every coordinate is selected.
__call__
¶
Return whether a coordinate is selected.
Returns:
-
bool(bool) –Whether
codeis covered.
TableLayout
dataclass
¶
TableLayout(
code: str,
rows: tuple[str, ...] = (),
columns: tuple[str, ...] = (),
sheets: tuple[str, ...] = (),
open_keys: tuple[str, ...] = (),
template: str | None = None,
open_axes: tuple[AxisName, ...] = (),
data_types: Mapping[
tuple[str | None, str | None, str | None], str
] = dict(),
)
The coordinates, open keys and cell data types of one table.
MemoryProvider serves cells from
layouts, and diagnose checks selections
against them. An axis is closed (its rows, columns or sheets
codes), open (named in open_axes: its rows, columns or sheets are
identified by the open_keys, not by codes) or absent (neither).
When a table has been split into several, as when C_02.00 became
C_02.00.a and C_02.00.b, rules may still select the original,
abstract code; describe it with the union of its parts' coordinates.
Attributes:
-
code(str) –The table code, such as
C_01.00. -
rows(tuple[str, ...]) –Row codes; empty for a table without closed rows.
-
columns(tuple[str, ...]) –Column codes; empty for a table without closed columns.
-
sheets(tuple[str, ...]) –Sheet codes; empty for a table without closed sheets.
-
open_keys(tuple[str, ...]) –Open key names, such as
("qCPI",); empty for a closed table. -
template(str | None) –The template code when it differs from
code, so{v_TEMPLATE}holds when any of its tables was reported. -
open_axes(tuple[AxisName, ...]) –The open axes among
rows,columnsandsheets. Optional: without it, an axis without codes of a table with open keys is taken to be open or absent, and selections of it are not checked. What a provider selects for a code on an open or absent axis is up to it: aMemoryProviderignores the selector, other providers may select nothing.diagnosereports such a code as a warning. -
data_types(Mapping[tuple[str | None, str | None, str | None], str]) –The data type of each cell by its
(row, column, sheet), withNonefor an open or absent axis:number,integer,string,date,booleanoritem. Optional;diagnoseuses it to find operands of the wrong type. It may be partial: a selection that covers a cell without a type has no known type, so it is not checked. It takes no part in equality.
Raises:
-
ValueError–For an unknown axis in
open_axes, an open axis with codes, or an unknown data type.
Examples:
>>> layout = TableLayout(
... "C_27.00",
... columns=("0010", "0020"),
... open_keys=("qCPI",),
... open_axes=("rows",),
... data_types={(None, "0010", None): "number"},
... )
>>> layout.open_axes, layout.data_types[None, "0010", None]
(('rows',), 'number')
data_types
class-attribute
instance-attribute
¶
data_types: Mapping[
tuple[str | None, str | None, str | None], str
] = field(default_factory=dict, compare=False, repr=False)
__post_init__
¶
Check the open axes and data types.
Raises:
-
ValueError–For an unknown or coded open axis, or an unknown data type.
coordinates
¶
Yield every closed (row, column, sheet) combination.
Yields:
-
Iterable[tuple[str | None, str | None, str | None]]–tuple[str | None, str | None, str | None]: One cell position.
MemoryProvider
¶
MemoryProvider(
tables: Iterable[TableLayout],
values: Mapping[CellKey, Value],
*,
reported: Iterable[str] | None = None,
parameters: Mapping[str, Value] | None = None,
table_groups: Mapping[str, Sequence[str]] | None = None,
operations: Mapping[str, str] | None = None,
earlier_reports: Mapping[tuple[str, int], DataProvider]
| None = None,
)
Provider over in-memory table layouts and values.
Values are keyed by (table, row, column, sheet, keys) where keys is
a tuple of (name, value) pairs for open tables (empty for closed ones).
Absent tables in reported are treated as not reported. Every optional
DataProvider method is implemented. Each
point's ref is its value key.
A MemoryProvider is safe to read from several threads at once.
Examples:
>>> from dpmxl import CellQuery, Number
>>> closed = TableLayout("C_01.00", rows=("0010", "0020"), columns=("0010",))
>>> open_ = TableLayout("C_27.00", columns=("0010",), open_keys=("qCPI",))
>>> provider = MemoryProvider(
... [closed, open_],
... {
... ("C_01.00", "0010", "0010", None, ()): Number.of(100, 0),
... ("C_27.00", None, "0010", None, (("qCPI", "A"),)): Number.of(1, 0),
... },
... parameters={"refPeriod": "2026-12-31"},
... )
>>> [(p.row, p.value) for p in provider.select(CellQuery("C_01.00"))][1]
('0020', None)
>>> [p.keys for p in provider.select(CellQuery("C_27.00"))]
[{'qCPI': 'A'}]
>>> provider.table_reported("C_27.00"), provider.parameter("refPeriod")
(True, '2026-12-31')
Index tables and values.
Parameters:
-
tables(Iterable[TableLayout]) –Table layouts.
-
values(Mapping[CellKey, Value]) –Cell values; see the class docstring for the key shape.
-
reported(Iterable[str] | None, default:None) –Template or table codes with a positive filing indicator; defaults to every table that has a value.
-
parameters(Mapping[str, Value] | None, default:None) –Report parameters such as
refPeriod. -
table_groups(Mapping[str, Sequence[str]] | None, default:None) –Table codes by table group code.
-
operations(Mapping[str, str] | None, default:None) –Operation expressions by operation code.
-
earlier_reports(Mapping[tuple[str, int], DataProvider] | None, default:None) –Reports of other periods by
(period, count), such as("A", 1)for the previous year.
reported
instance-attribute
¶
select
¶
Return closed cells, and one point per reported open key set.
Returns:
-
Sequence[DataPoint]–Sequence[DataPoint]: Selected data points.
Raises:
-
LookupError–If the table is unknown.
open_keys
¶
Return a table's open key names.
Returns:
-
tuple[str, ...]–tuple[str, ...]: Key names; empty for closed or unknown tables.
table_reported
¶
Return whether a table or its template was reported.
Returns:
-
bool | None–bool | None: Filing-indicator state.
table_group
¶
Return the table codes of a table group.
Returns:
-
Sequence[str] | None–Sequence[str] | None: The tables, or
Nonefor an unknown group.
earlier_report
¶
earlier_report(
period: str, count: int
) -> DataProvider | None
Return the report count periods earlier.
Returns:
-
DataProvider | None–DataProvider | None: The report, or
Nonewhen not given.
operation
¶
Return the expression of an operation.
Returns:
-
str | None–str | None: The expression, or
Nonefor an unknown operation.
normalize_code
cached
¶
Normalize an axis code for comparison.
Numeric codes are compared as numbers padded to four digits, so r310
in an older rule matches row 0310. Results are memoized: a report's
rules normalize the same few thousand codes millions of times.
Returns:
-
str(str) –A canonical code.
Examples:
axis_matcher
cached
¶
axis_matcher(selector: AxisSelector | None) -> AxisMatcher
Compile a selector once for repeated matching.
Returns:
-
AxisMatcher(AxisMatcher) –A callable matcher;
Noneand wildcards select all.
Examples:
axis_matches
¶
axis_matches(
code: str | None, selector: AxisSelector | None
) -> bool
Return whether a coordinate is selected.
None selectors and wildcards select every coordinate. Ranges are
inclusive and compare numerically when both bounds are numeric.
Returns:
-
bool(bool) –Whether
codeis covered byselector.
Examples: