Source code for vak.config.config

"""Class that represents the TOML configuration file used with the vak command-line interface."""

from __future__ import annotations

import pathlib

from attr.validators import instance_of, optional
from attrs import define, field

from . import load
from .eval import EvalConfig
from .learncurve import LearncurveConfig
from .predict import PredictConfig
from .prep import PrepConfig
from .train import TrainConfig
from .validators import are_keys_valid, are_tables_valid

TABLE_CLASSES_MAP = {
    "eval": EvalConfig,
    "learncurve": LearncurveConfig,
    "predict": PredictConfig,
    "prep": PrepConfig,
    "train": TrainConfig,
}


def _validate_tables_to_parse_arg_convert_list(
    tables_to_parse: str | list[str],
) -> list[str]:
    """Helper function used by :func:`from_toml` that
    validates the ``tables_to_parse`` argument,
    and returns it as a list of strings."""
    if isinstance(tables_to_parse, str):
        tables_to_parse = [tables_to_parse]

    if not isinstance(tables_to_parse, list):
        raise TypeError(
            f"`tables_to_parse` should be a string or list of strings but type was: {type(tables_to_parse)}"
        )

    if not all(
        [isinstance(table_name, str) for table_name in tables_to_parse]
    ):
        raise ValueError(
            "All table names in 'tables_to_parse' should be strings"
        )
    if not all(
        [
            table_name in list(TABLE_CLASSES_MAP.keys())
            for table_name in tables_to_parse
        ]
    ):
        raise ValueError(
            "All table names in 'tables_to_parse' should be valid names of tables. "
            f"Values for 'tables were: {tables_to_parse}.\n"
            f"Valid table names are: {list(TABLE_CLASSES_MAP.keys())}"
        )
    return tables_to_parse


[docs] @define class Config: """Class that represents the TOML configuration file used with the vak command-line interface. Attributes ---------- prep : vak.config.prep.PrepConfig Represents ``[vak.prep]`` table of config.toml file train : vak.config.train.TrainConfig Represents ``[vak.train]`` table of config.toml file eval : vak.config.eval.EvalConfig Represents ``[vak.eval]`` table of config.toml file predict : vak.config.predict.PredictConfig Represents ``[vak.predict]`` table of config.toml file. learncurve : vak.config.learncurve.LearncurveConfig Represents ``[vak.learncurve]`` table of config.toml file """ prep = field(validator=optional(instance_of(PrepConfig)), default=None) train = field(validator=optional(instance_of(TrainConfig)), default=None) eval = field(validator=optional(instance_of(EvalConfig)), default=None) predict = field( validator=optional(instance_of(PredictConfig)), default=None ) learncurve = field( validator=optional(instance_of(LearncurveConfig)), default=None )
[docs] @classmethod def from_config_dict( cls, config_dict: dict, tables_to_parse: str | list[str] | None = None, toml_path: str | pathlib.Path | None = None, ) -> "Config": """Return instance of :class:`Config` class, given a :class:`dict` containing the contents of a TOML configuration file. This :func:`classmethod` expects the output of :func:`vak.config.load._load_from_toml_path`, that converts a :class:`tomlkit.TOMLDocument` to a :class:`dict`, and returns the :class:`dict` that is accessed by the top-level key ``'vak'``. Parameters ---------- config_dict : dict Python ``dict`` containing a .toml configuration file, parsed by the ``toml`` library. toml_path : str, pathlib.Path path to a configuration file in TOML format. Default is None. Not required, used only to make any error messages clearer. tables_to_parse : str, list Name of top-level table or tables from configuration file that should be parsed. Can be a string (single table) or list of strings (multiple tables). Default is None, in which case all are validated and parsed. Returns ------- config : vak.config.parse.Config instance of :class:`Config` class, whose attributes correspond to the top-level tables in a config.toml file. """ are_tables_valid(config_dict, toml_path) if tables_to_parse is None: tables_to_parse = list( config_dict.keys() ) # i.e., parse all top-level tables else: tables_to_parse = _validate_tables_to_parse_arg_convert_list( tables_to_parse ) config_kwargs = {} for table_name in tables_to_parse: if table_name in config_dict: are_keys_valid(config_dict, table_name, toml_path) table_config_dict = config_dict[table_name] config_kwargs[table_name] = TABLE_CLASSES_MAP[ table_name ].from_config_dict(table_config_dict) else: raise KeyError( f"A table specified in `tables_to_parse` was not found in the config: {table_name}" ) return cls(**config_kwargs)
[docs] @classmethod def from_toml_path( cls, toml_path: str | pathlib.Path, tables_to_parse: list[str] | None = None, ) -> "Config": """Return instance of :class:`Config` class, given the path to a TOML configuration file. Parameters ---------- toml_path : str, pathlib.Path Path to a configuration file in TOML format. Parsed by ``toml`` library, then converted to an instance of ``vak.config.parse.Config`` by calling ``vak.parse.from_toml`` tables_to_parse : str, list Name of table or tables from configuration file that should be parsed. Can be a string (single table) or list of strings (multiple tables). Default is None, in which case all are validated and parsed. Returns ------- config : vak.config.parse.Config instance of :class:`Config` class, whose attributes correspond to tables in a config.toml file. """ config_dict: dict = load._load_toml_from_path(toml_path) return cls.from_config_dict(config_dict, tables_to_parse, toml_path)