This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author alonho
Recipients Alexander.Belopolsky, Christophe Simonis, alonho, anacrolix, belopolsky, eckhardt, ironfroggy, jackdied, jcea, ncoghlan, r.david.murray, rhettinger, ssadler
Date 2013-10-27.12:17:03
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1382876223.6.0.449322219197.issue4331@psf.upfronthosting.co.za>
In-reply-to
Content
I think the following test demonstrates the API we're looking for.
1. Am I missing any functionality?
2. How does partialmethod relate to @absolutemethod?

from functools import partial

class partialmethod(object):

    def __init__(self, func, *args, **keywords):
        # func could be a descriptor like classmethod which isn't callable,
        # so we can't inherit from partial (it verifies func is callable)
        if isinstance(func, partialmethod):
            # flattening is mandatory in order to place cls/self before all other arguments
            # it's also more efficient since only one function will be called
            self.func = func.func
            self.args = func.args + args
            self.keywords = {}
            self.keywords.update(func.keywords)
            self.keywords.update(keywords)
        else:
            self.func = func
            self.args = args
            self.keywords = keywords
    
    def _make_unbound_method(self):
        def _method(*args, **keywords):
            keywords.update(self.keywords)
            cls_or_self, *rest = args
            call_args = (cls_or_self,) + self.args + tuple(rest)
            return self.func(*call_args, **keywords)
        return _method

    def __get__(self, obj, cls):
        get = getattr(self.func, "__get__", None)
        if get is None:
            if obj is None:
                return self._make_unbound_method()
            return partial(self._make_unbound_method(), obj) # returns a bound method
        else:
            callable = get(obj, cls)
            if callable is self.func:
                return self._make_unbound_method()
        return partial(callable, *self.args, **self.keywords)

class A(object):
    def add(self, x, y):
        return self, x + y

    add10 = partialmethod(add, 10)
    add10class = partialmethod(classmethod(add), 10)
    add10static = partialmethod(staticmethod(add), 'self', 10)

    return15 = partialmethod(add10, 5) # nested partialmethod
    
    add2partial = partial(add, x=2)
    return12 = partialmethod(add2partial, y=10) # partialmethod over partial
    
def test():
    cls = A
    instance = cls()

    assert instance.add10class(5) == (cls, 15)
    assert cls.add10class(5) == (cls, 15)

    assert instance.add10static(5) == ('self', 15)
    assert cls.add10static(5) == ('self', 15)
    
    assert instance.add10(5) == (instance, 15)
    assert cls.add10(instance, 5) == (instance, 15)
    
    assert instance.return15() == (instance, 15)
    assert cls.return15(instance) == (instance, 15)

    assert instance.return12() == (instance, 12)
    assert cls.return12(instance) == (instance, 12)

test()
History
Date User Action Args
2013-10-27 12:17:03alonhosetrecipients: + alonho, rhettinger, jcea, ncoghlan, belopolsky, ironfroggy, jackdied, Christophe Simonis, ssadler, eckhardt, r.david.murray, Alexander.Belopolsky, anacrolix
2013-10-27 12:17:03alonhosetmessageid: <1382876223.6.0.449322219197.issue4331@psf.upfronthosting.co.za>
2013-10-27 12:17:03alonholinkissue4331 messages
2013-10-27 12:17:03alonhocreate