cadrumo.adapters.inbound.financial.providers._tabular_projection module

Deterministic projection of normalized tabular rows under a column-role mapping.

Consumes a NormalizedTable plus a ColumnRoleMapping — one FieldRole per column, decided once for the whole file — and copies every cell into its role. The copy is the whole of the operation: project_table() performs no stripping, no separator rewriting, no date parsing and no type coercion, so a projected value is byte-equal to the cell it came from.

That guarantee is the anti-fabrication control for the tabular lane. Deciding what a column means is a judgement that may be made by a model; moving a value is not, and is done only by this module. A projection step that “helpfully” normalized 1.234,56 on the way through would be indistinguishable at the far end from one that invented the number, which is why the property is byte equality rather than equality-after-normalization.

A column whose role is UNMAPPED is reported in ProjectedTable.unmapped_columns and copied nowhere. The file is never refused for carrying one: an export the product does not fully understand still yields every column it does.

See also

FieldRole

The closed vocabulary a column’s meaning is mapped onto.

core.tabular

Produces the normalized table this module projects.

class ColumnRoleMapping(**data)[source]

Bases: BaseModel

What each column of one table means, decided once for the whole file.

Positional rather than keyed by header text: real exports carry blank and duplicated header cells, so a column’s position is the only identifier guaranteed to address exactly one column.

Variables:

roles – One role per column, in column order.

Parameters:

data (Any)

roles: tuple[FieldRole, ...]
role_for(column_index)[source]

Return the role of column_index, or UNMAPPED beyond the mapping.

Return type:

FieldRole

Parameters:

column_index (int)

class ProjectedCell(**data)[source]

Bases: BaseModel

One source cell copied under its column’s role.

Variables:
  • column_index – Zero-based column the value came from.

  • header – The source header text for that column, verbatim.

  • role – The role the column was mapped to.

  • value – The source cell, byte-equal to how the file printed it.

Parameters:

data (Any)

column_index: NonNegativeInt
header: str
role: FieldRole
value: str
class ProjectedRow(**data)[source]

Bases: BaseModel

One normalized row projected under the mapping.

Variables:
  • source_line_number – Physical 1-based line the source row started on.

  • cells – The mapped cells, in column order. Unmapped columns are absent.

Parameters:

data (Any)

source_line_number: int
cells: tuple[ProjectedCell, ...]
value_for(role)[source]

Return the first value carried under role, or None.

Return type:

str | None

Parameters:

role (FieldRole)

class UnmappedColumn(**data)[source]

Bases: BaseModel

One column whose meaning was not established.

Variables:
  • column_index – Zero-based column position.

  • header – The source header text, verbatim, so an operator can see what the product did not recognise.

Parameters:

data (Any)

column_index: NonNegativeInt
header: str
class AmbiguousRole(**data)[source]

Bases: BaseModel

One role claimed by more than one column.

Variables:
  • role – The contested role.

  • column_indexes – Every column mapped to it, in column order.

  • headers – Those columns’ header texts, in the same order.

Parameters:

data (Any)

role: FieldRole
column_indexes: tuple[int, ...]
headers: tuple[str, ...]
class ProjectedTable(**data)[source]

Bases: BaseModel

A normalized table projected under a confirmed column-role mapping.

Variables:
  • rows – The projected rows, in source order.

  • unmapped_columns – Columns carried by the source whose meaning was not established. Reported, never copied.

  • ambiguous_roles – Roles claimed by more than one column. Every claiming column is still projected; the ambiguity is surfaced for an operator to resolve rather than guessed at.

Parameters:

data (Any)

rows: tuple[ProjectedRow, ...]
unmapped_columns: tuple[UnmappedColumn, ...]
ambiguous_roles: tuple[AmbiguousRole, ...]
project_table(table, mapping)[source]

Copy every mapped cell of table into its role under mapping.

Values are copied, never interpreted: each ProjectedCell.value is byte-equal to the NormalizedRow cell it came from. A row shorter than the header (a ragged export) yields only the cells it actually carries rather than being padded or refused.

Parameters:
Return type:

ProjectedTable

Returns:

The projected table, with unmapped and contested columns reported.