Source code for giql.table

"""Table configuration for GIQL transpilation.

This module defines the Table dataclass for configuring genomic table schemas.
"""

from dataclasses import dataclass
from typing import Literal

from giql.constants import DEFAULT_CHROM_COL
from giql.constants import DEFAULT_END_COL
from giql.constants import DEFAULT_GENOMIC_COL
from giql.constants import DEFAULT_START_COL
from giql.constants import DEFAULT_STRAND_COL


[docs] @dataclass class Table: """Genomic table configuration for transpilation. This class defines how genomic intervals are stored in a database table, mapping a pseudo-column name (genomic_col) to the physical columns that store chromosome, start, end, and optionally strand information. Parameters ---------- name : str The table name. genomic_col : str The pseudo-column name used in GIQL queries to reference the genomic interval (default: "interval"). chrom_col : str The physical column name storing chromosome/contig (default: "chrom"). start_col : str The physical column name storing interval start position (default: "start"). end_col : str The physical column name storing interval end position (default: "end"). strand_col : str | None The physical column name storing strand information, or None if the table has no strand column (default: "strand"). coordinate_system : Literal["0based", "1based"] The coordinate system used for positions (default: "0based"). interval_type : Literal["half_open", "closed"] The interval endpoint convention (default: "half_open"). Examples -------- Using default column names (via transpile):: sql = transpile(query, tables=["peaks"]) Mixing default and custom table configurations:: sql = transpile( query, tables=[ "peaks", Table( "variants", genomic_col="position", chrom_col="chr", start_col="pos_start", end_col="pos_end", strand_col=None, # No strand column coordinate_system="1based", interval_type="closed", ), ], ) """ name: str genomic_col: str = DEFAULT_GENOMIC_COL chrom_col: str = DEFAULT_CHROM_COL start_col: str = DEFAULT_START_COL end_col: str = DEFAULT_END_COL strand_col: str | None = DEFAULT_STRAND_COL coordinate_system: Literal["0based", "1based"] = "0based" interval_type: Literal["half_open", "closed"] = "half_open"
[docs] def __post_init__(self) -> None: """Validate field values after initialization.""" if self.coordinate_system not in ("0based", "1based"): raise ValueError( f"coordinate_system must be '0based' or '1based', " f"got {self.coordinate_system!r}" ) if self.interval_type not in ("half_open", "closed"): raise ValueError( f"interval_type must be 'half_open' or 'closed', " f"got {self.interval_type!r}" )
class Tables: """Container for Table configurations. Provides lookup of Table objects by name for use during transpilation. """ def __init__(self) -> None: self._tables: dict[str, Table] = {} def register(self, name: str, table: Table) -> None: """Register a table configuration. Parameters ---------- name : str The table name to register. table : Table Table configuration to register. """ self._tables[name] = table def get(self, name: str) -> Table | None: """Get a table configuration by name. Parameters ---------- name : str Table name to look up. Returns ------- Table | None Table configuration if found, None otherwise. """ return self._tables.get(name) def __contains__(self, name: str) -> bool: return name in self._tables def __iter__(self): return iter(self._tables.values())