Source code for elsheeto.models.csv_stage2
"""Models for storing the result of stage 1 CSV sectioned CSV parsing.
Stage 2 is converting the stage 1 results into key/value and data payload header
sections.
"""
from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field
from elsheeto.models.common import ParsedSheetType
[docs]
class HeaderSection(BaseModel):
"""Representation of a header section in a stage 2 sample sheet."""
#: Original section name (e.g., "header", "reads", "settings")
name: str
#: List of header rows as lists of strings preserving original structure
rows: Annotated[list[list[str]], Field(default_factory=list)]
model_config = ConfigDict(frozen=True)
@property
def key_values(self) -> dict[str, str]:
"""Get key-value pairs as a dictionary for backward compatibility.
Only considers rows with exactly 2 non-empty values as key-value pairs.
"""
result = {}
for row in self.rows:
# Filter out empty cells
non_empty_cells = [cell.strip() for cell in row if cell.strip()]
# Only treat rows with exactly 2 non-empty cells as key-value pairs
if len(non_empty_cells) == 2:
result[non_empty_cells[0]] = non_empty_cells[1]
return result
[docs]
class DataSection(BaseModel):
"""Representation of the data section in a stage 2 sample sheet."""
#: Header names.
headers: Annotated[list[str], Field(default_factory=list)]
#: Header to index map.
header_to_index: Annotated[dict[str, int], Field(default_factory=dict)]
#: Data rows.
data: Annotated[list[list[str]], Field(default_factory=list)]
model_config = ConfigDict(
frozen=True,
)
[docs]
class ParsedSheet(BaseModel):
"""Representation of a stage 2 sample sheet."""
#: Delimiter used in the file.
delimiter: str
#: Resulting sheet type.
sheet_type: ParsedSheetType
#: Zero or more key/value header sections in the sheet.
header_sections: Annotated[list[HeaderSection], Field(default_factory=list)]
#: Single data section in the sheet.
data_section: DataSection
model_config = ConfigDict(
frozen=True,
)