Source code for sqlspec.utils.env

"""Environment variable parsing utilities."""

import json
import os
from pathlib import Path
from typing import TYPE_CHECKING, Any, Final, get_args, get_origin, overload

if TYPE_CHECKING:
    from collections.abc import Callable, Sequence

__all__ = ("get_config_val", "get_config_val_with_aliases", "get_env", "get_env_with_aliases", "is_env_set")

TRUE_VALUES: Final[frozenset[str]] = frozenset({"1", "true", "yes", "y", "on", "t"})
FALSE_VALUES: Final[frozenset[str]] = frozenset({"0", "false", "no", "n", "off", "f"})

ParseType = bool | int | float | str | Path | list[Any] | dict[str, Any] | None


class _UnsetType:
    """Sentinel for an omitted type hint."""

    __slots__ = ()


_UNSET = _UnsetType()


class _EnvFactory:
    """Callable factory for delayed environment parsing."""

    __slots__ = ("_aliases", "_default", "_key", "_type_hint")

    def __init__(self, key: str, aliases: "Sequence[str]", default: ParseType, type_hint: object) -> None:
        self._aliases = aliases
        self._default = default
        self._key = key
        self._type_hint = type_hint

    def __call__(self) -> Any:
        if self._aliases:
            return get_config_val_with_aliases(self._key, self._aliases, self._default, self._type_hint)
        return get_config_val(self._key, self._default, self._type_hint)


@overload
def get_env(key: str, default: bool, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], bool]": ...


@overload
def get_env(key: str, default: int, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], int]": ...


@overload
def get_env(key: str, default: float, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], float]": ...


@overload
def get_env(key: str, default: str, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], str]": ...


@overload
def get_env(key: str, default: Path, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], Path]": ...


@overload
def get_env(key: str, default: list[Any], type_hint: "_UnsetType" = _UNSET) -> "Callable[[], list[Any]]": ...


@overload
def get_env(key: str, default: dict[str, Any], type_hint: "_UnsetType" = _UNSET) -> "Callable[[], dict[str, Any]]": ...


@overload
def get_env(key: str, default: None, type_hint: "_UnsetType" = _UNSET) -> "Callable[[], str | None]": ...


@overload
def get_env(key: str, default: ParseType, type_hint: object) -> "Callable[[], Any]": ...


def get_env(key: str, default: ParseType, type_hint: object = _UNSET) -> "Callable[[], Any]":
    """Return a callable that parses an environment variable on demand.

    Args:
        key: Environment variable name.
        default: Value returned when the variable is unset.
        type_hint: Optional parse target, including generic aliases such as ``list[int]``.

    Returns:
        Callable that returns the parsed value.
    """
    return _EnvFactory(key, (), default, type_hint)
@overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: bool, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], bool]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: int, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], int]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: float, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], float]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: str, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], str]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: Path, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], Path]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: list[Any], type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], list[Any]]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: dict[str, Any], type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], dict[str, Any]]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: None, type_hint: "_UnsetType" = _UNSET ) -> "Callable[[], str | None]": ... @overload def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: ParseType, type_hint: object ) -> "Callable[[], Any]": ... def get_env_with_aliases( key: str, aliases: "Sequence[str]", default: ParseType, type_hint: object = _UNSET ) -> "Callable[[], Any]": """Return a callable that parses a canonical environment key plus aliases. Args: key: Canonical environment variable name. aliases: Fallback variable names checked in order. default: Value returned when none of the variables are set. type_hint: Optional parse target, including generic aliases such as ``list[int]``. Returns: Callable that returns the parsed value. """ return _EnvFactory(key, aliases, default, type_hint)