dpmxl.diagnostics¶
Static checks for editors. See Build editor support.
dpmxl.diagnostics
¶
Static diagnostics: positioned problems in an expression, for editors.
diagnose reports what can be found without
report data. On its own it finds every syntax error, unknown functions,
calls with the wrong operands and selections without a table. Given table
layouts it also checks tables, rows, columns and sheets, open-table keys
and, when the layouts carry cell data types, operands of the wrong type.
Given the report parameters, it also reports names that resolve to nothing.
Severity
module-attribute
¶
error or warning; see Diagnostic.
LayoutLookup
module-attribute
¶
LayoutLookup = Callable[[str], TableLayout | None]
Returns a table's TableLayout, or None
for a table that does not exist, such as layouts.get for a dict.
DIAGNOSTIC_CODES
module-attribute
¶
DIAGNOSTIC_CODES = frozenset(
{
"syntax",
"unknown-function",
"operand-count",
"group-by",
"key-operand",
"missing-table",
"unknown-table",
"unknown-row",
"unknown-column",
"unknown-sheet",
"missing-row",
"missing-column",
"missing-sheet",
"open-row",
"open-column",
"open-sheet",
"empty-range",
"type-mismatch",
"unknown-key",
"unknown-name",
}
)
Every Diagnostic.code. Codes are stable;
messages may be reworded in minor releases.
Diagnostic
dataclass
¶
Diagnostic(
severity: Severity,
code: str,
message: str,
start: int,
end: int,
subject: str | None = None,
suggestion: str | None = None,
)
One problem in an expression, with the source text it concerns.
Attributes:
-
severity(Severity) –errorwhen evaluation would fail or select nothing as written;warningwhen the expression evaluates but probably does not mean what it says. -
code(str) –A stable identifier from
DIAGNOSTIC_CODES:syntax: the text does not parse;unknown-function;operand-countandgroup-by: a call with the wrong number of operands or agroup bythe function does not take;key-operand: no key name wheretime_shiftorannualiseneeds one;missing-table: a selection without a table;unknown-table: a table that does not exist;unknown-row,unknown-columnandunknown-sheet: a coordinate the table does not have, an error when no part of the selector matches and a warning when another part does;empty-range: the same for a range;missing-row,missing-columnandmissing-sheet: a code on an axis the table does not have;open-row,open-columnandopen-sheet: a code on an open axis, whose rows, columns or sheets have keys instead of codes. What a provider selects for such a code is up to it (aMemoryProviderignores the selector), so these are warnings, and they are not reported for a selector a sharedwithcontext applies;type-mismatch: an operand of the wrong data type;unknown-key: a name in a clause that is not a key of what the clause applies to (a warning where a report parameter may stand in and the parameters are not known);unknown-name: a name that is no report parameter or earlier assignment.
-
message(str) –What is wrong, in plain words.
-
start(int) –Zero-based offset of the first character concerned.
-
end(int) –Offset just past the last character; equals
startfor a problem at a position, such as the end of the expression. -
subject(str | None) –What the problem is about, when it names something: the function, table, coordinate, key or name as written, or the data type found;
Noneotherwise. -
suggestion(str | None) –A replacement for
expression[start:end]that likely fixes the problem, such assumforsumm;Nonewhen there is no likely fix.
pointer
¶
Render the source line and mark the text concerned.
Parameters:
-
expression(str) –The expression the diagnostic was found in.
Returns:
-
str(str) –Two lines for terminal output, as
-
str–
Examples:
diagnose
¶
diagnose(
expression: str,
layout: LayoutLookup | None = None,
*,
tables: Iterable[str] | None = None,
parameters: Iterable[str] | None = None,
program: bool = False,
) -> tuple[Diagnostic, ...]
Return the problems found in an expression without evaluating it.
Every syntax error is reported: after one, parsing resumes where the
enclosing construct can carry on, and an error caused by an earlier one
is left out. A construct that contains a syntax error is not checked
further. Selections inside with are checked with their context, and
a problem in the context is reported once, at the context.
Parameters:
-
expression(str) –A DPM-XL rule expression, or a script with
program=True. -
layout(LayoutLookup | None, default:None) –Looks up a table's
TableLayout, or returnsNonefor a table that does not exist. Without it, tables, coordinates, keys and data types are not checked. Table groups and operations are never checked. -
tables(Iterable[str] | None, default:None) –Every table code, to suggest one for an unknown table.
-
parameters(Iterable[str] | None, default:None) –Every report parameter name. With them, a name that is neither a parameter, nor assigned by an earlier statement, nor a key in a clause is an error; without them names are not checked outside clauses.
-
program(bool, default:False) –Accept a script (
;,:=and<-), asparse_programdoes; otherwise the text must be one expression, as forparse.
Returns:
-
Diagnostic–tuple[Diagnostic, ...]: Problems in source order; empty when none
-
...–were found.
Examples:
>>> for d in diagnose("summ({tC_01.00, r0010}) > 0 and"):
... print(d.start, d.end, d.code, d.message)
0 4 unknown-function unknown function 'summ'; did you mean 'sum'?
31 31 syntax expression ends where an operand is expected
>>> from dpmxl import TableLayout
>>> layouts = {"C_01.00": TableLayout("C_01.00", rows=("0010", "0020"))}
>>> for d in diagnose("{tC_01.00, r0011} = {tC_02.00, r0010}", layouts.get):
... print(d.start, d.end, d.message, d.suggestion)
11 16 row 0011 is not in table C_01.00; did you mean r0010? r0010
21 29 unknown table C_02.00 None