Source code for magni.utils.validation._levels

"""
..
    Copyright (c) 2014-2017, Magni developers.
    All rights reserved.
    See LICENSE.rst for further information.

Module providing the `validate_levels` function.

Routine listings
----------------
validate_levels(name, levels)
    Validate containers and mappings as well as contained objects.

"""

from __future__ import division

from magni.utils.validation import validate_generic as _generic
from magni.utils.validation import validate_numeric as _numeric
from magni.utils.validation._util import get_var as _get_var
from magni.utils.validation._util import report as _report


[docs]def validate_levels(name, levels): """ Validate containers and mappings as well as contained objects The present function is meant to valdiate the 'levels' of a variable. That is, the value of the variable itself, the values of the second level (in case the value is a list, tuple, or dict), the values of the third level, and so on. Parameters ---------- name : None The name of the variable to be validated. levels : list or tuple The list of levels. See Also -------- magni.utils.validation.validate_generic : Validate non-numeric objects. magni.utils.validation.validate_numeric : Validate numeric objects. Notes ----- `name` must refer to a variable in the parent scope of the function or method decorated by `magni.utils.validation.decorate_validation` which is closest to the top of the call stack. If `name` is a string then there must be a variable of that name in that scope. If `name` is a set-like object then there must be a variable having the first value in that set-like object as name. The remaining values are used as keys/indices on the variable to obtain the variable to be validated. For example, the `name` ('name', 0, 'key') refers to the variable "name[0]['key']". `levels` is a list containing the levels. The value of the variable is validated against the first level. In case the value is a list, tuple, or dict, the values contained in this are validated against the second level and so on. Each level is itself a list with the first value being either 'generic' or 'numeric' followed by the arguments that should be passed to the respective function (with the exception of `name` which is automatically prepended by the present function). Examples -------- Every public function and method of the present package (with the exception of the functions of this subpackage itself) validates every argument and keyword argument using the functionality of this subpackage. Thus, for examples of how to use the present function, browse through the code. """ if name is None: return ('levels', levels) if isinstance(name, (list, tuple)): name = list(name) else: name = [name] if not isinstance(levels, (list, tuple)): _report(TypeError, 'must be in {!r}.', (list, tuple), var_name='levels', var_value=levels, expr='type({})', prepend='Invalid validation call: ') if len(levels) == 0: _report(ValueError, 'must be > 0.', var_name='levels', var_value=levels, expr='len({})', prepend='Invalid validation call: ') _validate_level(name, _get_var(name), levels)
[docs]def _validate_level(name, var, levels, index=0): """ Validate a level. Parameters ---------- name : None The name of the variable. var : None The value of the variable. levels : set-like The levels. index : int The index of the current level. (the default is 0) """ if not isinstance(levels[index], (list, tuple)): _report(TypeError, 'must be in {!r}.', (list, tuple), var_name=('levels', index), var_value=levels[index], expr='type({})', prepend='Invalid validation call: ') if len(levels[index]) == 0: _report(ValueError, 'must be > 0.', var_name=('levels', index), var_value=levels[index], expr='len({})', prepend='Invalid validation call: ') if levels[index][0] not in ('generic', 'numeric'): _report(ValueError, 'must be in {!r}.', ('generic', 'numeric'), var_name=('levels', index, 0), var_value=levels[index][0], prepend='Invalid validation call: ') func = {'generic': _generic, 'numeric': _numeric}[levels[index][0]] args = (name,) + tuple(levels[index][1:]) + (var,) func(*args) if index + 1 < len(levels): if isinstance(var, (list, tuple)): for i, value in enumerate(var): _validate_level(name + [i], value, levels, index + 1) elif isinstance(var, dict): for key, value in var.items(): _validate_level(name + [key], value, levels, index + 1)