Source code for eradiate.config._settings

from __future__ import annotations

import enum
import os
from pathlib import Path
from typing import Any

from dynaconf import Dynaconf, Validator

from . import _defaults
from ..frame import AzimuthConvention


[docs] class ProgressLevel(enum.IntEnum): """ An enumeration defining valid progress levels. This is an integer enumeration, meaning that levels can be compared to numerics. """
[docs] @staticmethod def convert(value: Any) -> ProgressLevel: """ Attempt conversion of a value to an :class:`.ProgressLevel` instance. The conversion protocol is as follows: * If ``value`` is a string, it is converted to upper case and passed to the indexing operator of :class:`.ProgressLevel`. * If ``value`` is an integer, it is passed to the call operator of :class:`.ProgressLevel`. * If ``value`` is a :class:`.ProgressLevel` instance, it is returned without change. * Otherwise, the method raises an exception. Parameters ---------- value Value to attempt conversion of. Returns ------- Converted value Raises ------ TypeError If no conversion protocol exists for ``value``. """ if isinstance(value, ProgressLevel): return value elif isinstance(value, str): return ProgressLevel[value.upper()] elif isinstance(value, int): return ProgressLevel(value) else: raise TypeError(f"Cannot convert a {type(value)} instance to ProgressLevel")
NONE = 0 #: No progress SPECTRAL_LOOP = enum.auto() #: Up to spectral loop level progress KERNEL = enum.auto() #: Up to kernel level progress
def _validate_source_dir(value: Path | None) -> bool: if value is None: # Import must be local and not use the lazy loader to avoid circular imports from ..kernel._versions import kernel_installed # Detect whether kernel is installed kernel_is_installed, _ = kernel_installed() # Detect Read the Docs build rtd = os.environ.get("READTHEDOCS", "") == "True" if not kernel_is_installed and not rtd: raise RuntimeError( "Could not find a suitable production installation for the " "Eradiate kernel. This is either because you are using Eradiate " "in a production environment without having the eradiate-mitsuba " "package installed, or because you are using Eradiate directly " "from the sources. In the latter case, please make sure the " "'ERADIATE_SOURCE_DIR' environment variable is correctly set to " "the Eradiate installation directory. If you are using Eradiate " "directly from the sources, you can alternatively source the " "provided setpath.sh script. You can install the eradiate-mitsuba " "package using 'pip install eradiate-mitsuba'." ) else: eradiate_init = value / "src" / "eradiate" / "__init__.py" if not eradiate_init.is_file(): raise RuntimeError( f"While configuring Eradiate: could not find {eradiate_init} file. " "Please make sure the 'ERADIATE_SOURCE_DIR' environment variable is " "correctly set to the Eradiate installation directory. If you are " "using Eradiate directly from the sources, you can alternatively " "source the provided setpath.sh script. If you wish to use Eradiate " "in a production environment, you can install the eradiate-mitsuba " "package using 'pip install eradiate-mitsuba' and unset the " "'ERADIATE_SOURCE_DIR' environment variable." ) from FileNotFoundError(eradiate_init) return True def _path_converter(value: Path | str | list[Path | str]) -> list[Path]: """ Helper function that converts ERADIATE_PATH environment variable contents to a list of Path instances. """ if isinstance(value, list): return [Path(x) for x in value] if isinstance(value, Path): return [value] if isinstance(value, str): return _path_converter(value.split(":")) raise NotImplementedError(f"Cannot convert value of type {type(value)}") def _rng_seed_converter(value: Any): if value == "random": return value try: value = int(value) except TypeError: raise ValueError( f"While converting RNG_SEED: Cannot convert value ({value!r}) to int" ) if value < 0: raise ValueError( f"While converting RNG_SEED: value must be a positive integer (got {value})" ) return value #: Main settings data structure. See the `Dynaconf documentation <https://www.dynaconf.com/>`__ #: for details. settings = Dynaconf( settings_files=["eradiate.yml", "eradiate.yaml", "eradiate.toml"], envvar_prefix="ERADIATE", merge_enabled=True, validate_on_update=True, validators=[ Validator( # Process first, other parameters might depend on it "SOURCE_DIR", cast=lambda x: Path(x).resolve() if x is not None else None, condition=_validate_source_dir, default=_defaults.source_dir, ), Validator( "ABSORPTION_DATABASE.ERROR_HANDLING", default=_defaults.absorption_database__error_handling, ), Validator( "AZIMUTH_CONVENTION", cast=AzimuthConvention.convert, default=_defaults.azimuth_convention, ), Validator( "DATA_URL", cast=str, default=_defaults.data_url, ), Validator( "DATA_PATH", cast=Path, default=_defaults.data_path, ), Validator( "OFFLINE", cast=bool, default=_defaults.offline, ), Validator( "PATH", cast=_path_converter, default=_defaults.path, ), Validator( "PROGRESS", cast=ProgressLevel.convert, default=_defaults.progress, ), Validator( "RNG_SEED", cast=_rng_seed_converter, default=_defaults.rng_seed, ), ], ) def __getattr__(name): # Called if attribute cannot be resolved if name == "SOURCE_DIR": return settings.get("SOURCE_DIR") raise AttributeError(f"module '{__name__}' has no attribute '{name}'")