Skip to content

Python API

The public API is the names in dpmsynth.__all__, all on this page and covered by the stability policy. They are defined in dpmsynth.template, dpmsynth.generator and dpmsynth.scale; import them from dpmsynth. Names that start with an underscore, such as the private methods of SyntheticData, are internal.

from dpmxbrl import write_xbrl_csv

from dpmsynth import generate, load_template, write_scaled_package

result = generate(load_template("sample.json"), seed=7)
write_xbrl_csv(result.report, "report.zip")
written = write_scaled_package(result.data, "big.zip", rows=10_000)
print(result.passed, result.failed, written)
8 [] {'S_01.00': 14, 'S_02.00.a': 4, 'S_03.00': 10000}

Thread safety

generate keeps no shared state, so several templates may be generated in parallel threads; it is CPU-bound, so processes run faster. A SyntheticData is changed while it is generated and is safe to read from several threads afterwards; templates are immutable.

Templates

dpmsynth.load_template

load_template(
    source: str | PathLike[str] | Mapping[str, Any],
) -> ModuleTemplate

Load and validate a template from a JSON file or a parsed document.

Fields this version does not know are ignored, so newer exports still load.

Parameters:

  • source (str | PathLike[str] | Mapping[str, Any]) –

    A path to a JSON file, or the document as a mapping.

Returns:

Raises:

  • TemplateError –

    If the file cannot be read, is not JSON, or the document is not a valid dpm-synth-template/1 template.

Examples:

>>> template = load_template("minimal.json")
>>> template.module, len(template.tables), len(template.rules)
('DEMO', 1, 2)

dpmsynth.ModuleTemplate dataclass

ModuleTemplate(
    release: str,
    module: str,
    entry_point: str | None,
    tables: tuple[TemplateTable, ...],
    rules: tuple[TemplateRule, ...],
    reference_date: date | None = None,
    decimals: Mapping[str, int] = dict(),
)

Everything needed to generate one module's report.

Build one with load_template.

Attributes:

  • release (str) –

    The DPM release, such as 4.3.

  • module (str) –

    The module code, such as COREP_OF.

  • entry_point (str | None) –

    The module's entry point, written to report.json.

  • tables (tuple[TemplateTable, ...]) –

    The module's tables.

  • rules (tuple[TemplateRule, ...]) –

    The rules the report should satisfy.

  • reference_date (date | None) –

    The report's reference date; 2026-12-31 when None.

  • decimals (Mapping[str, int]) –

    Reporting decimals by data type code; m 0, p 4, i 0 and r 2 unless given.

release instance-attribute

release: str

module instance-attribute

module: str

entry_point instance-attribute

entry_point: str | None

tables instance-attribute

tables: tuple[TemplateTable, ...]

rules instance-attribute

rules: tuple[TemplateRule, ...]

reference_date class-attribute instance-attribute

reference_date: date | None = None

decimals class-attribute instance-attribute

decimals: Mapping[str, int] = field(default_factory=dict)

table

table(code: str) -> TemplateTable | None

Return a table by code, ignoring case.

Returns:

  • TemplateTable | None –

    TemplateTable | None: The table, or None.

Examples:

>>> template = load_template("minimal.json")
>>> template.table("t_01.00").code
'T_01.00'

dpmsynth.TemplateTable dataclass

TemplateTable(
    code: str,
    filing_indicator: str,
    cells: tuple[TemplateCell, ...],
    open_keys: tuple[OpenKey, ...] = (),
)

A table, its filing indicator, open keys and cells.

Attributes:

  • code (str) –

    The table code, such as C_07.00.a; it names the CSV file.

  • filing_indicator (str) –

    The filing indicator the table is reported under.

  • cells (tuple[TemplateCell, ...]) –

    The reportable cells.

  • open_keys (tuple[OpenKey, ...]) –

    The open-axis key columns; empty for a closed table.

code instance-attribute

code: str

filing_indicator instance-attribute

filing_indicator: str

cells instance-attribute

cells: tuple[TemplateCell, ...]

open_keys class-attribute instance-attribute

open_keys: tuple[OpenKey, ...] = ()

dpmsynth.OpenKey dataclass

OpenKey(
    code: str,
    column: str,
    items: tuple[str, ...] | None = None,
)

An open-axis key column of a table.

Attributes:

  • code (str) –

    The key's property code, as rules name it, such as qEBB.

  • column (str) –

    The column of the key in the table's CSV file.

  • items (tuple[str, ...] | None) –

    Allowed item qnames for an enumerated key; None for a typed key, which gets generated identifiers.

code instance-attribute

code: str

column instance-attribute

column: str

items class-attribute instance-attribute

items: tuple[str, ...] | None = None

dpmsynth.TemplateCell dataclass

TemplateCell(
    id: str,
    datapoint: str,
    data_type: str | None,
    row: str | None = None,
    column: str | None = None,
    sheet: str | None = None,
    items: tuple[str, ...] | None = None,
)

One reportable cell and the datapoint that carries its value.

Attributes:

  • id (str) –

    An identifier of the cell, unique within the template.

  • datapoint (str) –

    The datapoint code written in the datapoint column.

  • data_type (str | None) –

    The DPM data type code, such as m or e; None or an unknown code is text.

  • row (str | None) –

    The row code, such as 0010; None for a table without rows, * for every row of an open table.

  • column (str | None) –

    The column code.

  • sheet (str | None) –

    The sheet code, * for every sheet, or None.

  • items (tuple[str, ...] | None) –

    Allowed item qnames of an enumerated cell.

id instance-attribute

id: str

datapoint instance-attribute

datapoint: str

data_type instance-attribute

data_type: str | None

row class-attribute instance-attribute

row: str | None = None

column class-attribute instance-attribute

column: str | None = None

sheet class-attribute instance-attribute

sheet: str | None = None

items class-attribute instance-attribute

items: tuple[str, ...] | None = None

dpmsynth.TemplateRule dataclass

TemplateRule(
    code: str,
    expression: str,
    precondition: str | None = None,
    source: str = "eba",
)

A validation rule with its precondition.

Attributes:

  • code (str) –

    The rule code, such as v0001_m.

  • expression (str) –

    The DPM-XL expression.

  • precondition (str | None) –

    An optional DPM-XL precondition, such as {v_C_01.00}.

  • source (str) –

    Who defined the rule, such as eba.

code instance-attribute

code: str

expression instance-attribute

expression: str

precondition class-attribute instance-attribute

precondition: str | None = None

source class-attribute instance-attribute

source: str = 'eba'

dpmsynth.TemplateError

Bases: ValueError

Raised when a template cannot be read or is not a valid template.

The message names the offending field by its path in the document, such as tables[2].cells[0].datapoint.

Examples:

>>> load_template({"format": "dpm-synth-template/1", "module": "M"})
Traceback (most recent call last):
...
dpmsynth.template.TemplateError: release: required

dpmsynth.TEMPLATE_FORMAT module-attribute

TEMPLATE_FORMAT = 'dpm-synth-template/1'

The format value of the templates this version reads.

Generating

dpmsynth.generate

generate(
    template: ModuleTemplate,
    *,
    seed: int = 0,
    open_rows: int = 2,
    max_rounds: int = 40,
    entity: str = DEFAULT_ENTITY,
    reporting_level: str = "CON",
    reference_date: date | None = None,
) -> GenerationResult

Generate a report for template that satisfies as many rules as it can.

Parameters:

  • template (ModuleTemplate) –

    Module template, from load_template.

  • seed (int, default: 0 ) –

    Random seed; the same seed, template, options and versions give the same report.

  • open_rows (int, default: 2 ) –

    Key rows per open table, from 1 to MAX_OPEN_ROWS (1,000). Enumerated keys take their allowed items in order, so a table whose keys allow fewer combinations gets fewer rows.

  • max_rounds (int, default: 40 ) –

    Upper bound on evaluate-and-repair rounds; 0 evaluates the initial values only.

  • entity (str, default: DEFAULT_ENTITY ) –

    LEI of the reporting entity.

  • reporting_level (str, default: 'CON' ) –

    Suffix of the entity identifier, such as CON or IND; also the ReportingLevel parameter, in lower case.

  • reference_date (date | None, default: None ) –

    Overrides the template's reference date.

Returns:

  • GenerationResult ( GenerationResult ) –

    The report and the final rule status.

Raises:

  • ValueError –

    If open_rows or max_rounds is out of range, or entity or reporting_level is not an identifier.

Examples:

>>> from dpmsynth import load_template
>>> result = generate(load_template("minimal.json"), seed=7)
>>> result.passed, result.failed
(2, [])
>>> result.report.entity_id
'SYNTHETICDPMXL000002.CON'

dpmsynth.GenerationResult dataclass

GenerationResult(
    report: Report,
    data: SyntheticData,
    rules: int,
    passed: int,
    failed: list[str],
    not_evaluated: dict[str, str],
    not_applicable: list[str],
    rounds: int,
    repairs: int,
    history: list[int] = list(),
)

The generated report and how far the repair loop got.

passed, failed, not_evaluated and not_applicable together count every rule of the template once.

Attributes:

  • report (Report) –

    The report, ready for dpmxbrl.write_xbrl_csv.

  • data (SyntheticData) –

    The generated values, a dpm-xl data provider; pass it to write_scaled_package or evaluate rules on it.

  • rules (int) –

    Rules in the template.

  • passed (int) –

    Rules that pass on the final, rounded values.

  • failed (list[str]) –

    Codes of the rules that still fail.

  • not_evaluated (dict[str, str]) –

    Rules dpm-xl could not evaluate, such as time_shift without a previous report or a syntax error, with the reason, by rule code.

  • not_applicable (list[str]) –

    Codes of the rules whose precondition is false or that select no cell of the template.

  • rounds (int) –

    Evaluate-and-repair rounds run.

  • repairs (int) –

    Failing records repaired over all rounds.

  • history (list[int]) –

    Failing rules at the start of each round.

report instance-attribute

report: Report

data instance-attribute

rules instance-attribute

rules: int

passed instance-attribute

passed: int

failed instance-attribute

failed: list[str]

not_evaluated instance-attribute

not_evaluated: dict[str, str]

not_applicable instance-attribute

not_applicable: list[str]

rounds instance-attribute

rounds: int

repairs instance-attribute

repairs: int

history class-attribute instance-attribute

history: list[int] = field(default_factory=list)

dpmsynth.SyntheticData

SyntheticData(
    template: ModuleTemplate,
    rng: Random,
    open_rows: int,
    *,
    entity: str = DEFAULT_ENTITY,
    reporting_level: str = "CON",
)

Generated values for a template, readable as a dpm-xl data provider.

generate creates and repairs one; it is GenerationResult.data. It implements the dpmxl.DataProvider protocol, with the optional open_keys, so dpmxl.evaluate_rule(expression, data) evaluates any rule on the generated values.

Attributes:

  • template –

    The template, with the reference date the report uses.

  • values (dict[Slot, Value]) –

    Cell values by (datapoint, keys), where keys is a tuple of (key code, value) pairs of an open table's row, and () for a closed table. Numbers are dpmxl.Number, enumerated values dpmxl.Item.

  • key_rows (dict[str, list[tuple[tuple[str, Any], ...]]]) –

    Key rows by table code; [()] for a closed table.

  • entity –

    The LEI of the reporting entity.

  • reporting_level –

    CON or IND, the suffix of the entity identifier and the ReportingLevel parameter.

  • decimals (dict[str, int]) –

    Reporting decimals by data type code.

Create initial values and open-table key rows.

Parameters:

  • template (ModuleTemplate) –

    Module template.

  • rng (Random) –

    Random source.

  • open_rows (int) –

    Key rows to generate per open table.

  • entity (str, default: DEFAULT_ENTITY ) –

    LEI of the reporting entity.

  • reporting_level (str, default: 'CON' ) –

    Suffix of the entity identifier.

template instance-attribute

template = template

rng instance-attribute

rng = rng

entity instance-attribute

entity = entity

reporting_level instance-attribute

reporting_level = reporting_level

decimals instance-attribute

decimals: dict[str, int] = {
    **_DEFAULT_DECIMALS,
    **template.decimals,
}

values instance-attribute

values: dict[Slot, Value] = {}

key_rows instance-attribute

key_rows: dict[str, list[tuple[tuple[str, Any], ...]]] = {}

select

select(query: CellQuery) -> Sequence[DataPoint]

Return the selected cells for every key row of the table.

Numbers carry their reporting decimals, so rules are judged with the same tolerance as the written report.

Returns:

  • Sequence[DataPoint] –

    Sequence[DataPoint]: Points whose ref is the

  • Sequence[DataPoint] –

    (datapoint, keys) slot.

Raises:

  • LookupError –

    If the table is not in the template.

table_reported

table_reported(table: str) -> bool | None

Whether a table or filing indicator is in the template.

Every table of the template is reported.

Returns:

  • bool | None –

    bool | None: Whether a table code, a filing indicator or a table

  • bool | None –

    under a template code such as C_07.00 matches, ignoring case.

parameter

parameter(name: str) -> Value

Return a report parameter.

Returns:

  • Value ( Value ) –

    refPeriod (the reference date) or ReportingLevel

  • Value –

    (con or ind); otherwise None.

open_keys

open_keys(table: str) -> tuple[str, ...]

Return the open key codes of a table.

Returns:

  • tuple[str, ...] –

    tuple[str, ...]: Key codes; empty for a closed or unknown table.

dpmsynth.DEFAULT_ENTITY module-attribute

DEFAULT_ENTITY = 'SYNTHETICDPMXL000002'

The fictional LEI that reports are generated for unless told otherwise.

dpmsynth.DEFAULT_REFERENCE_DATE module-attribute

DEFAULT_REFERENCE_DATE = date(2026, 12, 31)

The reference date of a template that gives none.

dpmsynth.LEI_PREFIX module-attribute

LEI_PREFIX = 'SYNTH'

The prefix of every LEI-shaped identifier dpm-synth generates.

Generated identifiers are SYNTH followed by 13 letters and digits and two ISO 17442 check digits, so they pass LEI validation but are visibly fictional and cannot coincide with an entity's real LEI by chance.

dpmsynth.MAX_OPEN_ROWS module-attribute

MAX_OPEN_ROWS = 1000

The most key rows per open table that generate solves.

Every rule is evaluated on every key row in every round, so the time grows with the rows; for larger tables, write a scaled package instead.

Writing

dpmsynth.build_report

build_report(data: SyntheticData) -> Report

Turn generated values into a report that dpm-xbrl can write.

Facts follow the EBA xBRL-CSV convention: a datapoint and factValue per cell, with the open keys of the row. The entity is <entity>.<reporting level> in the reporting-subject scheme, every table's filing indicator is reported, and a decimals* parameter is set for each numeric data type the template uses. generate calls it; call it yourself after changing data.values.

Parameters:

  • data (SyntheticData) –

    Generated values, GenerationResult.data.

Returns:

  • Report ( Report ) –

    The report, for dpmxbrl.write_xbrl_csv.

Examples:

>>> from dpmsynth import generate, load_template
>>> data = generate(load_template("minimal.json"), seed=7).data
>>> report = build_report(data)
>>> [fact.datapoint for fact in report.facts]
['dp1001', 'dp1002', 'dp1003']

dpmsynth.write_scaled_package

write_scaled_package(
    data: SyntheticData,
    target: str | PathLike[str],
    *,
    rows: int | Mapping[str, int],
) -> dict[str, int]

Write an xBRL-CSV package with every open table scaled to rows key rows.

Closed tables are written as generated. Each open table gets rows key rows, whose values repeat the generated rows in turn. Typed keys get new identifiers; enumerated keys keep the values of the generated row that is repeated, so rules that filter on them still hold, and a table with only enumerated keys keeps its generated rows. The package is laid out, named and described exactly as dpmxbrl.write_xbrl_csv writes the unscaled report, but tables are streamed to the ZIP file, so memory stays flat.

Parameters:

  • data (SyntheticData) –

    Generated values, GenerationResult.data.

  • target (str | PathLike[str]) –

    ZIP file to write; its name without .zip names the package's root folder.

  • rows (int | Mapping[str, int]) –

    Key rows per open table, or a mapping of table code to rows; tables missing from the mapping keep their generated rows.

Returns:

  • dict[str, int] –

    dict[str, int]: Fact rows written per table code.

Raises:

  • ValueError –

    If a row count is not a whole number of 1 or more.

  • ReportError –

    If dpm-xbrl cannot write the package header.

  • OSError –

    If the file cannot be written.

Examples:

>>> from dpmsynth import generate, load_template
>>> result = generate(load_template("sample.json"), seed=7)
>>> written = write_scaled_package(result.data, "big.zip", rows=1000)
>>> written["S_03.00"], written["S_02.00.a"]
(1000, 4)

Version

dpmsynth.__version__ module-attribute

__version__ = version('dpm-synth')