Exemple #1
0
def _check_value(name, var, value_in):
    """
    Check the value of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    value_in : set-like
        The allowed values.

    """

    if value_in is not None:
        if not isinstance(value_in, (list, tuple)):
            _report(TypeError,
                    'must be in {!r}.', (list, tuple),
                    var_name='value_in',
                    var_value=value_in,
                    prepend='Invalid validation call: ')

        if var not in value_in:
            _report(ValueError, 'must be in {!r}.', value_in, var_name=name)
Exemple #2
0
def _check_inheritance(name, var, superclass):
    """
    Check the superclasses of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    superclass : class
        The required superclass.

    """

    if superclass is not None:
        if not isinstance(superclass, type):
            _report(TypeError,
                    'must be a type.',
                    var_name='superclass',
                    var_value=superclass,
                    prepend='Invalid validation call: ')

        if not issubclass(var, superclass):
            _report(TypeError,
                    'must be a subclass of {!r}.',
                    superclass,
                    var_name=name)
Exemple #3
0
def _check_type(name, dtype, types_):
    """
    Check the type of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dtype : type
        The data type of the variable to be validated.
    types_ : set-like
        The accepted types.

    """

    valid = False

    for type_ in types_:
        if type_ not in _types.keys():
            _report(ValueError, 'must be in {!r}.', _types.keys(),
                    var_name='type_', var_value=type_,
                    prepend='Invalid validation call: ')

        if isinstance(dtype(), _types[type_][None]):
            valid = True
            break

    if not valid:
        _report(TypeError, '>>{}.dtype<<, {!r}, must be in {!r}.',
                (name, dtype, types_), prepend='The value(s) of ')
Exemple #4
0
def _check_len(name, var, len_):
    """
    Check the length of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    len_ : int
        The required length.

    """

    if len_ is not None:
        if not isinstance(len_, int):
            _report(TypeError,
                    'must be {!r}.',
                    int,
                    var_name='len_',
                    var_value=len_,
                    expr='type({})',
                    prepend='Invalid validation call: ')

        if not hasattr(var, '__len__') or len(var) != len_:
            _report(ValueError,
                    'must be {!r}.',
                    len_,
                    var_name=name,
                    expr='len({})')
Exemple #5
0
def _check_type(name, dtype, types_):
    """
    Check the type of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dtype : type
        The data type of the variable to be validated.
    types_ : set-like
        The accepted types.

    """

    valid = False

    for type_ in types_:
        if type_ not in list(_types.keys()):
            _report(ValueError,
                    'must be in {!r}.',
                    list(_types.keys()),
                    var_name='type_',
                    var_value=type_,
                    prepend='Invalid validation call: ')

        if isinstance(dtype(), _types[type_][None]):
            valid = True
            break

    if not valid:
        _report(TypeError,
                '>>{}.dtype<<, {!r}, must be in {!r}.', (name, dtype, types_),
                prepend='The value(s) of ')
Exemple #6
0
def _check_shape(name, dshape, shape):
    """
    Check the shape of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dshape : list or tuple
        The shape of the variable to be validated.
    shape : list or tuple
        The accepted shape.

    """

    if shape is not None:
        if not isinstance(shape, (list, tuple)):
            _report(TypeError, 'must be in {!r}.', (list, tuple),
                    var_name='shape', var_value=shape, expr='type({})',
                    prepend='Invalid validation call: ')

        if len(dshape) != len(shape):
            _report(ValueError, '>>len({}.shape)<<, {!r}, must be {!r}.',
                    (name, len(dshape), len(shape)),
                    prepend='The value(s) of ')

        for i, value in enumerate(shape):
            if not isinstance(value, (int, long)):
                _report(TypeError, 'must be {!r}.', (int, long),
                        var_name=('shape', i), var_value=value,
                        expr='type({})', prepend='Invalid validation call: ')

            if value > -1 and dshape[i] != value:
                _report(ValueError, '>>{}.shape[{}]<<, {!r}, must be {!r}.',
                        (name, i, dshape[i], value), prepend='The value(s) of')
Exemple #7
0
def _check_range(name, bounds, range_):
    """
    Check the range of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    bounds : list or tuple
        The bounds of the variable to be validated.
    range_ : None
        The accepted range(s).

    """

    if not isinstance(range_, (list, tuple)):
        range_ = (range_, '[-inf;inf]')

    try:
        tests = [req.split(';') for req in range_]

        for i in (0, 1):
            tests[i][0] = [bounds[i][0], tests[i][0][0], tests[i][0][1:]]
            tests[i][0][1] = {']': '>', '(': '>', '[': '>='}[tests[i][0][1]]
            tests[i][1] = [bounds[i][1], tests[i][1][-1], tests[i][1][:-1]]
            tests[i][1][1] = {'[': '<', ')': '<', ']': '<='}[tests[i][1][1]]

        for expr, tests_ in zip(('real({})', 'imag({})'), tests):
            for func, test in zip(('min', 'max'), tests_):
                bound, op, value = test
                test = '{} {} {}'.format(bound, op, value)

                if not eval(test.replace('inf', 'np.inf')):
                    _report(ValueError,
                            '>>{}({})<<, {!r}, must be {} {!r}.',
                            (func, expr.format(name), bound, op, eval(value)),
                            prepend='The value(s) of ')
    except (AttributeError, KeyError, IndexError, SyntaxError):
        _report(ValueError,
                'must be a valid range.',
                var_name='range_',
                var_value=range_,
                prepend='Invalid validation call: ')
Exemple #8
0
def _check_type(name, var, types_):
    """
    Check the type of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    types_ : set-like
        The allowed types.

    """

    valid = False

    for type_ in types_:
        if isinstance(type_, type):
            if isinstance(var, type_):
                valid = True
                break
        elif type_ in list(_types.keys()):
            if isinstance(var, _types[type_]):
                valid = True
                break
        elif type_ in ('implicit collection', 'collection'):
            if hasattr(var, '__iter__'):
                valid = True
                break
        else:
            _report(ValueError,
                    'must be a valid type.',
                    var_name='type_',
                    var_value=type_,
                    prepend='Invalid validation call: ')

    if not valid:
        _report(TypeError,
                'must be in {!r}.',
                types_,
                var_name=name,
                expr='type({})')
Exemple #9
0
def _check_precision(name, dtype, types_, precision):
    """
    Check the precision of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dtype : type
        The data type of the variable to be validated.
    types_ : set-like
        The list of accepted types.
    precision : None
        The accepted precision(s).

    """

    if isinstance(precision, (list, tuple)):
        precisions = precision
    else:
        precisions = (precision, )

    for precision in precisions:
        if precision not in _precisions:
            _report(ValueError,
                    'must be in {!r}.',
                    _precisions,
                    var_name='precision',
                    var_value=precisions,
                    prepend='Invalid validation call: ')

    if None not in precisions:
        dtypes = [
            _types[type_][precision_] for type_ in types_
            for precision_ in precisions if precision_ in _types[type_]
        ]

        if not isinstance(dtype(), tuple(dtypes)):
            _report(TypeError,
                    '>>{}.dtype<<, {!r}, must be in {!r}.',
                    (name, dtype, dtypes),
                    prepend='The value(s) of ')
Exemple #10
0
def _check_range(name, bounds, range_):
    """
    Check the range of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    bounds : list or tuple
        The bounds of the variable to be validated.
    range_ : None
        The accepted range(s).

    """

    if not isinstance(range_, (list, tuple)):
        range_ = (range_, '[-inf;inf]')

    try:
        tests = [req.split(';') for req in range_]

        for i in (0, 1):
            tests[i][0] = [bounds[i][0], tests[i][0][0], tests[i][0][1:]]
            tests[i][0][1] = {']': '>', '(': '>', '[': '>='}[tests[i][0][1]]
            tests[i][1] = [bounds[i][1], tests[i][1][-1], tests[i][1][:-1]]
            tests[i][1][1] = {'[': '<', ')': '<', ']': '<='}[tests[i][1][1]]

        for expr, tests_ in zip(('real({})', 'imag({})'), tests):
            for func, test in zip(('min', 'max'), tests_):
                bound, op, value = test
                test = '{} {} {}'.format(bound, op, value)

                if not eval(test.replace('inf', 'np.inf')):
                    _report(ValueError, '>>{}({})<<, {!r}, must be {} {!r}.',
                            (func, expr.format(name), bound, op, eval(value)),
                            prepend='The value(s) of ')
    except (AttributeError, KeyError, SyntaxError):
        _report(ValueError, 'must be a valid range.', var_name='range_',
                var_value=range_, prepend='Invalid validation call: ')
Exemple #11
0
def _check_value(name, var, value_in):
    """
    Check the value of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    value_in : set-like
        The allowed values.

    """

    if value_in is not None:
        if not hasattr(value_in, '__iter__'):
            _report(TypeError, 'must be iterable.', var_name='value_in',
                    var_value=value_in, prepend='Invalid validation call: ')

        if var not in value_in:
            _report(ValueError, 'must be in {!r}.', value_in, var_name=name)
Exemple #12
0
def _check_precision(name, dtype, types_, precision):
    """
    Check the precision of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dtype : type
        The data type of the variable to be validated.
    types_ : set-like
        The list of accepted types.
    precision : None
        The accepted precision(s).

    """

    if not isinstance(precision, str) and hasattr(precision, '__iter__'):
        precisions = precision
    else:
        precisions = (precision,)

    if None not in precisions:
        dtypes = []

        for type_ in types_:
            for precison in precisions:
                if precision not in _types[type_]:
                    _report(ValueError, 'must be in {!r}.',
                            _types[type_].keys(), var_name='precision',
                            var_value=precisions,
                            prepend='Invalid validation call: ')

                dtypes.append(_types[type_][precision])

        if not isinstance(dtype(), tuple(dtypes)):
            _report(TypeError, '>>{}.dtype<<, {!r}, must be in {!r}.',
                    (name, dtype, dtypes), prepend='The value(s) of ')
Exemple #13
0
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 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)
Exemple #14
0
def _check_keys(name, var, keys_in, has_keys):
    """
    Check the keys of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    keys_in : set-like
        The allowed keys.
    has_keys : set-like
        The required keys.

    """

    if keys_in is not None:
        if not isinstance(keys_in, (list, tuple)):
            _report(TypeError,
                    'must be in {!r}.', (list, tuple),
                    var_name='keys_in',
                    var_value=keys_in,
                    prepend='Invalid validation call: ')

        for key in list(var.keys()):
            if key not in keys_in:
                _report(KeyError,
                        'must be in {!r}.',
                        keys_in,
                        var_name=name,
                        expr='{}.keys()')

    if has_keys is not None:
        if not isinstance(has_keys, (list, tuple)):
            _report(TypeError,
                    'must be in {!r}.', (list, tuple),
                    var_name='has_keys',
                    var_value=has_keys,
                    prepend='Invalid validation call: ')

        for key in has_keys:
            if key not in list(var.keys()):
                _report(KeyError,
                        'must have the key {!r}.',
                        key,
                        var_name=name)
Exemple #15
0
def _check_type(name, var, types_):
    """
    Check the type of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    types_ : set-like
        The allowed types.

    """

    valid = False

    for type_ in types_:
        if isinstance(type_, type):
            if isinstance(var, type_):
                valid = True
                break
        elif type_ in _types.keys():
            if isinstance(var, _types[type_]):
                valid = True
                break
        elif type_ in ('implicit collection', 'collection'):
            if hasattr(var, '__iter__'):
                valid = True
                break
        else:
            _report(ValueError, 'must be a valid type.', var_name='type_',
                    var_value=type_, prepend='Invalid validation call: ')

    if not valid:
        _report(TypeError, 'must be in {!r}.', types_, var_name=name,
                expr='type({})')
Exemple #16
0
def _check_len(name, var, len_):
    """
    Check the length of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    len_ : int
        The required length.

    """

    if len_ is not None:
        if not isinstance(len_, int):
            _report(TypeError, 'must be {!r}.', int, var_name='len_',
                    var_value=len_, expr='type({})',
                    prepend='Invalid validation call: ')

        if not hasattr(var, '__len__') or len(var) != len_:
            _report(ValueError, 'must be {!r}.', len_, var_name=name,
                    expr='len({})')
Exemple #17
0
def _check_shape(name, dshape, shape):
    """
    Check the shape of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    dshape : list or tuple
        The shape of the variable to be validated.
    shape : list or tuple
        The accepted shape.

    """

    if shape is not None:
        if not isinstance(shape, (list, tuple)):
            _report(TypeError,
                    'must be in {!r}.', (list, tuple),
                    var_name='shape',
                    var_value=shape,
                    expr='type({})',
                    prepend='Invalid validation call: ')

        if len(dshape) != len(shape):
            _report(ValueError,
                    '>>len({}.shape)<<, {!r}, must be {!r}.',
                    (name, len(dshape), len(shape)),
                    prepend='The value(s) of ')

        for i, value in enumerate(shape):
            if not isinstance(value, int):
                _report(TypeError,
                        'must be {!r}.', (int, int),
                        var_name=('shape', i),
                        var_value=value,
                        expr='type({})',
                        prepend='Invalid validation call: ')

            if value > -1 and dshape[i] != value:
                _report(ValueError,
                        '>>{}.shape[{}]<<, {!r}, must be {!r}.',
                        (name, i, dshape[i], value),
                        prepend='The value(s) of')
Exemple #18
0
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 list(var.items()):
                _validate_level(name + [key], value, levels, index + 1)
Exemple #19
0
def _check_keys(name, var, keys_in, has_keys):
    """
    Check the keys of a variable.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    var : None
        The value of the variable to be validated.
    keys_in : set-like
        The allowed keys.
    has_keys : set-like
        The required keys.

    """

    if keys_in is not None:
        if not hasattr(keys_in, '__iter__'):
            _report(TypeError, 'must be iterable.', var_name='keys_in',
                    var_value=keys_in, prepend='Invalid validation call: ')

        for key in var.keys():
            if key not in keys_in:
                _report(KeyError, 'must be in {!r}.', keys_in, var_name=name,
                        expr='{}.keys()')

    if has_keys is not None:
        if not hasattr(has_keys, '__iter__'):
            _report(TypeError, 'must be iterable.', var_name='has_keys',
                    var_value=has_keys, prepend='Invalid validation call: ')

        for key in has_keys:
            if key not in var.keys():
                _report(KeyError, 'must have the key {!r}.', key,
                        var_name=name)
Exemple #20
0
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)
Exemple #21
0
def validate_numeric(name, type_, range_='[-inf;inf]', shape=(),
                     precision=None, ignore_none=False, var=None):
    """
    Validate numeric objects.

    The present function is meant to valdiate the type or class of an object.
    Furthermore, if the object may only take on a connected range of values,
    the object can be validated against this range. Also, the shape of the
    object can be validated. Finally, the precision used to represent the
    object can be validated.

    If the present function is called with `name` set to None, an iterable with
    the value 'numeric' followed by the remaining arguments passed in the call
    is returned. This is useful in combination with the validation function
    `magni.utils.validation.validate_levels`.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    type_ : None
        One or more references to groups of types.
    range_ : None
        The range of accepted values. (the default is '[-inf;inf]', which
        implies that all values are accepted)
    shape : list or tuple
        The accepted shape. (the default is (), which implies that only scalar
        values are accepted)
    precision : None
        One or more precisions.
    ignore_none : bool
        A flag indicating if the variable is allowed to be none. (the default
        is False)
    var : None
        The value of the variable to be validated.

    See Also
    --------
    magni.utils.validation.validate_generic : Validate non-numeric objects.
    magni.utils.validation.validate_levels : Validate contained 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']".

    `type_` is either a single value treated as a list with one value or a
    set-like object containing at least one value. Each value refers to a
    number of data types depending if the string value is 'boolean', 'integer',
    'floating', or 'complex'.

    - 'boolean' tests if the variable is a bool or has the data type
      `numpy.bool8`.
    - 'integer' tests if the variable is an int or has the data type
      `numpy.int8`, `numpy.int16`, `numpy.int32`, or `numpy.int64`.
    - 'floating' tests if the variable is a float or has the data type
      `numpy.float16`, `numpy.float32`, `numpy.float64`, or `numpy.float128`.
    - 'complex' tests if the variable is a complex or has the data type
      `numpy.complex32`, `numpy.complex64`, or `numpy.complex128`.

    `range_` is either a list with two strings or a single string. In the
    latter case, the default value of the argument is used as the second
    string. The first value represents the accepted range of real values
    whereas the second value represents the accepted range of imaginary values.
    Each string consists of the following parts:

    - One of the following delimiters: '[', '(', ']'.
    - A numeric value (or '-inf').
    - A semi-colon.
    - A numeric value (or 'inf').
    - One of the following delimiters: ']', ')', '['.

    `shape` is either None meaning that any shape is accepted or a list of
    integers. In the latter case, the integer -1 may be used to indicate that
    the given axis may have any length.

    `precision` is either an integer treated as a list with one value or a
    set-like object containing at least one integer. Each value refers to an
    accepted number of bits used to store each value of the variable.

    `var` can be used to pass the value of the variable to be validated. This
    is useful either when the variable cannot be looked up by `name` (for
    example, if the variable is a property of the argument of a function) or to
    remove the overhead of looking up the value.

    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 ('numeric', type_, range_, shape, precision, ignore_none)

    if var is None:
        var = _get_var(name)

    if var is None:
        if not isinstance(ignore_none, bool):
            _report(TypeError, 'must be {!r}.', bool, var_name='ignore_none',
                    var_value=ignore_none, expr='type({})',
                    prepend='Invalid validation call: ')

        if ignore_none:
            return
        else:
            _report(ValueError, 'must not be {!r}.', None, var_name=name)

    dtype, bounds, dshape = _examine_var(name, var)

    if isinstance(type_, str) or not hasattr(type_, '__iter__'):
        type_ = (type_,)

    _check_type(name, dtype, type_)
    _check_range(name, bounds, range_)
    _check_shape(name, dshape, shape)
    _check_precision(name, dtype, type_, precision)
Exemple #22
0
def validate_generic(name, type_, value_in=None, len_=None, keys_in=None,
                     has_keys=None, ignore_none=False, var=None):
    """
    Validate non-numeric objects.

    The present function is meant to validate the type or class of an object.
    Furthermore, if the object may only take on a limited number of values, the
    object can be validated against this list. In the case of collections (for
    example lists and tuples) and mappings (for example dictionaries), a
    specific length can be required. Furthermore, in the case of mappings, the
    keys can be validated by requiring and/or only allowing certain keys.

    If the present function is called with `name` set to None, an iterable with
    the value 'generic' followed by the remaining arguments passed in the call
    is returned. This is useful in combination with the validation function
    `magni.utils.validation.validate_levels`.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    type_ : None
        One or more references to groups of types, specific types, and/or
        specific classes.
    value_in : set-like
        The list of values accepted. (the default is None, which implies that
        all values are accepted)
    len_ : int
        The length required. (the default is None, which implies that all
        lengths are accepted)
    keys_in : set-like
        The list of accepted keys. (the default is None, which implies that all
        keys are accepted)
    has_keys : set-like
        The list of required keys. (the default is None, which implies that no
        keys are required)
    ignore_none : bool
        A flag indicating if the variable is allowed to be none. (the default
        is False)
    var : None
        The value of the variable to be validated.

    See Also
    --------
    magni.utils.validation.validate_levels : Validate contained 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']".

    `type_` is either a single value treated as a list with one value or a
    set-like object containing at least one value. Each value is either a
    specific type or class, or it refers to one or more types by having one of
    the string values 'string', 'explicit collection', 'implicict collection',
    'collection', 'mapping', 'function', 'class'.

    - 'string' tests if the variable is a str.
    - 'explicit collection' tests if the variable is a list or tuple.
    - 'implicit collection' tests if the variable is iterable.
    - 'collection' is a combination of the two above.
    - 'mapping' tests if the variable is a dict.
    - 'function' tests if the variable is a function.
    - 'class' tests if the variable is a type.

    `var` can be used to pass the value of the variable to be validated. This
    is useful either when the variable cannot be looked up by `name` (for
    example, if the variable is a property of the argument of a function) or to
    remove the overhead of looking up the value.

    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 ('generic', type_, value_in, len_, keys_in, has_keys,
                ignore_none)

    if var is None:
        var = _get_var(name)

    if var is None:
        if not isinstance(ignore_none, bool):
            _report(TypeError, 'must be {!r}.', bool, var_name='ignore_none',
                    var_value=ignore_none, expr='type({})',
                    prepend='Invalid validation call: ')

        if ignore_none:
            return
        else:
            _report(ValueError, 'must not be {!r}.', None, var_name=name)

    if isinstance(type_, (str, type)) or not hasattr(type_, '__iter__'):
        type_ = (type_,)

    _check_type(name, var, type_)
    _check_value(name, var, value_in)
    _check_len(name, var, len_)
    _check_keys(name, var, keys_in, has_keys)
Exemple #23
0
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)
    elif isinstance(name, str):
        name = [name]
    elif hasattr(name, '__iter__'):
        name = [value for value in 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: ')

    _validate_level(name, _get_var(name), levels)
Exemple #24
0
def validate_numeric(name,
                     type_,
                     range_='[-inf;inf]',
                     shape=(),
                     precision=None,
                     ignore_none=False,
                     var=None):
    """
    Validate numeric objects.

    The present function is meant to valdiate the type or class of an object.
    Furthermore, if the object may only take on a connected range of values,
    the object can be validated against this range. Also, the shape of the
    object can be validated. Finally, the precision used to represent the
    object can be validated.

    If the present function is called with `name` set to None, an iterable with
    the value 'numeric' followed by the remaining arguments passed in the call
    is returned. This is useful in combination with the validation function
    `magni.utils.validation.validate_levels`.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    type_ : None
        One or more references to groups of types.
    range_ : None
        The range of accepted values. (the default is '[-inf;inf]', which
        implies that all values are accepted)
    shape : list or tuple
        The accepted shape. (the default is (), which implies that only scalar
        values are accepted)
    precision : None
        One or more precisions.
    ignore_none : bool
        A flag indicating if the variable is allowed to be none. (the default
        is False)
    var : None
        The value of the variable to be validated.

    See Also
    --------
    magni.utils.validation.validate_generic : Validate non-numeric objects.
    magni.utils.validation.validate_levels : Validate contained 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']".

    `type_` is either a single value treated as a list with one value or a
    set-like object containing at least one value. Each value refers to a
    number of data types depending if the string value is 'boolean', 'integer',
    'floating', or 'complex'.

    - 'boolean' tests if the variable is a bool or has the data type
      `numpy.bool8`.
    - 'integer' tests if the variable is an int or has the data type
      `numpy.int8`, `numpy.int16`, `numpy.int32`, or `numpy.int64`.
    - 'floating' tests if the variable is a float or has the data type
      `numpy.float16`, `numpy.float32`, `numpy.float64`, or `numpy.float128`.
    - 'complex' tests if the variable is a complex or has the data type
      `numpy.complex32`, `numpy.complex64`, or `numpy.complex128`.

    Because `bool` is a subclass of `int`, a `bool` will pass validation as an
    'integer'. This, however, is not the case for `numpy.bool8`.

    `range_` is either a list with two strings or a single string. In the
    latter case, the default value of the argument is used as the second
    string. The first value represents the accepted range of real values
    whereas the second value represents the accepted range of imaginary values.
    Each string consists of the following parts:

    - One of the following delimiters: '[', '(', ']'.
    - A numeric value (or '-inf').
    - A semi-colon.
    - A numeric value (or 'inf').
    - One of the following delimiters: ']', ')', '['.

    `shape` is either None meaning that any shape is accepted or a list of
    integers. In the latter case, the integer -1 may be used to indicate that
    the given axis may have any length.

    `precision` is either an integer treated as a list with one value or a
    list or tuple containing at least one integer. Each value refers to an
    accepted number of bits used to store each value of the variable.

    `var` can be used to pass the value of the variable to be validated. This
    is useful either when the variable cannot be looked up by `name` (for
    example, if the variable is a property of the argument of a function) or to
    remove the overhead of looking up the value.

    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 ('numeric', type_, range_, shape, precision, ignore_none)

    if var is None:
        var = _get_var(name)

    if var is None:
        if not isinstance(ignore_none, bool):
            _report(TypeError,
                    'must be {!r}.',
                    bool,
                    var_name='ignore_none',
                    var_value=ignore_none,
                    expr='type({})',
                    prepend='Invalid validation call: ')

        if ignore_none:
            return
        else:
            _report(ValueError, 'must not be {!r}.', None, var_name=name)

    if not isinstance(var, (_Number, np.generic, np.ndarray, _MatrixBase)):
        _report(TypeError,
                '>>{}<<, {!r}, must be numeric.', (name, var),
                prepend='The value(s) of ')

    dtype, bounds, dshape = _examine_var(name, var)

    if isinstance(type_, str) or not hasattr(type_, '__iter__'):
        type_ = (type_, )

    _check_type(name, dtype, type_)
    _check_range(name, bounds, range_)
    _check_shape(name, dshape, shape)
    _check_precision(name, dtype, type_, precision)
Exemple #25
0
def validate_generic(name, type_, value_in=None, len_=None, keys_in=None,
                     has_keys=None, superclass=None, ignore_none=False,
                     var=None):
    """
    Validate non-numeric objects.

    The present function is meant to validate the type or class of an object.
    Furthermore, if the object may only take on a limited number of values, the
    object can be validated against this list. In the case of collections (for
    example lists and tuples) and mappings (for example dictionaries), a
    specific length can be required. Furthermore, in the case of mappings, the
    keys can be validated by requiring and/or only allowing certain keys.

    If the present function is called with `name` set to None, an iterable with
    the value 'generic' followed by the remaining arguments passed in the call
    is returned. This is useful in combination with the validation function
    `magni.utils.validation.validate_levels`.

    Parameters
    ----------
    name : None
        The name of the variable to be validated.
    type_ : None
        One or more references to groups of types, specific types, and/or
        specific classes.
    value_in : set-like
        The list of values accepted. (the default is None, which implies that
        all values are accepted)
    len_ : int
        The length required. (the default is None, which implies that all
        lengths are accepted)
    keys_in : set-like
        The list of accepted keys. (the default is None, which implies that all
        keys are accepted)
    has_keys : set-like
        The list of required keys. (the default is None, which implies that no
        keys are required)
    superclass : class
        The required superclass. (the default is None, which implies that no
        superclass is required)
    ignore_none : bool
        A flag indicating if the variable is allowed to be none. (the default
        is False)
    var : None
        The value of the variable to be validated.

    See Also
    --------
    magni.utils.validation.validate_levels : Validate contained 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']".

    `type_` is either a single value treated as a list with one value or a
    set-like object containing at least one value. Each value is either a
    specific type or class, or it refers to one or more types by having one of
    the string values 'string', 'explicit collection', 'implicict collection',
    'collection', 'mapping', 'function', 'class'.

    - 'string' tests if the variable is a str.
    - 'explicit collection' tests if the variable is a list or tuple.
    - 'implicit collection' tests if the variable is iterable.
    - 'collection' is a combination of the two above.
    - 'mapping' tests if the variable is a dict.
    - 'function' tests if the variable is a function.
    - 'class' tests if the variable is a type.

    `var` can be used to pass the value of the variable to be validated. This
    is useful either when the variable cannot be looked up by `name` (for
    example, if the variable is a property of the argument of a function) or to
    remove the overhead of looking up the value.

    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 ('generic', type_, value_in, len_, keys_in, has_keys,
                superclass, ignore_none)

    if var is None:
        var = _get_var(name)

    if var is None:
        if not isinstance(ignore_none, bool):
            _report(TypeError, 'must be {!r}.', bool, var_name='ignore_none',
                    var_value=ignore_none, expr='type({})',
                    prepend='Invalid validation call: ')

        if ignore_none:
            return
        else:
            _report(ValueError, 'must not be {!r}.', None, var_name=name)

    if isinstance(type_, (str, type)) or not hasattr(type_, '__iter__'):
        type_ = (type_,)

    _check_type(name, var, type_)
    _check_value(name, var, value_in)
    _check_len(name, var, len_)
    _check_keys(name, var, keys_in, has_keys)
    _check_inheritance(name, var, superclass)