Source code for comdab.models.type

from typing import Any, Unpack, get_args

from pydantic import ConfigDict, Field

from comdab.models.base import ComdabModel
from comdab.path import (
    ComdabPath,
    _PathDescriptor,  # pyright: ignore[reportPrivateUsage]  # typing usage only
    dict_of_paths,
    sub_path,
    terminal_path,
)


class _BaseComdabType(ComdabModel, frozen=True):
    """Root class representing a database type.

    Equivalent to a :class:`sqlalchemy.types.TypeEngine` object.
    """

    type: str = ""  # Model field, but defined in __init_subclass__
    implem_name: str
    extra: dict[str, Any] = Field(default_factory=dict)

    def __init_subclass__(cls, **kwargs: Unpack[ConfigDict]) -> None:
        super().__init_subclass__(**kwargs)
        cls.type = cls.__name__

    class Path(ComdabPath):
        type = terminal_path()
        implem_name = terminal_path()
        extra = dict_of_paths(ComdabPath)

        # Union of fields of all types
        length = terminal_path()
        collation = terminal_path()
        precision = terminal_path()
        scale = terminal_path()
        with_timezone = terminal_path()
        second_precision = terminal_path()
        day_precision = terminal_path()
        length = terminal_path()
        item_type: _PathDescriptor["_BaseComdabType.Path"]  # Defined below (references itself)
        dimensions = terminal_path()
        values = terminal_path()
        type_name = terminal_path()


_item_type_descr = sub_path(_BaseComdabType.Path)
_item_type_descr.__set_name__(_BaseComdabType.Path, "item_type")
_BaseComdabType.Path.item_type = _item_type_descr


[docs] class ComdabTypes: """Registry of all data types handled by comdab. Each class member represent a database type, equivalent to a :class:`sqlalchemy.types.TypeEngine` class. """
[docs] class String(_BaseComdabType, frozen=True): length: int | None collation: str | None
[docs] class Integer(_BaseComdabType, frozen=True): pass
[docs] class Float(_BaseComdabType, frozen=True): pass
[docs] class Numeric(_BaseComdabType, frozen=True): precision: int | None scale: int | None
[docs] class Boolean(_BaseComdabType, frozen=True): pass
[docs] class DateTime(_BaseComdabType, frozen=True): with_timezone: bool
[docs] class Date(_BaseComdabType, frozen=True): pass
[docs] class Time(_BaseComdabType, frozen=True): pass
[docs] class Interval(_BaseComdabType, frozen=True): second_precision: int | None day_precision: int | None
[docs] class JSON(_BaseComdabType, frozen=True): pass
[docs] class Binary(_BaseComdabType, frozen=True): length: int | None
[docs] class UUID(_BaseComdabType, frozen=True): pass
[docs] class Array(_BaseComdabType, frozen=True): item_type: "ComdabType" dimensions: int
[docs] class Enum(_BaseComdabType, frozen=True): values: set[str] type_name: str | None collation: str | None
# === PostgreSQL-specific types ===
[docs] class HSTORE(_BaseComdabType, frozen=True): pass
[docs] class Range(_BaseComdabType, frozen=True): item_type: "ComdabType"
[docs] class MultiRange(_BaseComdabType, frozen=True): item_type: "ComdabType"
# === Unknown type ===
[docs] class Unknown(_BaseComdabType, frozen=True): """A type not handled (yet) by comdab, when run with ``allow_unknown_types=True``."""
type ComdabType = ( # Union of all TYPES members ComdabTypes.String | ComdabTypes.Integer | ComdabTypes.Float | ComdabTypes.Numeric | ComdabTypes.Boolean | ComdabTypes.DateTime | ComdabTypes.Date | ComdabTypes.Time | ComdabTypes.Interval | ComdabTypes.JSON | ComdabTypes.Binary | ComdabTypes.UUID | ComdabTypes.Array | ComdabTypes.Enum | ComdabTypes.HSTORE | ComdabTypes.Range | ComdabTypes.MultiRange | ComdabTypes.Unknown ) ComdabType_Path = _BaseComdabType.Path assert set(get_args(ComdabType.__value__)) == { t for t in ComdabTypes.__dict__.values() if isinstance(t, type) and issubclass(t, _BaseComdabType) }, "Mismatch between ComdabType and ComdabTypes members!"