Skip to content

Options

Process-global options (string keys, no symbol type) plus the per-frequency holidays_map. option_scope is a contextlib-style context manager for scoped overrides.

tsecon._options

Global package options.

Mirrors TimeSeriesEcon.jl/src/options.jl. A small dictionary of process-global settings consulted by other modules at call time. Public API:

  • :func:getoption / :func:setoption — generic accessors.
  • :func:set_holidays_map — install a BDaily Boolean :class:TSeries (True = business day, False = holiday) under "bdaily_holidays_map". Accepts either a pre-built TSeries (set_holidays_map(t)) or a country / subdivision code (set_holidays_map("CA", "ON")); the country form requires the optional holidays extra (pip install 'TimeSeriesEconPy[holidays]') and delegates to the upstream python-holidays package for the calendar data — single source of truth, no vendored CSVs.
  • :func:get_holidays_options — list supported country codes (no arg) or subdivisions of a country (with a country code arg). Mirrors Julia's get_holidays_options.
  • :func:clear_holidays_map — set bdaily_holidays_map back to None.

Recognised option names and their types:

========================== =========================== ================================= Name Type Default ========================== =========================== ================================= bdaily_holidays_map TSeries[BDaily, bool] None or None bdaily_creation_bias "strict" / "previous" / "strict" "next" / "nearest" x13path str "" ========================== =========================== =================================

Setting an unknown option raises :class:KeyError; passing an invalid value for a known option raises :class:ValueError (for the enum-like bias) or :class:TypeError (for the wrong Python type).

The options dictionary is process-global. Tests that mutate it must restore the previous value in a teardown — there is a context-manager helper :func:option_scope for that pattern.

getoption

getoption(name: OptionName | str) -> Any

Return the current value of a recognised option.

Raises :class:KeyError for unknown names.

Source code in src/tsecon/_options.py
def getoption(name: OptionName | str) -> Any:
    """Return the current value of a recognised option.

    Raises :class:`KeyError` for unknown names.
    """
    if name not in _DEFAULTS:
        msg = f"unknown option: {name!r}. Recognised names: {sorted(_DEFAULTS)}."
        raise KeyError(msg)
    return _options[name]

setoption

setoption(name: OptionName | str, value: Any) -> None

Set the value of a recognised option, validating its type.

  • bdaily_creation_bias — must be one of "strict", "previous", "next", "nearest".
  • bdaily_holidays_map — must be None or a Boolean BDaily :class:~tsecon.tseries.TSeries.
  • x13path — must be a string.
Source code in src/tsecon/_options.py
def setoption(name: OptionName | str, value: Any) -> None:
    """Set the value of a recognised option, validating its type.

    * ``bdaily_creation_bias`` — must be one of ``"strict"``, ``"previous"``,
      ``"next"``, ``"nearest"``.
    * ``bdaily_holidays_map`` — must be ``None`` or a Boolean BDaily
      :class:`~tsecon.tseries.TSeries`.
    * ``x13path`` — must be a string.
    """
    if name == "bdaily_creation_bias":
        if value not in VALID_BDAILY_BIASES:
            msg = (
                f"bdaily_creation_bias must be one of {sorted(VALID_BDAILY_BIASES)}; "
                f"received {value!r}."
            )
            raise ValueError(msg)
        _options[name] = value
        return
    if name == "bdaily_holidays_map":
        if value is not None:
            _validate_holidays_map(value)
        _options[name] = value
        return
    if name == "x13path":
        if not isinstance(value, str):
            msg = f"x13path must be a string; received {type(value).__name__}."
            raise TypeError(msg)
        _options[name] = value
        return
    msg = f"unknown option: {name!r}. Recognised names: {sorted(_DEFAULTS)}."
    raise KeyError(msg)

set_holidays_map

set_holidays_map(
    arg: Any, subdivision: str | None = None
) -> None

Install a BDaily Boolean holidays map under bdaily_holidays_map.

Two call forms:

  • set_holidays_map(t) — install a pre-built BDaily Boolean :class:~tsecon.tseries.TSeries (True = business day, False = holiday).
  • set_holidays_map("CA", "ON") — fetch the calendar for the given country / subdivision from the holidays PyPI package, build a BDaily Boolean TSeries spanning bdaily("1970-01-01") to bdaily("2049-12-31") (matches the Julia upstream's default range), and install it.

Parameters:

Name Type Description Default
arg Any

Either a pre-built BDaily Boolean :class:~tsecon.tseries.TSeries or a country code string accepted by :func:holidays.country_holidays (ISO 3166 alpha-2 like "CA", "US", "DK"; alpha-3 codes like "CAN" are also accepted — whatever the upstream package supports).

required
subdivision str | None

Optional subdivision code (ISO 3166-2 short form, e.g. "ON", "QC", "CA"). Only meaningful when arg is a country code; passing it with a TSeries raises :class:TypeError.

None

Raises:

Type Description
ImportError

arg is a string and the holidays package is not installed. The error message includes the pip install hint.

ValueError

arg is an unsupported country code, or subdivision is not a recognised subdivision of arg. The Julia upstream raises :class:ArgumentError here.

TypeError

subdivision is passed alongside a TSeries, or arg is neither a string nor a TSeries.

Notes

The country / subdivision codes follow the python-holidays package's conventions (ISO 3166), which differ in minor cases from the Julia upstream's CSV-derived names (e.g. the Julia CSVs spell a few subdivisions with spaces that the package replaces with underscores or drops). The package is the single source of truth; discover the supported codes with :func:get_holidays_options.

Examples:

>>> set_holidays_map("DK")  # Denmark, federal holidays
>>> set_holidays_map("CA", "ON")  # Ontario, Canada
>>> from tsecon import bdaily, TSeries, MITRange
>>> cal = TSeries.trues(MITRange(bdaily("2022-01-03"), bdaily("2022-12-30")))
>>> set_holidays_map(cal)  # pre-built TSeries
Source code in src/tsecon/_options.py
def set_holidays_map(arg: Any, subdivision: str | None = None) -> None:
    """Install a BDaily Boolean holidays map under ``bdaily_holidays_map``.

    Two call forms:

    * ``set_holidays_map(t)`` — install a pre-built BDaily Boolean
      :class:`~tsecon.tseries.TSeries` (``True`` = business day,
      ``False`` = holiday).
    * ``set_holidays_map("CA", "ON")`` — fetch the calendar for the given
      country / subdivision from the ``holidays`` PyPI package, build a
      BDaily Boolean TSeries spanning ``bdaily("1970-01-01")`` to
      ``bdaily("2049-12-31")`` (matches the Julia upstream's default
      range), and install it.

    Parameters
    ----------
    arg
        Either a pre-built BDaily Boolean :class:`~tsecon.tseries.TSeries`
        or a country code string accepted by
        :func:`holidays.country_holidays` (ISO 3166 alpha-2 like ``"CA"``,
        ``"US"``, ``"DK"``; alpha-3 codes like ``"CAN"`` are also accepted
        — whatever the upstream package supports).
    subdivision
        Optional subdivision code (ISO 3166-2 short form, e.g. ``"ON"``,
        ``"QC"``, ``"CA"``). Only meaningful when ``arg`` is a country
        code; passing it with a TSeries raises :class:`TypeError`.

    Raises
    ------
    ImportError
        ``arg`` is a string and the ``holidays`` package is not installed.
        The error message includes the ``pip install`` hint.
    ValueError
        ``arg`` is an unsupported country code, or ``subdivision`` is not
        a recognised subdivision of ``arg``. The Julia upstream raises
        :class:`ArgumentError` here.
    TypeError
        ``subdivision`` is passed alongside a TSeries, or ``arg`` is
        neither a string nor a TSeries.

    Notes
    -----
    The country / subdivision codes follow the ``python-holidays``
    package's conventions (ISO 3166), which differ in minor cases from
    the Julia upstream's CSV-derived names (e.g. the Julia CSVs spell
    a few subdivisions with spaces that the package replaces with
    underscores or drops). The package is the single source of truth;
    discover the supported codes with :func:`get_holidays_options`.

    Examples
    --------
    >>> set_holidays_map("DK")  # Denmark, federal holidays  # doctest: +SKIP
    >>> set_holidays_map("CA", "ON")  # Ontario, Canada  # doctest: +SKIP
    >>> from tsecon import bdaily, TSeries, MITRange  # doctest: +SKIP
    >>> cal = TSeries.trues(MITRange(bdaily("2022-01-03"), bdaily("2022-12-30")))
    >>> set_holidays_map(cal)  # pre-built TSeries  # doctest: +SKIP
    """
    if isinstance(arg, str):
        _set_holidays_map_from_country(arg, subdivision)
        return
    if subdivision is not None:
        msg = (
            "set_holidays_map: `subdivision=` is only meaningful when the first "
            f"argument is a country-code string; received {type(arg).__name__}."
        )
        raise TypeError(msg)
    setoption("bdaily_holidays_map", arg)

get_holidays_options

get_holidays_options(
    country: str | None = None,
) -> tuple[str, ...]

List supported country codes (or subdivisions of a given country).

Mirrors Julia's get_holidays_options(country=nothing). Both no-arg and country-arg forms return a sorted tuple. Subdivisions are reported using the country's native code (ISO 3166-2 short form), exactly as the holidays package exposes them.

Parameters:

Name Type Description Default
country str | None

Optional country code accepted by :func:holidays.country_holidays. When None, return all supported country codes.

None

Returns:

Type Description
tuple of str

Sorted country codes (no arg) or sorted subdivision codes (one arg). A country with no subdivisions returns an empty tuple.

Raises:

Type Description
ImportError

The holidays package is not installed.

ValueError

country is not a supported country code. The Julia upstream raises :class:ArgumentError.

Source code in src/tsecon/_options.py
def get_holidays_options(country: str | None = None) -> tuple[str, ...]:
    """List supported country codes (or subdivisions of a given country).

    Mirrors Julia's ``get_holidays_options(country=nothing)``. Both no-arg
    and country-arg forms return a sorted tuple. Subdivisions are reported
    using the country's native code (ISO 3166-2 short form), exactly as
    the ``holidays`` package exposes them.

    Parameters
    ----------
    country
        Optional country code accepted by
        :func:`holidays.country_holidays`. When ``None``, return all
        supported country codes.

    Returns
    -------
    tuple of str
        Sorted country codes (no arg) or sorted subdivision codes (one
        arg). A country with no subdivisions returns an empty tuple.

    Raises
    ------
    ImportError
        The ``holidays`` package is not installed.
    ValueError
        ``country`` is not a supported country code. The Julia upstream
        raises :class:`ArgumentError`.
    """
    holidays_mod = _require_holidays()
    countries = holidays_mod.list_supported_countries()
    if country is None:
        return tuple(sorted(countries))
    if country not in countries:
        msg = (
            f"Unsupported country: {country!r}. "
            "Call get_holidays_options() (no argument) to list supported codes."
        )
        raise ValueError(msg)
    return tuple(sorted(countries[country]))

clear_holidays_map

clear_holidays_map() -> None

Reset bdaily_holidays_map to None.

Source code in src/tsecon/_options.py
def clear_holidays_map() -> None:
    """Reset ``bdaily_holidays_map`` to ``None``."""
    setoption("bdaily_holidays_map", None)

get_holidays_map

get_holidays_map() -> Any

Return the currently installed holidays map (or None).

Source code in src/tsecon/_options.py
def get_holidays_map() -> Any:
    """Return the currently installed holidays map (or ``None``)."""
    return _options["bdaily_holidays_map"]

option_scope

option_scope(**overrides: Any) -> Iterator[None]

Context manager that temporarily overrides one or more options.

On exit, every overridden option is restored to its prior value. Convenient for tests; the wrapper goes through :func:setoption so the same validation applies.

Source code in src/tsecon/_options.py
@contextmanager
def option_scope(**overrides: Any) -> Iterator[None]:
    """Context manager that temporarily overrides one or more options.

    On exit, every overridden option is restored to its prior value.
    Convenient for tests; the wrapper goes through :func:`setoption` so the
    same validation applies.
    """
    saved: dict[str, Any] = {name: _options[name] for name in overrides}
    try:
        for name, value in overrides.items():
            setoption(name, value)
        yield
    finally:
        for name, value in saved.items():
            _options[name] = value