Skip to content

dpmxbrl.filing

The EBA filing rules: the rule catalogue, the log that collects findings, the checks the readers run, and the rule tuples that callers use to add their own findings. Everything on this page is in dpmxbrl.filing.__all__.

See check EBA filing rules, add your own filing findings and the list of rules checked.

EBA filing rules: checks on how a report is written, before its values.

The EBA Filing Rules (version 5.8, 25 February 2026) constrain the report file itself: one entity and reference date, filing indicators, decimals, units, file naming, and constructs that must not appear. A report that breaks a "MUST" rule is rejected however good its values are; "SHOULD" rules are recommendations.

The readers record a :class:FilingFinding for each rule a report breaks that can be judged from the file alone. Rules that need the taxonomy, such as which templates a module has or a data point's data type, are left to callers, which can build findings with the same classes.

RULE_TITLES module-attribute

RULE_TITLES: dict[str, str] = {
    "1.4": "Character encoding",
    "1.5": "Taxonomy entry point",
    "1.6": "Filing indicators",
    "1.6.1": "One filing indicator per template",
    "1.6.3": "Filing indicator codes",
    "1.7": "Templates indicated as reported",
    "1.7.1": "Facts outside the reported templates",
    "1.9": "Valid XBRL",
    "1.13": "Standalone declaration",
    "1.14": "Schema location attributes",
    "1.15": "XInclude",
    "2.1": "xml:base",
    "2.2": "Absolute entry point URL",
    "2.3": "One taxonomy reference",
    "2.4": "Linkbase references",
    "2.7": "Unused or duplicated contexts",
    "2.8": "Reporting subject identification",
    "2.9": "One reporting subject",
    "2.10": "Reference date format",
    "2.11": "xbrli:forever",
    "2.13": "Period consistency",
    "2.14": "xbrli:segment",
    "2.15": "Scenario content",
    "2.16": "Duplicate facts",
    "2.16.1": "Facts differing only by unit",
    "2.17": "Precision attribute",
    "2.18": "Decimals",
    "2.19": "Nil and empty values",
    "2.21": "Duplicated units",
    "2.22": "Unused units",
    "2.25": "Footnotes",
    "3.1": "Currency of monetary facts",
    "3.2": "Non-monetary units",
    "3.4": "Unused namespace prefixes",
    "3.5": "Canonical namespace prefixes",
    "3.6": "Reporting subject",
    "3.9": "Namespace declarations",
    "3.10": "One prefix per namespace",
    "3.11": "Leading or trailing spaces",
    "Package": "xBRL-CSV report package",
    "File naming": "File naming",
    "xBRL-CSV 1": "Decimals suffix",
    "xBRL-CSV 2": "Header row",
    "xBRL-CSV 4": "Key column values",
    "xBRL-CSV 5": "Special values",
    "xBRL-CSV 6": "Tables of templates not reported",
}

Each rule's number in the EBA Filing Rules and a short title.

Numbered rules come from sections 1 to 3. Package and File naming are the requirements in "File naming structure for remittance to the EBA"; xBRL-CSV n are the numbered "xBRL-CSV reports extra rules".

Rule module-attribute

Rule = tuple[str, str, Severity, str]

A finding's rule number, tag, severity and message, for :meth:FilingLog.add.

NIL_VALUE module-attribute

NIL_VALUE: Rule = (
    "2.19",
    "nilUsed",
    "error",
    "Facts must not be reported as #nil; leave out a fact that is not reported.",
)

EMPTY_VALUE module-attribute

EMPTY_VALUE: Rule = (
    "2.19",
    "emptyUsed",
    "error",
    "Facts must not be reported as #empty; such values were skipped.",
)

SPECIAL_VALUE module-attribute

SPECIAL_VALUE: Rule = (
    "xBRL-CSV 5",
    "specialValueUsed",
    "error",
    "Fact values must not use special values starting with # (#none, #empty, #nil or others).",
)

SPECIAL_KEY_VALUE module-attribute

SPECIAL_KEY_VALUE: Rule = (
    "xBRL-CSV 5",
    "specialKeyValueUsed",
    "error",
    "Key columns must not use special values starting with #.",
)

DECIMALS_SUFFIX module-attribute

DECIMALS_SUFFIX: Rule = (
    "xBRL-CSV 1",
    "decimalsSuffixUsed",
    "error",
    "Fact values must not use the decimals suffix (such as 78920030d-4); decimals belong in parameters.csv.",
)

SPACES module-attribute

SPACES: Rule = (
    "3.11",
    "leadingOrTrailingSpacesInText",
    "warning",
    "Fact values should not start or end with spaces or line breaks.",
)

Rule 3.11 for fact values, which applies to string data points only.

The readers do not know data types, so they leave this check to callers that do; they check key values (:data:KEY_SPACES) themselves.

KEY_SPACES module-attribute

KEY_SPACES: Rule = (
    "3.11",
    "leadingOrTrailingSpacesInText",
    "warning",
    "Key values should not start or end with spaces or line breaks.",
)

MISSING_KEY_VALUE module-attribute

MISSING_KEY_VALUE: Rule = (
    "xBRL-CSV 4",
    "missingKeyValue",
    "error",
    "Key columns must hold a value for each reported fact.",
)

FilingLog

FilingLog()

Collect findings, counting repeats of the same finding.

A finding is identified by its rule, code and message. The log keeps a count and up to five distinct locations for each, and returns them in rule order. It is not synchronized; use one log per thread.

Examples:

>>> import dataclasses
>>> from dpmxbrl import read_report
>>> from dpmxbrl.filing import FilingLog
>>> report = read_report("report.zip")
>>> log = FilingLog()
>>> log.extend(report.filing)
>>> rule = (
...     "1.6",
...     "missingFilingIndicator",
...     "error",
...     "Each template needs one.",
... )
>>> log.add(*rule, "C_30.00")
>>> report = dataclasses.replace(report, filing=log.result())
>>> [(finding.rule, finding.examples) for finding in report.filing]
[('1.6', ('C_30.00',)), ('File naming', ('report.zip',))]

Create an empty log.

add

add(
    rule: str,
    code: str,
    severity: Severity,
    message: str,
    location: str | None = None,
    *,
    count: int = 1,
) -> None

Record count occurrences of a finding, keeping a few locations.

A location already kept for the finding is not kept again. Callers usually unpack a :data:Rule tuple: log.add(*NIL_VALUE, where).

Parameters:

  • rule (str) –

    Rule number, a key of :data:RULE_TITLES.

  • code (str) –

    The rule's tag in the EBA document.

  • severity (Severity) –

    error for a MUST rule, warning for SHOULD.

  • message (str) –

    What is wrong, as a sentence.

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

    Where, such as reports/c_01.00.csv:3; optional.

  • count (int, default: 1 ) –

    Occurrences to add; zero or less records nothing.

extend

extend(findings: Iterable[FilingFinding]) -> None

Record findings made elsewhere, keeping each location once.

Parameters:

  • findings (Iterable[FilingFinding]) –

    Findings such as a report's filing; counts add up.

result

result() -> tuple[FilingFinding, ...]

Return the findings in rule order.

Returns:

  • tuple[FilingFinding, ...] –

    tuple[FilingFinding, ...]: One finding per rule, tag and message.

checked_rules

checked_rules(
    format: ReportFormat,
    *,
    taxonomy: bool = False,
    columnar: bool = False,
) -> frozenset[tuple[str, str]]

Return the findings a reader can record, as (rule, code) pairs.

Callers that check rules themselves use it to avoid reporting a rule twice. The set is exact for each mode: the rules the taxonomy adds are there only with taxonomy, canonical prefixes (3.5) only for XML, and the columnar reader, which builds no facts, records neither 2.18 nor 3.2 (b).

Parameters:

  • format (ReportFormat) –

    xbrl-xml for :func:~dpmxbrl.read_xbrl_xml, xbrl-csv for :func:~dpmxbrl.read_xbrl_csv.

  • taxonomy (bool, default: False ) –

    Whether the reader is given taxonomy packages.

  • columnar (bool, default: False ) –

    For xbrl-csv, whether the report is read with :func:~dpmxbrl.frames.read_xbrl_csv_frames.

Returns:

  • frozenset[tuple[str, str]] –

    frozenset[tuple[str, str]]: The (rule, code) pairs.

Raises:

  • ValueError –

    If format is not a report format, or columnar is asked for XML.

Examples:

>>> from dpmxbrl.filing import checked_rules
>>> added = checked_rules("xbrl-csv", taxonomy=True) - checked_rules("xbrl-csv")
>>> for rule, code in sorted(added):
...     print(rule, code)
1.6.3 invalidFilingIndicatorValue
2.18 accuracyRequirements
3.2 useDecimalFractions

sort_findings

sort_findings(
    findings: Iterable[FilingFinding],
) -> tuple[FilingFinding, ...]

Order findings by rule number, then the annex requirements.

Numbered rules come first in numeric order (2.9 before 2.10), then xBRL-CSV n, then Package and File naming.

Parameters:

Returns:

  • tuple[FilingFinding, ...] –

    tuple[FilingFinding, ...]: The findings in document order.

check_subject

check_subject(report: Report, log: FilingLog) -> None

Check the reporting subject's scheme and identifier (rules 2.8 and 3.6).

The EBA prescribes two schemes: the LEI scheme for a bare LEI, and the reporting-subject scheme for an identifier with a suffix such as .CON. Reports from 31 December 2022 onwards must use a suffix unless their module name ends in _con or _ind. A suffix the EBA does not list is a warning: other codes are agreed with the EBA.

Parameters:

  • report (Report) –

    Report whose entity scheme, identifier, entry point and reference date are checked.

  • log (FilingLog) –

    Log the findings are added to.

check_file_name

check_file_name(
    name: str, report: Report, log: FilingLog
) -> None

Check a report file's name against the EBA naming structure.

The structure, ReportSubject_Country_FrameworkCodeModuleVersion_ Module_ReferenceDate_CreationTimestamp, is the one competent authorities use when they send reports to the EBA; reporters confirm their own with their supervisor, so mismatches are warnings.

Parameters:

  • name (str) –

    File name or path; a .zip, .xbrl or .xml suffix is ignored.

  • report (Report) –

    Report whose entity, entry point and reference date the name must match.

  • log (FilingLog) –

    Log the findings are added to.

Examples:

>>> from dpmxbrl import read_report
>>> from dpmxbrl.filing import FilingLog, check_file_name
>>> log = FilingLog()
>>> name = (
...     "SYNTHETICDPMXL000002.CON_FR_COREP030300_COREPLE_"
...     "2025-12-31_20260115093000000.zip"
... )
>>> check_file_name(name, read_report("report.zip"), log)
>>> log.result()
()

check_entry_point

check_entry_point(
    entry_points: list[str],
    log: FilingLog,
    *,
    where: str,
    xml: bool,
) -> None

Check that one absolute entry point URL is referenced (1.5, 2.2, 2.3).

Parameters:

  • entry_points (list[str]) –

    Every entry point the report references.

  • log (FilingLog) –

    Log the findings are added to.

  • where (str) –

    Location for the findings, such as the file name.

  • xml (bool) –

    Whether the report is XBRL-XML, which chooses the tags and the element named in the messages.

FilingFinding and Severity are re-exported here from dpmxbrl.