"""Data models for the table layout exporter."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class DimensionMember:
"""One dimensional assignment: a dimension (property) to a member."""
property_id: int
dimension_label: str
dimension_code: str
domain_code: str
member_label: str
member_code: str
data_type_code: str = ""
hierarchy_code: str = ""
sign: str = ""
@dataclass(frozen=True)
class ReleaseWindow:
"""Validity window of the version being exported.
Codes and signatures are release-versioned, so a workbook must show
the ones in force while its module version was reportable — not
today's. The window is the module version's start/end releases (the
table version's own, when tables are exported outside a module).
``start_release_id`` of ``None`` means "since the beginning" and
``end_release_id`` of ``None`` means "still open".
"""
start_release_id: Optional[int] = None
end_release_id: Optional[int] = None
@dataclass
class EnumValue:
"""One allowed value of an enumerated variable."""
code: str
label: str
depth: int = 0
# Fully qualified member signature (e.g. ``eba_CU:ALL``).
signature: str = ""
# Code of the category the member is filed in, which is the one
# its own code belongs to: a hierarchy hanging from a
# super-category draws its values from the categories composing
# it, and each names itself with its own.
category_code: str = ""
@dataclass
class Enumeration:
"""The hierarchy that restricts an enumerated variable's values."""
subcategory_vid: int
code: str
name: str
category_code: str
values: list[EnumValue] = field(default_factory=list)
@dataclass
class LayoutHeader:
"""A resolved header in display order."""
header_id: int
header_vid: int
code: str
label: str
direction: str # "x" (column), "y" (row), "z" (sheet)
order: int
is_abstract: bool
is_key: bool
parent_header_id: Optional[int]
parent_first: bool
depth: int = 0
sort_key: str = ""
property_id: Optional[int] = None
context_id: Optional[int] = None
categorisations: list[DimensionMember] = field(default_factory=list)
subcategory_vid: Optional[int] = None
subcategory_code: str = ""
subcategory_description: str = ""
subcategory_cat_code: str = ""
# Open-row key column fields (populated for IsKey columns)
key_variable_vid: Optional[int] = None
key_variable_id: Optional[int] = None
key_data_type_code: str = ""
key_property_name: str = ""
key_categorisations: list["DimensionMember"] = field(default_factory=list)
key_enumeration: Optional[Enumeration] = None
@dataclass
class CellData:
"""One cell in the table grid."""
row_header_id: Optional[int]
col_header_id: int
sheet_header_id: Optional[int]
variable_vid: Optional[int]
variable_id: Optional[int] = None
is_excluded: bool = False
is_void: bool = False
sign: str = ""
data_type_code: str = ""
domain_label: str = ""
dp_categorisations: list[DimensionMember] = field(default_factory=list)
# True when the cell has no variable yet and its metadata was
# derived from the table structure instead.
is_derived: bool = False
# Enumerated cells only: the hierarchy of the bounding header that
# restricts which values may be reported here.
subcategory_vid: Optional[int] = None
enumeration: Optional[Enumeration] = None
[docs]
@dataclass
class ExportConfig:
"""Configuration flags for the export."""
annotate: bool = True
# Tables under construction have cells before their variables are
# generated. When set, such a cell's property and dimensions are
# derived from the headers bounding it, so the workbook shows the
# datapoint the table is being built to hold.
derive_missing_variables: bool = True
add_header_comments: bool = True
add_cell_comments: bool = True
show_code_row: bool = True
show_code_column: bool = True
show_abstract_header_codes: bool = False
[docs]
@dataclass
class TableLayout:
"""Complete processed layout for one DPM table."""
table_vid: int
table_code: str
table_name: str
rows: list[LayoutHeader] = field(default_factory=list)
columns: list[LayoutHeader] = field(default_factory=list)
sheets: list[LayoutHeader] = field(default_factory=list)
cells: dict[tuple[Optional[int], int, Optional[int]], CellData] = field(
default_factory=dict,
)
max_col_depth: int = 0
max_row_depth: int = 0
dimension_ids: list[tuple[int, str]] = field(default_factory=list)
is_open_row: bool = False