Commit 45f97c45 authored by Paulo Medeiros's avatar Paulo Medeiros
Browse files

Lint config_parser.py docstrings.

parent ec0609b2
......@@ -35,6 +35,7 @@ class UndefinedValueType:
We will use instances of this class to mark things such as missing
config file values, unspecified defaults in functions, etc. We don't
want to use None in these cases, as None may be a valid arg value.
"""
def __init__(
......@@ -92,7 +93,7 @@ NoDefaultProvided = UndefinedValueType(name="NoDefaultProvided")
class UndefinedConfigValueError(Exception):
"""Exception to be raised when retrieving undefined config value."""
"""Exception to be raised if UndefinedConfigValue is encountered."""
class ConfigDict(DotMap):
......@@ -112,6 +113,7 @@ class ConfigDict(DotMap):
(c) If self._dynamic is True, then, instead of raising KeyError:
* Retrievals on missing keys return UndefinedConfigValue
* Sublevels are automatically created if needed upon item setting
"""
def __init__(self, *args, **kwargs):
......@@ -225,6 +227,8 @@ class _MetadataDict(ConfigDict):
class _ConfigMetadataRegistry(ConfigDict):
"""Class to help register metadata about known config options."""
def register(
self,
key,
......@@ -235,6 +239,28 @@ class _ConfigMetadataRegistry(ConfigDict):
astype=NoDefaultProvided,
case_sensitive=NoDefaultProvided,
):
"""Register a metadata registry entry.
Args:
key (str): The key (name) of the param metadata to be registed.
default (obj): The default value for the registered metadata.
(Default value = NoDefaultProvided)
minval (obj): An optional min value.
(Default value = NoDefaultProvided).
maxval (obj): An optional max value.
(Default value = NoDefaultProvided).
choices (list): Optional list of allowed choices.
(Default value = NoDefaultProvided).
astype (type): Optional type info for the metadata. Used, e.g.,
for typecasting. (Default value = NoDefaultProvided).
case_sensitive (bool): Whether future lookups should consider
character case in the metadata key.
(Default value = NoDefaultProvided).
Raises:
TypeError: If key is not a string.
"""
if not isinstance(key, str):
raise TypeError("key must be a string")
try:
......@@ -260,7 +286,15 @@ class _ConfigMetadataRegistry(ConfigDict):
self._dynamic = False
def copy_template(self, key):
# "section" will be defined using a context manager
"""Copy contents from self["_template"] to section.key.
"section" needs to be defined in the upper-level scope,
using a context manager.
Args:
key (str): String such that the destination where the template
will be copied into is section.key.
"""
dest_key = "{}.{}".format(section, key)
if "." in section:
template_key, _, _dropped = section.rpartition(".")
......@@ -479,6 +513,28 @@ def _parse_dtg_entires(dtgs_config):
def _raw2parsed(raw, recog_configs=config_metadata, parent_keys=()):
"""Return parsed confif from raw input, validating with metadata.
Descend recursively into input dict raw and validate raw configs against
the registered metadata. Configs not that don't have corresponding metadata
info will be passed unchanged.
Args:
raw (dict): Raw configs, as read from config file.
recog_configs (_ConfigMetadataRegistry): Configs for which we have
registered metadata. Default value = config_metadata.
parent_keys (tuple): Tuple of all config dict keys, in order, traversed
to get to the current raw dict. Default value = (). Used for dicts
nested within the top-level raw.
Returns:
ParsedConfig: Parsed configs from raw.
Raises:
ValueError: If any config in raw is not a valid choice, or has an
invalid value.
"""
# Do not use mutable data structures for argument defaults (parent_keys)
parent_keys = list(parent_keys)
parsed = ConfigDict(_dynamic=True)
......@@ -559,6 +615,27 @@ def _raw2parsed(raw, recog_configs=config_metadata, parent_keys=()):
def _fill_defaults(raw, recog_configs=config_metadata, parent_keys=()):
"""Fill defaults into raw config according to registered metadata.
Descend recursively into input dict raw and fill in default values
according to metadata registered in this module.
Args:
raw (dict): Raw configs, as read from config file.
recog_configs (_ConfigMetadataRegistry): Configs for which we have
registered metadata. Default value = config_metadata.
parent_keys (tuple): Tuple of all config dict keys, in order, traversed
to get to the current raw dict. Default value = (). Used for dicts
nested within the top-level raw.
Returns:
dict: Copy of raw with defaults filled in.
Raises:
TypeError: If any metadata dict found while parsing raw is not an
instance of either _MetadataDict or ConfigDict classes.
"""
# Do not use mutable data structures for argument defaults (parent_keys)
parent_keys = list(parent_keys)
parsed = ConfigDict(raw, _dynamic=False)
......@@ -607,7 +684,8 @@ def _fill_defaults(raw, recog_configs=config_metadata, parent_keys=()):
class ParsedConfig:
"""Parsed version of config file or raw dict.
Each section in config will be accessible as self.section
Each section in config will be accessible as self.section.
"""
def __init__(
......@@ -656,7 +734,7 @@ class ParsedConfig:
return self.get(keys_for_get, default)
def get(self, item, default=UndefinedConfigValue):
"""Return parsed config values for the active clustering method."""
"""Implement get method with default UndefinedConfigValue."""
rtn = self._parsed.get(item, default=UndefinedConfigValue)
if rtn is UndefinedConfigValue:
if default is NoDefaultProvided:
......@@ -695,7 +773,15 @@ class ParsedConfig:
def read_config(config_path):
"""Read config file at location "config_path"."""
"""Read config file at location "config_path".
Args:
config_path (pathlib.Path): The path to the config file.
Returns:
ParsedConfig: Parsed configs read from config_path.
"""
logging.info("Reading config file %s", Path(config_path).resolve())
config = ParsedConfig(config_path, global_default=UndefinedConfigValue)
return config
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment