예제 #1
0
    def _validate_and_split_len(self, key):
        """Validate all key lengths greater than one, N.

        Valid input is an arbitrarily deep series of iterables that culminate
        in N length tuples, this includes an iterable depth of zero. The N
        length tuples can contain for each member either a type string or an
        iterable of type strings.
        """
        if isinstance(key, tuple) and len(key) == self._len_keys:
            fst, snd = key
            if any([
                    not is_good_iterable(v) and not isinstance(v, str)
                    for v in key
            ]):
                raise KeyError("The key {} is not valid.".format(key))
            key = list(key)
            for ind in range(len(key)):
                if isinstance(key[ind], str):
                    key[ind] = [key[ind]]
            return list(product(*key))
        elif _is_iterable(key):
            keys = []
            for k in key:
                keys.extend(self._validate_and_split_len(k))
            return keys
        else:
            raise KeyError("The key {} is not valid.".format(key))
예제 #2
0
 def __init__(self, sequence, default):
     if _is_iterable(default):
         dft_iter = cycle(default)
     else:
         dft_iter = repeat(default)
     self.default = tuple(
         [_to_default(item, dft) for item, dft in zip(sequence, dft_iter)])
예제 #3
0
    def validate_and_split_len(self, key):
        """Validate all key lengths greater than one, N.

        Valid input is an arbitrarily deep series of iterables that culminate
        in N length tuples, this includes an iterable depth of zero.  The N
        length tuples can contain for each member either a type string or an
        iterable of type strings.
        """
        if isinstance(key, tuple) and len(key) == self.len_key:
            if any([
                    not _is_good_iterable(v) and not isinstance(v, str)
                    for v in key
            ]):
                raise KeyError("The key {} is not valid.".format(key))
            # convert str to single item list for proper enumeration using
            # product
            key_types_list = [[v] if isinstance(v, str) else v for v in key]
            return list(product(*key_types_list))
        elif _is_iterable(key):
            keys = []
            for k in key:
                keys.extend(self.validate_and_split_len(k))
            return keys
        else:
            raise KeyError("The key {} is not valid.".format(key))
예제 #4
0
def _to_default(value, defaults=_NoDefault):
    if isinstance(value, tuple):
        if defaults is _NoDefault or _is_iterable(defaults):
            return _SmartDefaultFixedLengthSequence(value, defaults)
        else:
            return defaults
    if _is_iterable(value):
        if defaults is _NoDefault or _is_iterable(defaults):
            return _SmartDefaultSequence(value, defaults)
        else:
            return defaults
    elif isinstance(value, Mapping):
        if defaults is _NoDefault or isinstance(defaults, Mapping):
            return _SmartDefaultMapping(value, defaults)
        else:
            return defaults
    elif isclass(value) or callable(value):
        return RequiredArg if defaults is _NoDefault else defaults
    else:
        return value if defaults is _NoDefault else defaults
예제 #5
0
 def __call__(self, sequence):
     """Called when the value is set."""
     if not _is_iterable(sequence):
         raise TypeConversionError(
             "Expected a sequence like instance. Received {} of type {}."
             "".format(sequence, type(sequence)))
     else:
         new_sequence = []
         try:
             for i, (v, c) in enumerate(zip(sequence, self)):
                 new_sequence.append(c(v))
         except (TypeConversionError) as err:
             raise TypeConversionError("In list item number {}: {}"
                                       "".format(i, str(err)))
         return new_sequence
예제 #6
0
    def _validate_and_split_len_one(self, key):
        """Validate single type keys.

        Accepted input is a type string, and arbitrarily nested interators that
        culminate in str types.
        """
        if isinstance(key, str):
            return [key]
        elif _is_iterable(key):
            keys = []
            for k in key:
                keys.extend(self._validate_and_split_len_one(k))
            return keys
        else:
            raise KeyError("The key {} is not valid.".format(key))
예제 #7
0
 def _validate(self, sequence):
     """Called when the value is set."""
     if not _is_iterable(sequence):
         raise TypeConversionError(
             f"Expected a sequence like instance. Received {sequence} of "
             f"type {type(sequence)}.")
     else:
         new_sequence = []
         try:
             for i, v in enumerate(sequence):
                 new_sequence.append(self.converter(v))
         except (ValueError, TypeError) as err:
             raise TypeConversionError(
                 f"In list item number {i}: {str(err)}") from err
         return new_sequence
예제 #8
0
 def __call__(self, sequence):
     """Called when the value is set."""
     if not _is_iterable(sequence):
         raise TypeConversionError(
             "Expected a tuple like object. Received {} of type {}."
             "".format(sequence, type(sequence)))
     elif len(sequence) != len(self.converter):
         raise TypeConversionError(
             "Expected exactly {} items. Received {}.".format(
                 len(self.converter), len(sequence)))
     else:
         new_sequence = []
         try:
             for i, (v, c) in enumerate(zip(sequence, self)):
                 new_sequence.append(c(v))
         except (TypeConversionError) as err:
             raise TypeConversionError("In tuple item number {}: {}"
                                       "".format(i, str(err)))
         return tuple(new_sequence)
예제 #9
0
 def _validate(self, sequence):
     """Called when the value is set."""
     if not _is_iterable(sequence):
         raise TypeConversionError(
             f"Expected a tuple like object. Received {sequence} of type "
             f"{type(sequence)}.")
     elif len(sequence) != len(self.converter):
         raise TypeConversionError(
             f"Expected exactly {len(self.converter)} items. Received "
             f"{len(sequence)}.")
     else:
         new_sequence = []
         try:
             for i, (v, c) in enumerate(zip(sequence, self)):
                 new_sequence.append(c(v))
         except (ValueError, TypeError) as err:
             raise TypeConversionError(
                 f"In tuple item number {i}: {str(err)}") from err
         return tuple(new_sequence)
예제 #10
0
def to_type_converter(value):
    """The function to use for creating a structure of `TypeConverter` objects.

    This is the function to use when defining validation not any of the
    `TypeConverter` subclasses.

    .. code-block:: python

        # list take a list of tuples of 3 floats each
        validation = to_type_converter(
            {'str': str, 'list': [(float, float, float)]})
    """
    if isinstance(value, tuple):
        return TypeConverterFixedLengthSequence(value)
    if _is_iterable(value):
        return TypeConverterSequence(value)
    elif isinstance(value, Mapping):
        return TypeConverterMapping(value)
    else:
        return TypeConverterValue(value)
예제 #11
0
def is_good_iterable(obj):
    """Returns True if object is iterable with respect to types."""
    return _is_iterable(obj) and has_str_elems(obj)