Exemple #1
0
def attr_func(*attrs, **kwargs):
    """Creates an "attribute function" for given attribute name(s).

    Resulting function will retrieve attributes with given names, in order,
    from the object that has been passed to it.
    For example, ``attr_func('a', 'b')(foo)`` yields the same as ``foo.a.b``

    :param attrs: Attribute names
    :param default: Optional keyword argument specifying default value
                    that will be returned when some attribute is not present

    :return: Unary attribute function
    """
    ensure_argcount(attrs, min_=1)
    ensure_keyword_args(kwargs, optional=('default',))

    # preprocess argument list:
    # * allow dots in arguments, interpreting them as multiple attributes,
    #   e.g. ``attr_func('a.b')`` as ``attr_func('a', 'b')``
    # * make sure the attribute names are valid Python identifiers
    attrs = map(ensure_string, attrs)
    attrs = flatten(attr.split('.') if '.' in attr else [attr]
                    for attr in attrs)
    for attr in attrs:
        if not is_identifier(attr):
            raise ValueError("'%s' is not a valid attribute name", attr)

    if 'default' in kwargs:
        default = kwargs['default']
        if len(attrs) == 1:
            getattrs = lambda obj: getattr(obj, attrs[0], default)
        else:
            def getattrs(obj):
                for attr in attrs:
                    try:
                        obj = getattr(obj, attr)
                    except AttributeError:
                        return default
                return obj
    else:
        if len(attrs) == 1:
            getattrs = operator.attrgetter(attrs[0])
        else:
            def getattrs(obj):
                for attr in attrs:
                    obj = getattr(obj, attr)
                return obj

    return getattrs
Exemple #2
0
def key_func(*keys, **kwargs):
    """Creates a "key function" based on given keys.

    Resulting function will perform lookup using specified keys, in order,
    on the object passed to it as an argument.
    For example, ``key_func('a', 'b')(foo)`` is equivalent to ``foo['a']['b']``.

    :param keys: Lookup keys
    :param default: Optional keyword argument specifying default value
                    that will be returned when some lookup key is not present

    :return: Unary key function
    """
    ensure_argcount(keys, min_=1)
    ensure_keyword_args(kwargs, optional=('default',))

    keys = list(map(ensure_string, keys))

    if 'default' in kwargs:
        default = kwargs['default']
        def getitems(obj):
            for key in keys:
                try:
                    obj = obj[key]
                except KeyError:
                    return default
            return obj
    else:
        if len(keys) == 1:
            getitems = operator.itemgetter(keys[0])
        else:
            def getitems(obj):
                for key in keys:
                    obj = obj[key]
                return obj

    return getitems
Exemple #3
0
 def test_args__none(self):
     with self.assertRaises(TypeError):
         __unit__.ensure_argcount(None, min_=1, max_=1)
Exemple #4
0
 def test_invalid_limits(self):
     with self.assertRaises(ValueError) as r:
         __unit__.ensure_argcount(self.FEW_ARGS, min_=2, max_=1)
     self.assertIn("greater", str(r.exception))
Exemple #5
0
 def test_no_limits(self):
     with self.assertRaises(ValueError):
         __unit__.ensure_argcount(self.FEW_ARGS)
Exemple #6
0
 def test_args__exact(self):
     __unit__.ensure_argcount(self.FEW_ARGS, min_=self.FEW, max_=self.FEW)
     __unit__.ensure_argcount(self.MANY_ARGS,
                              min_=self.MANY,
                              max_=self.MANY)
Exemple #7
0
 def test_args__exactly_max(self):
     __unit__.ensure_argcount(self.MANY_ARGS,
                              min_=self.LESS_THAN_MANY,
                              max_=self.MANY)
Exemple #8
0
 def test_args__exactly_min(self):
     __unit__.ensure_argcount(self.FEW_ARGS,
                              min_=self.FEW,
                              max_=self.MORE_THAN_FEW)
Exemple #9
0
 def test_args__exact(self):
     __unit__.ensure_argcount(self.FEW_ARGS, min_=self.FEW, max_=self.FEW)
     __unit__.ensure_argcount(self.MANY_ARGS, min_=self.MANY, max_=self.MANY)
Exemple #10
0
 def test_args__more_than_max(self):
     with self.assertRaises(TypeError) as r:
         __unit__.ensure_argcount(self.MANY_ARGS, max_=self.LESS_THAN_MANY)
     self.assertIn("expected at most", str(r.exception))
Exemple #11
0
 def test_args__less_than_min(self):
     with self.assertRaises(TypeError) as r:
         __unit__.ensure_argcount(self.FEW_ARGS, min_=self.MORE_THAN_FEW)
     self.assertIn("expected at least", str(r.exception))
Exemple #12
0
 def test_args__empty(self):
     __unit__.ensure_argcount([], min_=0, max_=0)
     __unit__.ensure_argcount([], min_=0, max_=self.MANY)
     with self.assertRaises(TypeError):
         __unit__.ensure_argcount([], min_=self.FEW)
Exemple #13
0
 def test_args__some_object(self):
     with self.assertRaises(TypeError):
         __unit__.ensure_argcount(object(), min_=1, max_=1)
Exemple #14
0
 def test_args__none(self):
     with self.assertRaises(TypeError):
         __unit__.ensure_argcount(None, min_=1, max_=1)
Exemple #15
0
 def test_invalid_limits(self):
     with self.assertRaises(ValueError) as r:
         __unit__.ensure_argcount(self.FEW_ARGS, min_=2, max_=1)
     self.assertIn("greater", str(r.exception))
Exemple #16
0
 def test_no_limits(self):
     with self.assertRaises(ValueError):
         __unit__.ensure_argcount(self.FEW_ARGS)
Exemple #17
0
 def test_args__exactly_min(self):
     __unit__.ensure_argcount(self.FEW_ARGS,
                              min_=self.FEW, max_=self.MORE_THAN_FEW)
Exemple #18
0
 def test_args__exactly_max(self):
     __unit__.ensure_argcount(self.MANY_ARGS,
                              min_=self.LESS_THAN_MANY, max_=self.MANY)