dpm-xbrl
Read and write EBA-style regulatory XBRL reports in both serializations, xBRL-CSV
report packages and XBRL 2.1 XML instances, through one neutral fact model.
It targets reports built on the data point model (DPM) taxonomies of the
European Banking Authority and is tested on EBA reports. It is an independent
project, not affiliated with or endorsed by the EBA.
The package uses only the standard library and needs Python 3.11 or newer.
The optional fast extra adds isal, which inflates ZIP entries about twice
as fast as zlib; the bytes read are the same either way.
from dpmxbrl import read_report
report = read_report("report.zip") # or a directory, report.json, .xbrl, or bytes
print(report.entity_id, report.reference_date, len(report.facts))
for fact in report.facts_for_template("C_01.00"):
print(fact.datapoint, fact.keys, fact.value)
Model
dpmxbrl.model (re-exported from dpmxbrl) defines two frozen, slotted
dataclasses:
Fact:value(lexical value as written,Nonewhen nil),concept(prefixed qname),datapoint(xBRL-CSV datapoint code),template(xBRL-CSV table template id,Nonefor XML),dimensions(explicit dimension qname to member qname),typed_dimensions(typed dimension qname to the typed value text),keys(xBRL-CSV non-fact column name to cell value, in header order),unit(iso4217:EUR,xbrli:pure,num/denomfor divide units,a*bfor products),decimals(Nonemeans INF or unspecified) andlocation(reports/c_01.00.csv:3with the 1-based physical line, orinstance.xbrl#f12with the fact id,#factNfor the Nth fact without id).Report:format,entry_point,entity_scheme,entity_id,reference_date,base_currency,parameters,decimals_parameters,filing_indicators,facts,namespaces,warningsandfiling(the EBA filing rules the report breaks, see below).
Report.facts_for_template(code) compares template codes case-insensitively,
so filing-indicator codes such as C_01.00 select facts from c_01.00.csv.
local_name(qname) returns the local part of a prefixed or Clark qname.
Qnames always use prefixes declared in Report.namespaces. XML keeps the
instance's own prefixes; a namespace declared again deeper in the document
under another prefix is rendered with the first prefix bound to it.
Reading
read_report(source, *, name=None, metadata_resolver=None,
taxonomy_packages=(), limits=Limits()) -> Report
read_xbrl_csv(source, *, name=None, metadata_resolver=None,
taxonomy_packages=(), limits=Limits()) -> Report
read_xbrl_xml(source, *, name=None, limits=Limits()) -> Report
detect_format(source) -> "xbrl-csv" | "xbrl-xml"
read_report treats ZIP input (bytes or a path), a directory and a .json
path as xBRL-CSV and everything else as XBRL-XML. Every failure raises
ReportError (a ValueError) naming the file and, where known, the line.
xBRL-CSV
- A ZIP or directory with exactly one
reports/*.jsonreport (normallyreports/report.json), optionally below one top-level folder, plus an optionalMETA-INF/reportPackage.jsonwhosedocumentTypemust behttps://xbrl.org/report-package/2023or.../2023/xbrl-csv. A directory may also holdreport.jsondirectly. documentInfo.documentTypemust behttps://xbrl.org/2021/xbrl-csv; the 2019-2021 PWD/CR/PR draft URIs are accepted with a warning. Duplicate JSON keys are rejected.parameters.csv(or the metadata'sparameterURL) must have the headername,value.entityIDsuch aslei:5299...becomesentity_id; its prefix is looked up innamespacesforentity_scheme, else kept as the scheme.refPeriodmust be aYYYY-MM-DDdate. Parameters nameddecimals*populatedecimals_parameters(#noneandINFmap toNone). Inline JSONparametersare merged first; the CSV file overrides them.FilingIndicators.csvmust have the headertemplateID,reported, withreportedone oftrue,false,1,0.- Every other
*.csvunder the reports folder is a table. Its template id is the file stem unless the metadatatablesmaps the file URL to a template.
EBA convention (no metadata). Tables need datapoint and factValue
columns; every other column is a key column kept in Fact.keys. Each row with
a non-empty factValue is one fact. #nil gives a nil fact, #empty and
#none are skipped, ## escapes a leading #, and other # values are kept
as written; each case adds a warning. Fact.decimals stays None; consumers
pick the decimals_parameters entry for the fact's data type. Exact duplicate
rows are reported once; conflicting duplicates (same template, datapoint and
keys, different value) are all kept. Repeated findings are aggregated into one
warning with a count and the first location.
Resolved metadata. report.json and its extends chain are followed
recursively (cycle-safe, diamond-safe, depth-limited), merging namespaces,
tableTemplates, tables, parameters, dimensions, decimals and
parameterURL, with the extending document taking precedence. Relative URLs
resolve inside the package or against the extending document's URL. Absolute
URLs are resolved by metadata_resolver(url) first and then through the
META-INF/catalog.xml rewriteURI/rewriteSystem prefixes of the given
taxonomy package ZIPs. Nothing is fetched over the network. Table urls and
parameterURL resolve against the report's own JSON.
For a table whose template is resolved, the supported xBRL-CSV subset is:
template columns; fact columns (with dimensions or propertiesFrom);
property-group columns (propertyGroups, such as EBA's datapoint column keyed
by dp...); other columns as key columns; report, template, column and
property-group dimensions and decimals, in increasing precedence;
$column and $parameter references (row cell, then table parameters, then
report parameters), $$ escapes and #none; core dimensions concept,
unit, period, entity and language; and taxonomy-defined dimensions. A
taxonomy-defined dimension value that is a qname with a declared prefix is an
explicit member; any other value is a typed value. Fact.datapoint is the
property-group key and Fact.keys keeps the key columns. A table whose
template cannot be resolved falls back to the EBA convention, and unresolved
extends produce one warning.
XBRL-XML
- The prolog is scanned before parsing and any DOCTYPE (and with it any ENTITY
declaration) is rejected; external entities are never resolved. Parsing
streams with
iterparseand clears each top-level element once processed. link:schemaRefgivesentry_point. Contexts provide the entity identifier and scheme, the reference date (instant, or the end date of a duration) andxbrldi:explicitMember/xbrldi:typedMemberfrom segment or scenario. A typed member's value is the stripped text of its single child element; the child element name is not kept.- Units with one or more measures, or a divide, become strings. Facts are
top-level elements outside the
xbrli,linkandfindnamespaces with acontextRef;xsi:nil="true"givesvalue=None;decimals="INF"givesNone.precisionis ignored, and tuples and elements withoutcontextRefare skipped, each with a warning. find:fIndicators/find:filingIndicatorprovide filing indicators;find:fileddefaults to true.- The report entity and reference date are the most common across facts, and
base_currencyis the most common single-measureiso4217unit. More than one entity or period adds a warning, because EBA requires one.
Limits
Limits(max_zip_entries=10_000, max_total_size=2 GiB, max_file_size=512 MiB, max_facts=20_000_000, max_extends_depth=32). Report packages are also rejected
for absolute or .. entry names, duplicate entries and encrypted entries, and
package directories for links that leave the directory. The file-size limit
also applies to XML instances and to files read from taxonomy packages. CSV
rows are streamed with the csv module (utf-8-sig), including from ZIPs.
An entry whose compressed data is damaged raises ReportError naming the entry.
EBA filing rules
Both readers record the EBA Filing Rules
(version 5.8, February 2026) that a report breaks and that the file alone can show, in
Report.filing: one FilingFinding per rule and problem, with the rule's
number (2.19), its tag in the EBA document (nilUsed), a severity, a
message, how many times it occurs and up to five locations.
dpmxbrl.filing.RULE_TITLES names each rule. Severity is error where the
rule says MUST (EBA rejects the report) and warning where it says SHOULD;
file-naming findings are warnings because each supervisor confirms its own
naming.
- Both formats: one absolute taxonomy entry point (1.5, 2.2, 2.3); the
reporting subject's scheme, suffix, upper case and LEI check digits (2.8,
3.6); and the file name against
ReportSubject_Country_ FrameworkCodeModuleVersion_Module_ReferenceDate_CreationTimestamp, including the reporting subject, module and reference date. - XBRL-XML: UTF-8 and no standalone declaration (1.4, 1.13); filing
indicators present, unique and in a context without segment or scenario
(1.6, 1.6.1); no
xsi:schemaLocation, XInclude,xml:base,link:linkbaseRef, footnotes, segments, forever or duration periods, or non-dimensional scenario content (1.14, 1.15, 2.1, 2.4, 2.25, 2.11, 2.13, 2.14, 2.15); one entity and reference date, as plain dates (2.9, 2.10, 2.13); no duplicate facts, and none differing only by unit (2.16, 2.16.1);decimalsrather thanprecision, and present on numeric facts (2.17, 2.18); no nil or empty facts (2.19); unused or repeated contexts and units (2.7, 2.21, 2.22); one reporting currency, and currency-of-denomination facts in the currency their CUS or CUA member names (3.1);xbrli:purefor other numeric facts (3.2); and namespace prefixes declared once, on the document element, and used (3.4, 3.9, 3.10). - xBRL-CSV:
META-INF/reportPackage.json,parameters.csvwithrefPeriod, andFilingIndicators.csv; the root folder named as the ZIP; nodocumentInfo.taxonomy(1.5); a plain-daterefPeriod(2.10); unique filing indicators (1.6.1); no table file for a template indicated as not reported (xBRL-CSV rule 6); no special values in fact or key columns (#nil,#emptyand any other value starting with#; 2.19 and rule 5); no decimals suffix (rule 1); key values without leading or trailing spaces (3.11).
Rules that need the taxonomy are left to the caller, which can build
FilingFindings and merge them with dpmxbrl.filing.FilingLog: a filing
indicator for every template of the module and only valid codes (1.6, 1.6.3),
facts outside the reported templates (1.7.1), minimum decimals per data type
(2.18), fact values without leading or trailing spaces, which applies to
string data points only (3.11, SPACES in dpmxbrl.filing), an entry
point valid for the reference date (1.5), and baseCurrency when monetary
facts use it. Not checked: units against the XBRL unit registry (2.23),
decimal notation for rates (3.2), canonical prefixes (3.5),
generating-software information (2.26) and comments (2.5).
read_xbrl_csv_frames checks special fact values only; the decimals suffix,
spaces around key values and special key values are left to callers that
split values by data type, which can record them with the same messages
(DECIMALS_SUFFIX, KEY_SPACES, SPECIAL_KEY_VALUE in dpmxbrl.filing).
Writing
write_xbrl_csv(report, target, *, root=None) -> None
write_xbrl_xml(report, target, *, typed_domains=None) -> None
default_package_root(report) -> str
write_xbrl_csv writes a ZIP report package in EBA convention:
<root>/META-INF/reportPackage.json, <root>/reports/report.json (extending
entry_point and declaring namespaces), parameters.csv (entityID,
refPeriod, baseCurrency, decimals*, then any other parameter),
FilingIndicators.csv and one <template>.csv per template with header
datapoint,factValue,<key columns in first-seen order>. Nil values are
written as #nil, empty strings as #empty and a leading # as ##. The root
defaults to <entity id>_<reference date>. Output is deterministic (sorted
templates, source fact order, fixed ZIP timestamps). Facts without a template
or datapoint raise ReportError before anything is written.
write_xbrl_xml writes schemaRef, filing indicators, contexts deduplicated
by dimensions (c1, c2, ..., entity plus an instant at reference_date,
dimensions in the scenario), units (u1, ...) and facts. A fact with a unit
is numeric and gets decimals (INF when unset) unless it is nil. Facts
without a concept, undeclared prefixes and a missing entity or reference date
raise ReportError. Because the reader does not keep typed-domain element
names, typed dimensions need typed_domains={"eba_dim:qINC": "eba_typ:qCC"}.
Reading a written report reproduces its facts in both formats; the tests cover these round trips.
CLI
dpm-xbrl inspect PATH [--json] [--taxonomy-package ZIP ...]
dpm-xbrl convert IN OUT [--taxonomy-package ZIP ...]
[--typed-domain DIMENSION=ELEMENT ...] [--root NAME]
inspect prints the format, entry point, entity, reference date, base
currency, filing indicators (reported of total), the fact count per template,
the warnings and the EBA filing rules the report breaks. convert chooses the output format from the suffix: .zip
writes xBRL-CSV, .xbrl or .xml writes XBRL-XML. Errors print error: ...
and exit with status 1.
Development
uv sync
uv run pytest
uv run ruff check
uv run ruff format --check
uv run ty check
Known gaps
- No taxonomy validation, schema lookups or calculation and formula checks. Without a taxonomy, an explicit member and a typed value that looks like a declared qname cannot be told apart in xBRL-CSV metadata.
- xBRL-CSV: no
rowIdColumn,links, footnotes,@start/@endperiod semantics, per-factperiod/entity/languagevalues (they are ignored), or multiple reports per package. Taxonomy packages must be ZIPs. - EBA-convention CSV facts carry no concept, dimensions, unit or decimals, so they cannot be written as XML; XML facts carry no datapoint or template, so they cannot be written as CSV. Converting between formats needs resolved xBRL-CSV metadata.
- Empty-string facts do not survive an xBRL-CSV round trip (
#emptyis skipped when read), andFact.decimals, concepts and dimensions are not written to EBA-convention CSV. - XML: tuples, footnotes,
precision, segment versus scenario placement, forever periods and typed-domain element names are not kept. XML output puts all dimensions in the scenario and uses one entity and instant. The XML writer holds the instance text in memory before writing it. - Fact locations in XML use the fact id rather than a line number.
Metadata
Release files for dpm-xbrl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dpm_xbrl-0.1.0.tar.gz | 53.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dpm_xbrl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 112.6 kB
Release files / dpm_xbrl-0.1.0.tar.gz
| Download URL | dpm_xbrl-0.1.0.tar.gz |
|---|---|
| Size | 53.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3cc96e920d7e99a1b5cb1aa24334b9c5693c5ca5d248bd68b4bff9e0ce19bb8
|
|
BLAKE2b-256 checksum How to use checksums |
375fc4697bf348a97b079e958ed82fd8237613b51dee697d553b2bf480521d9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / dpm_xbrl-0.1.0-py3-none-any.whl
| Download URL | dpm_xbrl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 59.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6dbba762d4a15d082968088dbf084e02b609d76c4c6fc8071aa75a09ca202860
|
|
BLAKE2b-256 checksum How to use checksums |
18f6e0b4f4d31faebeddfbc6f56b17190c81f9fc95bbdd2095b23e409efb6ea5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for dpm-xbrl 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.