Skip to content

dpmxbrl

The top-level package: readers, writers and the fact model. Everything on this page is in dpmxbrl.__all__ and covered by the stability policy. The model classes are defined in dpmxbrl.model and re-exported here; import them from dpmxbrl.

All functions are safe to call from several threads at once: each call works on its own input and returns immutable results. See thread safety.

Reading

dpmxbrl.read_report

read_report(
    source: str | PathLike[str] | bytes,
    *,
    name: str | None = None,
    metadata_resolver: MetadataResolver | None = None,
    taxonomy_packages: str
    | PathLike[str]
    | Sequence[str | PathLike[str]] = (),
    limits: Limits = Limits(),
) -> Report

Read a report, detecting xBRL-CSV or XBRL-XML from the input.

The format is detected as by :func:detect_format; the input is then read by :func:read_xbrl_csv or :func:read_xbrl_xml.

Parameters:

  • source (str | PathLike[str] | bytes) –

    Bytes, a file path, an xBRL-CSV package directory, or the path of a package's report.json.

  • name (str | None, default: None ) –

    Label used in messages and fact locations, such as the file name of uploaded bytes; the EBA file-naming rule checks it.

  • metadata_resolver (MetadataResolver | None, default: None ) –

    xBRL-CSV extends URL resolver; unused for XML.

  • taxonomy_packages (str | PathLike[str] | Sequence[str | PathLike[str]], default: () ) –

    Local taxonomy package ZIPs, one path or a sequence: they resolve xBRL-CSV metadata and add the filing rules that need the taxonomy.

  • limits (Limits, default: Limits() ) –

    Resource limits for untrusted input.

Returns:

  • Report ( Report ) –

    The parsed report.

Raises:

Examples:

>>> from dpmxbrl import read_report
>>> report = read_report("instance.xbrl")
>>> report.format, report.reference_date.isoformat(), len(report.facts)
('xbrl-xml', '2025-12-31', 3)
>>> [(finding.rule, finding.code) for finding in report.filing]
[('File naming', 'invalidFileName')]

dpmxbrl.read_xbrl_csv

read_xbrl_csv(
    source: str | PathLike[str] | bytes,
    *,
    name: str | None = None,
    metadata_resolver: MetadataResolver | None = None,
    taxonomy_packages: str
    | PathLike[str]
    | Sequence[str | PathLike[str]] = (),
    limits: Limits = Limits(),
) -> Report

Read an xBRL-CSV report package from a ZIP or a directory.

Parameters:

  • source (str | PathLike[str] | bytes) –

    ZIP bytes, a ZIP path, a package directory, or report.json.

  • name (str | None, default: None ) –

    Label used in messages instead of the source path.

  • metadata_resolver (MetadataResolver | None, default: None ) –

    Returns the bytes for an absolute extends URL, or None when unknown. It is consulted before taxonomy packages.

  • taxonomy_packages (str | PathLike[str] | Sequence[str | PathLike[str]], default: () ) –

    Local taxonomy package ZIPs, one path or a sequence, whose META-INF/catalog.xml rewrites resolve extends URLs.

  • limits (Limits, default: Limits() ) –

    Resource limits for untrusted input.

Returns:

  • Report ( Report ) –

    Report with format == "xbrl-csv".

Raises:

  • ReportError –

    If the package is invalid, unsafe or over a limit.

Examples:

>>> from dpmxbrl import read_xbrl_csv
>>> report = read_xbrl_csv("described.zip", taxonomy_packages=["taxonomy.zip"])
>>> fact = report.facts[0]
>>> fact.datapoint, fact.concept, fact.unit, fact.decimals
('dp84817', 'eba_met:mi53', 'iso4217:EUR', -3)

dpmxbrl.read_xbrl_xml

read_xbrl_xml(
    source: str | PathLike[str] | bytes,
    *,
    name: str | None = None,
    taxonomy_packages: str
    | PathLike[str]
    | Sequence[str | PathLike[str]] = (),
    limits: Limits = Limits(),
) -> Report

Read one XBRL 2.1 XML instance.

Parameters:

  • source (str | PathLike[str] | bytes) –

    Instance bytes or a path to the instance document.

  • name (str | None, default: None ) –

    Label used in messages and fact locations.

  • taxonomy_packages (str | PathLike[str] | Sequence[str | PathLike[str]], default: () ) –

    Local taxonomy package ZIPs, one path or a sequence; with them the filing rules that need the taxonomy are checked too.

  • limits (Limits, default: Limits() ) –

    Resource limits for untrusted input.

Returns:

  • Report ( Report ) –

    Report with format == "xbrl-xml".

Raises:

  • ReportError –

    If the instance is malformed, unsafe or over a limit.

Examples:

>>> from dpmxbrl import read_xbrl_xml
>>> fact = read_xbrl_xml("instance.xbrl").facts[2]
>>> fact.concept, dict(fact.dimensions), dict(fact.typed_dimensions)
('eba_met:qNCO', {'eba_dim:qNCO': 'eba_qCO:qx2000'}, {'eba_dim:qINC': 'CP0001'})

dpmxbrl.detect_format

detect_format(
    source: str | PathLike[str] | bytes,
    *,
    name: str | None = None,
) -> ReportFormat

Detect whether input is an xBRL-CSV package or an XBRL-XML instance.

ZIP archives, directories and .json metadata paths are xBRL-CSV; anything else is read as XBRL-XML. A ZIP is recognized by its content, whatever its suffix.

Parameters:

  • source (str | PathLike[str] | bytes) –

    Bytes, a file path, or an xBRL-CSV package directory.

  • name (str | None, default: None ) –

    Label used in messages instead of the path, such as the file name of uploaded bytes.

Returns:

  • ReportFormat ( ReportFormat ) –

    "xbrl-csv" or "xbrl-xml".

Raises:

  • ReportError –

    If a path does not exist or cannot be read, or if a .zip file or one starting like a ZIP archive cannot be read as one (it is incomplete or damaged; reading it as XML would only report malformed XML).

Examples:

>>> from dpmxbrl import detect_format
>>> detect_format("report.zip"), detect_format("instance.xbrl")
('xbrl-csv', 'xbrl-xml')

Writing

dpmxbrl.write_xbrl_csv

write_xbrl_csv(
    report: Report,
    target: str | Path | IO[bytes],
    *,
    root: str | None = None,
    taxonomy_packages: str
    | PathLike[str]
    | Sequence[str | PathLike[str]] = (),
    strict: bool = True,
    limits: Limits = Limits(),
) -> SkippedFacts

Write an EBA xBRL-CSV report package ZIP.

The package holds META-INF/reportPackage.json, reports/report.json, parameters.csv, FilingIndicators.csv and one datapoint,factValue,<keys> table per template. Output is deterministic: templates are sorted, facts keep their order, and ZIP timestamps are fixed.

With taxonomy_packages, the module's JSON entry point (the entry point with .json for .xsd) gives the tables: each fact with a concept, such as one read from XML, goes in every table row whose data point has its concept and dimensions, with the module's table files, columns and prefixes. report.json extends the JSON entry point, and baseCurrency and the decimals* parameters come from the facts. Facts without a concept keep their template and datapoint.

Parameters:

  • report (Report) –

    Report to write; without taxonomy packages every fact needs a template and datapoint.

  • target (str | Path | IO[bytes]) –

    Destination path or writable binary stream.

  • root (str | None, default: None ) –

    Top-level folder name; defaults to the target's file name without .zip, as the EBA filing rules ask, or to default_package_root for a stream.

  • taxonomy_packages (str | PathLike[str] | Sequence[str | PathLike[str]], default: () ) –

    Local taxonomy package ZIPs, one path or a sequence, holding the module's xBRL-CSV metadata, used to place facts by concept.

  • strict (bool, default: True ) –

    With taxonomy packages, whether a fact that cannot be placed exactly raises ReportError; when False it is left out and returned.

  • limits (Limits, default: Limits() ) –

    Resource limits for reading the taxonomy packages.

Returns:

  • SkippedFacts ( SkippedFacts ) –

    The facts left out, each a :class:SkippedFact with

  • SkippedFacts –

    the reason and its code; always empty when strict is true.

Warns:

  • DecimalsWarning –

    If a decimals* parameter is lower than the decimals of some of its facts, naming them.

Raises:

  • ReportError –

    If a fact lacks a template or datapoint (without taxonomy packages) or cannot be placed (with them, in strict mode), the module metadata is missing, or a template or root name is not a safe file name.

Examples:

>>> from dpmxbrl import read_report, write_xbrl_csv
>>> report = read_report("report.zip")
>>> write_xbrl_csv(report, "copy.zip")  # root folder "copy"
()
>>> read_report("copy.zip").facts == report.facts
True

dpmxbrl.write_xbrl_xml

write_xbrl_xml(
    report: Report,
    target: str | Path | IO[bytes],
    *,
    typed_domains: Mapping[str, str] | None = None,
    taxonomy_packages: str
    | PathLike[str]
    | Sequence[str | PathLike[str]] = (),
    limits: Limits = Limits(),
) -> None

Write an XBRL 2.1 XML instance.

Contexts are deduplicated per dimension combination (ids c1, c2 in first-use order) and use the report entity and an instant at the reference date; dimensions are written in the scenario. Facts with a unit are numeric and get decimals (INF when unset) unless nil; a fact with decimals but no unit, as xBRL-CSV metadata gives pure facts, gets xbrli:pure. A fact repeated with the same concept, dimensions, unit, value and decimals, as in several xBRL-CSV tables, is written once. The schemaRef names the module's XSD entry point: a JSON entry point, as xBRL-CSV reports extend, is mapped to the XSD that the taxonomy packages list for it, or else named by the EBA's convention.

Parameters:

  • report (Report) –

    Report to write; every fact needs a concept.

  • target (str | Path | IO[bytes]) –

    Destination path or writable binary stream.

  • typed_domains (Mapping[str, str] | None, default: None ) –

    Typed dimension qname to the qname of its typed domain element, with a prefix the report declares or in Clark notation ({namespace}local, declared under a new prefix if needed); required for each typed dimension used by a fact unless the taxonomy packages give it.

  • taxonomy_packages (str | PathLike[str] | Sequence[str | PathLike[str]], default: () ) –

    Local taxonomy package ZIPs, one path or a sequence, whose dimension schemas give the typed domain (xbrldt:typedDomainRef) of each typed dimension not in typed_domains, declared with the prefix its schema uses.

  • limits (Limits, default: Limits() ) –

    Resource limits for reading the taxonomy packages.

Raises:

  • ReportError –

    If a fact lacks a concept, the entity or reference date is missing, a prefix is undeclared or invalid, a qname has an invalid local name, a typed domain is unknown, or a value holds a character XML cannot represent.

Warns:

  • EntryPointWarning –

    If the XSD entry point for a JSON one comes from the EBA's naming convention rather than the taxonomy packages.

Examples:

>>> from dpmxbrl import read_report, write_xbrl_xml
>>> report = read_report("described.zip", taxonomy_packages=["taxonomy.zip"])
>>> write_xbrl_xml(report, "described.xbrl", taxonomy_packages=["taxonomy.zip"])
>>> instance = read_report("described.xbrl")
>>> len(instance.facts), instance.entry_point.rsplit("/", 1)[1]
(6, 'corep_of.xsd')

dpmxbrl.default_package_root

default_package_root(report: Report) -> str

Return the default top-level folder name of a written report package.

Parameters:

  • report (Report) –

    Report whose entity and reference date name the folder.

Returns:

  • str ( str ) –

    <entity id>_<reference date> made path-safe, or report.

Examples:

>>> from dpmxbrl import default_package_root, read_report
>>> default_package_root(read_report("report.zip"))
'SYNTHETICDPMXL000002.CON_2025-12-31'

dpmxbrl.SkippedFacts module-attribute

SkippedFacts = tuple[SkippedFact, ...]

The facts that write_xbrl_csv(..., strict=False) left out.

dpmxbrl.SkippedFact

Bases: NamedTuple

A fact that write_xbrl_csv(..., strict=False) left out.

Attributes:

  • fact (Fact) –

    The fact.

  • reason (str) –

    Why, as a phrase such as its unit iso4217:USD differs from baseCurrency iso4217:EUR, which the other facts use; it may be reworded.

  • code (str) –

    Why, as a stable code: undeclaredPrefix (a prefix of its concept or dimensions is not declared), noDataPoint (no data point of the module has its concept and dimensions), unitMismatch (its unit does not fit the data point) or currencyMismatch (its unit differs from the baseCurrency the other facts use).

fact instance-attribute

fact: Fact

reason instance-attribute

reason: str

code instance-attribute

code: str

dpmxbrl.EntryPointWarning

Bases: UserWarning

write_xbrl_xml named an XSD entry point it could not confirm.

dpmxbrl.DecimalsWarning

Bases: UserWarning

write_xbrl_csv lowered the decimals some facts state.

An EBA xBRL-CSV package gives decimals per data type, in decimals* parameters; each takes the lowest decimals of its facts, so a fact that had more now states less accuracy than in the report.

Model

dpmxbrl.Report dataclass

Report(
    format: ReportFormat,
    entry_point: str | None,
    entity_scheme: str | None,
    entity_id: str | None,
    reference_date: date | None,
    base_currency: str | None,
    parameters: Mapping[str, str],
    decimals_parameters: Mapping[str, int | None],
    filing_indicators: Mapping[str, bool],
    facts: tuple[Fact, ...],
    namespaces: Mapping[str, str],
    warnings: tuple[str, ...] = (),
    filing: tuple[FilingFinding, ...] = (),
)

One regulatory report read from xBRL-CSV or XBRL-XML.

Attributes:

  • format (ReportFormat) –

    Serialization the report was read from.

  • entry_point (str | None) –

    Taxonomy entry point (extends[0] or schemaRef).

  • entity_scheme (str | None) –

    Entity identifier scheme URI, or the CSV prefix when no namespace declares it.

  • entity_id (str | None) –

    Entity identifier without scheme.

  • reference_date (date | None) –

    Reference date (CSV refPeriod; XML instant/end).

  • base_currency (str | None) –

    Base currency unit such as iso4217:EUR.

  • parameters (Mapping[str, str]) –

    xBRL-CSV report parameters; empty for XML.

  • decimals_parameters (Mapping[str, int | None]) –

    xBRL-CSV decimals* parameters; None for #none/INF.

  • filing_indicators (Mapping[str, bool]) –

    Template code to whether it was reported.

  • facts (tuple[Fact, ...]) –

    Reported facts in source order.

  • namespaces (Mapping[str, str]) –

    Prefix to namespace URI.

  • warnings (tuple[str, ...]) –

    Non-fatal findings in deterministic order.

  • filing (tuple[FilingFinding, ...]) –

    EBA filing rules the report breaks that the file alone shows (see :mod:dpmxbrl.filing), in rule order.

format instance-attribute

format: ReportFormat

entry_point instance-attribute

entry_point: str | None

entity_scheme instance-attribute

entity_scheme: str | None

entity_id instance-attribute

entity_id: str | None

reference_date instance-attribute

reference_date: date | None

base_currency instance-attribute

base_currency: str | None

parameters instance-attribute

parameters: Mapping[str, str]

decimals_parameters instance-attribute

decimals_parameters: Mapping[str, int | None]

filing_indicators instance-attribute

filing_indicators: Mapping[str, bool]

facts instance-attribute

facts: tuple[Fact, ...]

namespaces instance-attribute

namespaces: Mapping[str, str]

warnings class-attribute instance-attribute

warnings: tuple[str, ...] = ()

filing class-attribute instance-attribute

filing: tuple[FilingFinding, ...] = ()

facts_for_template

facts_for_template(code: str) -> tuple[Fact, ...]

Select facts reported in one xBRL-CSV table template.

Template codes compare case-insensitively, and a table also matches its filing indicator, its code without single-letter parts: both c_07.00.a and C_07.00 select the facts of c_07.00.a.csv, and C_07.00 those of c_07.00.b.csv too. XML facts have no template, so nothing matches in an XML report.

Parameters:

  • code (str) –

    Template code or filing indicator, such as C_27.00 or c_07.00.a.

Returns:

  • tuple[Fact, ...] –

    tuple[Fact, ...]: Matching facts in source order.

Examples:

>>> from dpmxbrl import read_report
>>> report = read_report("report.zip")
>>> [fact.value for fact in report.facts_for_template("C_28.00")]
['67129000', '60309000', '41250000', '38900000']

dpmxbrl.Fact dataclass

Fact(
    value: str | None,
    concept: str | None = None,
    datapoint: str | None = None,
    template: str | None = None,
    dimensions: Mapping[str, str] = dict(),
    typed_dimensions: Mapping[str, str] = dict(),
    keys: Mapping[str, str] = dict(),
    unit: str | None = None,
    decimals: int | None = None,
    location: str = "",
)

One reported fact independent of its serialization.

Attributes:

  • value (str | None) –

    Lexical value as written; None when the fact is nil.

  • concept (str | None) –

    Prefixed concept qname such as eba_met:qABJ. xBRL-CSV facts carry it only when table metadata was resolved.

  • datapoint (str | None) –

    xBRL-CSV datapoint code such as dp84817.

  • template (str | None) –

    xBRL-CSV table template identifier; None for XML.

  • dimensions (Mapping[str, str]) –

    Explicit dimension qname to member qname.

  • typed_dimensions (Mapping[str, str]) –

    Typed dimension qname to typed value text.

  • keys (Mapping[str, str]) –

    xBRL-CSV non-fact column name to cell value, in header order.

  • unit (str | None) –

    Unit such as iso4217:EUR or a/b for a divide unit.

  • decimals (int | None) –

    Decimals accuracy; None means INF or unspecified.

  • location (str) –

    Source location, reports/x.csv:3 (the 1-based physical line) or file.xbrl#id (#factN for the Nth fact without an id).

The mappings of facts that are read are read-only and may be shared between facts; copy one with dict() to change it.

Examples:

>>> from dpmxbrl import read_report
>>> fact = read_report("report.zip").facts_for_template("C_27.00")[0]
>>> fact.datapoint, fact.value
('dp5486584', 'Northwind Holdings')
>>> dict(fact.keys)
{'qINC': 'CP0001', 'qNCO': 'eba_qCO:qx2000'}
>>> fact.location
'reports/c_27.00.csv:2'

value instance-attribute

value: str | None

concept class-attribute instance-attribute

concept: str | None = None

datapoint class-attribute instance-attribute

datapoint: str | None = None

template class-attribute instance-attribute

template: str | None = None

dimensions class-attribute instance-attribute

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

typed_dimensions class-attribute instance-attribute

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

keys class-attribute instance-attribute

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

unit class-attribute instance-attribute

unit: str | None = None

decimals class-attribute instance-attribute

decimals: int | None = None

location class-attribute instance-attribute

location: str = ''

dpmxbrl.FilingFinding dataclass

FilingFinding(
    rule: str,
    code: str,
    severity: Severity,
    message: str,
    count: int = 1,
    examples: tuple[str, ...] = (),
)

One EBA filing rule a report breaks, with how often and where.

Attributes:

  • rule (str) –

    The rule's number, a key of :data:dpmxbrl.filing.RULE_TITLES.

  • code (str) –

    The rule's tag in the EBA document, such as nilUsed.

  • severity (Severity) –

    error when the rule says MUST, warning for SHOULD.

  • message (str) –

    What is wrong and what the rule requires, as a sentence.

  • count (int) –

    How many times the report breaks it.

  • examples (tuple[str, ...]) –

    Up to five locations, such as report.xbrl#f12.

rule and code are stable across releases; message may be reworded in a minor release.

rule instance-attribute

rule: str

code instance-attribute

code: str

severity instance-attribute

severity: Severity

message instance-attribute

message: str

count class-attribute instance-attribute

count: int = 1

examples class-attribute instance-attribute

examples: tuple[str, ...] = ()

dpmxbrl.Limits dataclass

Limits(
    max_zip_entries: int = 10000,
    max_total_size: int = 2 * 1024**3,
    max_file_size: int = 512 * 1024**2,
    max_facts: int = 20000000,
    max_extends_depth: int = 32,
    max_taxonomy_entries: int = 100000,
)

Resource limits applied while reading untrusted report input.

Attributes:

  • max_zip_entries (int) –

    Maximum number of entries in a report package ZIP.

  • max_total_size (int) –

    Maximum total uncompressed size of a report package.

  • max_file_size (int) –

    Maximum uncompressed size of one file, including an XBRL-XML instance document.

  • max_facts (int) –

    Maximum number of facts in one report.

  • max_extends_depth (int) –

    Maximum nesting depth of xBRL-CSV extends.

  • max_taxonomy_entries (int) –

    Maximum number of entries in one taxonomy package ZIP; the EBA's reporting frameworks package has about 17,400. Files read from taxonomy packages also count towards max_total_size.

Examples:

>>> from dataclasses import replace
>>> from dpmxbrl import Limits, ReportError, read_report
>>> try:
...     read_report("report.zip", limits=replace(Limits(), max_facts=10))
... except ReportError as error:
...     print(error)
reports/c_28.00.csv:2: report exceeds the limit of 10 facts

max_zip_entries class-attribute instance-attribute

max_zip_entries: int = 10000

max_total_size class-attribute instance-attribute

max_total_size: int = 2 * 1024 ** 3

max_file_size class-attribute instance-attribute

max_file_size: int = 512 * 1024 ** 2

max_facts class-attribute instance-attribute

max_facts: int = 20000000

max_extends_depth class-attribute instance-attribute

max_extends_depth: int = 32

max_taxonomy_entries class-attribute instance-attribute

max_taxonomy_entries: int = 100000

dpmxbrl.ReportError

ReportError(message: str, *, problems: Sequence[str] = ())

Bases: ValueError

Raised when a report cannot be read or written safely.

Every unreadable, unsafe or over-limit input raises it, with a message that names the file and, where known, the line or entry.

Attributes:

  • problems (tuple[str, ...]) –

    Every problem found, one message each; an error about a single problem holds its own message.

Examples:

>>> from dpmxbrl import ReportError, read_report
>>> try:
...     read_report("missing.zip")
... except ReportError as error:
...     print(error)
missing.zip: no such file or directory

Create an error with a message and, optionally, all its problems.

problems instance-attribute

problems: tuple[str, ...] = tuple(problems) or (message,)

__reduce__

__reduce__() -> tuple[Any, ...]

Pickle with the problems, for subclasses too.

Returns:

  • tuple ( Any ) –

    A function that rebuilds the error from its class, message

  • ... –

    and problems, whatever arguments the subclass takes.

dpmxbrl.ReportFormat module-attribute

ReportFormat = Literal['xbrl-csv', 'xbrl-xml']

dpmxbrl.Severity module-attribute

Severity = Literal['error', 'warning']

error for a "MUST" filing rule (the report is rejected), warning for a "SHOULD" rule.

dpmxbrl.local_name

local_name(qname: str) -> str

Return the local part of a prefixed or Clark-notation qname.

Parameters:

  • qname (str) –

    A qname such as eba_met:mi53 or {namespace}mi53.

Returns:

  • str ( str ) –

    Text after the last } or the first :; a name without

  • str –

    either is returned as is.

Examples:

>>> from dpmxbrl import local_name
>>> local_name("eba_met:mi53"), local_name("{http://example.com/met}mi53")
('mi53', 'mi53')

dpmxbrl.filing_indicator_code

filing_indicator_code(template: str) -> str

Return the filing indicator code of an xBRL-CSV table template.

Single-letter parts are dropped: c_07.00.a is filed as c_07.00, f_18.00.a.dp as f_18.00.dp. Filing indicators compare case-insensitively.

Parameters:

  • template (str) –

    Table template id, such as a table file's stem.

Returns:

  • str ( str ) –

    The template id without single-letter parts.

Examples:

>>> from dpmxbrl import filing_indicator_code
>>> filing_indicator_code("c_07.00.a"), filing_indicator_code("F_18.00.a.dp")
('c_07.00', 'F_18.00.dp')

Version

dpmxbrl.__version__ module-attribute

__version__ = version('dpm-xbrl')