Source code for eradiate._config

"""
Global configuration components. The centric part is the
:class:`.EradiateConfig` class, whose defaults can be set using environment
variables. A single instance :data:`.config` is aliased in the top-level module
for convenience.
"""

import enum
import os.path
import pathlib

import attrs
import environ
from environ._environ_config import CNF_KEY, RAISE, _ConfigEntry
from environ.exceptions import ConfigError

from .frame import AzimuthConvention


def var(
    default=RAISE,
    converter=None,
    name=None,
    validator=None,
    help=None,
    on_setattr=None,
):
    """
    Reimplementation of `environ-config`'s :func:`var` with `on_setattr` support.

    Declare a configuration attribute on the body of `config`-decorated class.

    It will be attempted to be filled from an environment variable based on the
    prefix and *name*.

    Parameters
    ----------
    default
        Setting this to a value makes the config attribute optional.

    name : str
        Overwrite name detection with a string.  If not set, the name of the
        attribute is used.

    converter
        A callable that is run with the found value and its return value is
        used.  Please note that it is also run for default values.

    validator
        A callable that is run with the final value. See ``attrs``'s
        `chapter on validation <https://www.attrs.org/en/stable/init.html#validators>`_
        for details.
        You can also use any validator that is
        `shipped with attrs <https://www.attrs.org/en/stable/api.html#validators>`_.

    help : str
        A help string that is used by `generate_help`.

    on_setattr : callable or list of callables or None or attrs.setters.NO_OP, optional
        This argument is directly forwarded to :func:`attrs.field`, with the notable
        difference that the default behaviour executes converters and
        validators.
    """
    if on_setattr is None:
        on_setattr = attrs.setters.pipe(attrs.setters.convert, attrs.setters.validate)

    return attrs.field(
        default=default,
        metadata={CNF_KEY: _ConfigEntry(name, default, None, None, help)},
        converter=converter,
        validator=validator,
        on_setattr=on_setattr,
    )


[docs] class ProgressLevel(enum.IntEnum): """ An enumeration defining valid progress levels. This is an integer enumeration, meaning that levels can be compared. """ NONE = 0 #: No progress SPECTRAL_LOOP = enum.auto() #: Up to spectral loop level progress KERNEL = enum.auto() #: Up to kernel level progress
def format_help_dicts_rst(help_dicts, display_defaults=False): """ Help dictionary formatter for environment variable help generation. """ help_strs = [] for help_dict in help_dicts: help_str = f".. envvar:: {help_dict['var_name']}\n\n" help_str += f" *{'Required' if help_dict['required'] else 'Optional'}" if help_dict.get("default") and display_defaults: help_str += f", default={repr(help_dict['default'])}.* " else: help_str += "*. " if help_dict.get("help_str"): help_str += f"{help_dict['help_str']}" help_strs.append(help_str) return "\n\n".join(help_strs)
[docs] @environ.config(prefix="ERADIATE") class EradiateConfig: """ Global configuration for Eradiate. This class, instantiated once as the :data:`eradiate.config` attribute, contains global configuration parameters for Eradiate. It is initialized using :ref:`environment variables <sec-config-env_vars>` as defaults. See Also -------- :data:`eradiate.config`, `the environ-config library <https://environ-config.readthedocs.io>`_ """ #: Path to the Eradiate source directory. source_dir = var( converter=lambda x: x if x is None else pathlib.Path(x).absolute(), help="Path to the Eradiate source directory. If it is not set, then the " "current setup is assumed to be a production installation of Eradiate.", default=None, ) @source_dir.validator def _dir_validator(self, var, dir): if dir is None: # Import must be local and not use the lazy loader to avoid circular imports from .kernel._versions import kernel_installed is_installed, _ = kernel_installed() if not is_installed: raise ConfigError( "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'." ) return eradiate_init = dir / "src" / "eradiate" / "__init__.py" if not eradiate_init.is_file(): raise ConfigError( 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) #: URL where small data files are located (production use only) small_files_registry_url = var( default="https://raw.githubusercontent.com/eradiate/eradiate-data", converter=str, help="URL where small data files are located (production use only)", ) #: Revision of the small files registry (production use only) small_files_registry_revision = var( default="master", converter=str, help="Revision of the small files registry (production use only)", ) #: URL where large data files are located. data_store_url = var( default="http://eradiate.eu/data/store/", converter=str, help="URL where large data files are located.", ) #: Path to the Eradiate download directory. download_dir = var( converter=lambda x: x if x is None else pathlib.Path(x).absolute(), help="Path to the Eradiate download directory.", default=None, ) #: If ``True``, activate the offline mode. All online data stores #: will be disconnected. offline = environ.bool_var( default=False, help="If ``True``, activate the offline mode. All online data stores " "will be disconnected.", ) #: An integer flag setting the level of progress display (see #: :class:`ProgressLevel`). Values are preferably set using strings #: (``["NONE", "SPECTRAL_LOOP", "KERNEL"]``). Only affects tqdm-based progress #: bars. progress = var( default="KERNEL", converter=lambda x: ProgressLevel[x.upper()] if isinstance(x, str) else ProgressLevel(x), help="An integer flag setting the level of progress display (see" ":class:`.ProgressLevel`). Values are preferably set using strings " '(``["NONE", "SPECTRAL_LOOP", "KERNEL"]``). Only affects tqdm-based ' "progress bars.", ) #: The convention applied when interpreting azimuth values as part #: of the specification of a direction (see :class:`.AzimuthConvention`). #: Values are preferably set using strings (*e.g.* ``"EAST_RIGHT"``, #: ``"NORTH_LEFT"``, etc.). azimuth_convention = var( default="EAST_RIGHT", converter=lambda x: AzimuthConvention[x.upper()] if isinstance(x, str) else x, validator=attrs.validators.instance_of(AzimuthConvention), help="The convention applied when interpreting azimuth values as part " "of the specification of a direction (see :class:`.AzimuthConvention`). " 'Values are preferably set using strings (*e.g.* ``"EAST_RIGHT"``, ' '``"NORTH_LEFT"``, etc.).', )
try: #: Global configuration object instance. #: See :class:`EradiateConfig`. config = EradiateConfig.from_environ() except environ.exceptions.MissingEnvValueError as e: if "ERADIATE_SOURCE_DIR" in e.args: raise ConfigError( f"While configuring Eradiate: environment variable '{e}' is missing. " "Please set this variable to the absolute path to the Eradiate " "installation directory. If you are using Eradiate directly from the " "sources, you can alternatively source the provided setpath.sh script." ) from e else: raise e