root/masterdriverz/snakeoil/snakeoil/currying.py @ ferringb%2540gmail.com-20070429202721-8mqijyr56t6ntz7w

Revision ferringb%2540gmail.com-20070429202721-8mqijyr56t6ntz7w, 3.6 kB (checked in by Brian Harring <ferringb@…>, 21 months ago)

set of changes; move _functoolmodules to _compatibility, pull in py2.5's any/all, slave compatibility to that, tweak test_compatibility a bit so it's slightly saner in terms of not doing repeated/wasteful tests

Line 
1# Copyright: 2005 Brian Harring <ferringb@gmail.com>
2# License: GPL2
3
4"""
5Function currying, generating a functor with a set of args/defaults pre bound.
6
7L{pre_curry} and L{post_curry} return "normal" python functions.
8L{partial} returns a callable object. The difference between
9L{pre_curry} and L{partial} is this::
10
11    >>> def func(arg=None, self=None):
12    ...     return arg, self
13    >>> curry = pre_curry(func, True)
14    >>> part = partial(func, True)
15    >>> class Test(object):
16    ...     curry = pre_curry(func, True)
17    ...     part = partial(func, True)
18    ...     def __repr__(self):
19    ...         return '<Test object>'
20    >>> curry()
21    (True, None)
22    >>> Test().curry()
23    (True, <Test object>)
24    >>> part()
25    (True, None)
26    >>> Test().part()
27    (True, None)
28
29If your curried function is not used as a class attribute the results
30should be identical. Because L{partial} has an implementation in c
31while L{pre_curry} is python you should use L{partial} if possible.
32"""
33
34from operator import attrgetter
35
36__all__ = ("pre_curry", "partial", "post_curry", "pretty_docs",
37    "alias_class_method")
38
39def pre_curry(func, *args, **kwargs):
40    """passed in args are prefixed, with further args appended"""
41
42    if not kwargs:
43        def callit(*moreargs, **morekwargs):
44            return func(*(args + moreargs), **morekwargs)
45    elif not args:
46        def callit(*moreargs, **morekwargs):
47            kw = kwargs.copy()
48            kw.update(morekwargs)
49            return func(*moreargs, **kw)
50    else:
51        def callit(*moreargs, **morekwargs):
52            kw = kwargs.copy()
53            kw.update(morekwargs)
54            return func(*(args+moreargs), **kw)
55
56    callit.func = func
57    return callit
58
59
60class native_partial(object):
61
62    """Like pre_curry, but does not get turned into an instance method."""
63
64    def __init__(self, func, *args, **kwargs):
65        self.func = func
66        self.args = args
67        self.kwargs = kwargs
68
69    def __call__(self, *moreargs, **morekwargs):
70        kw = self.kwargs.copy()
71        kw.update(morekwargs)
72        return self.func(*(self.args + moreargs), **kw)
73
74# Unused import, unable to import
75# pylint: disable-msg=W0611,F0401
76try:
77    from functools import partial
78except ImportError:
79    try:
80        from snakeoil._compatibility import partial
81    except ImportError:
82        partial = native_partial
83
84
85def post_curry(func, *args, **kwargs):
86    """passed in args are appended to any further args supplied"""
87
88    if not kwargs:
89        def callit(*moreargs, **morekwargs):
90            return func(*(moreargs+args), **morekwargs)
91    elif not args:
92        def callit(*moreargs, **morekwargs):
93            kw = morekwargs.copy()
94            kw.update(kwargs)
95            return func(*moreargs, **kw)
96    else:
97        def callit(*moreargs, **morekwargs):
98            kw = morekwargs.copy()
99            kw.update(kwargs)
100            return func(*(moreargs+args), **kw)
101
102    callit.func = func
103    return callit
104
105def pretty_docs(wrapped, extradocs=None):
106    wrapped.__module__ = wrapped.func.__module__
107    doc = wrapped.func.__doc__
108    if extradocs is None:
109        wrapped.__doc__ = doc
110    else:
111        wrapped.__doc__ = extradocs
112    return wrapped
113
114
115def alias_class_method(attr):
116    """at runtime, redirect to another method
117
118    attr is the desired attr name to lookup, and supply all later passed in
119    args/kws to
120
121    Useful for when setting has_key to __contains__ for example, and
122    __contains__ may be overriden.
123    """
124    grab_attr = attrgetter(attr)
125
126    def _asecond_level_call(self, *a, **kw):
127        return grab_attr(self)(*a, **kw)
128
129    return _asecond_level_call
Note: See TracBrowser for help on using the browser.