Skip to content

Commit

Permalink
Merge pull request #220 from eriknw/curry_classmethods
Browse files Browse the repository at this point in the history
`curry` can work on class methods by using the `__get__` descriptor protocol
  • Loading branch information
eriknw committed Jan 12, 2015
2 parents 0ca38c8 + 546f47a commit 785edcf
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 1 deletion.
5 changes: 5 additions & 0 deletions toolz/functoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ def __call__(self, *args, **kwargs):

return curry(self._partial, *args, **kwargs)

def __get__(self, instance, owner):
if instance is None:
return self
return curry(self, instance)

# pickle protocol because functools.partial objects can't be pickled
def __getstate__(self):
# dictoolz.keyfilter, I miss you!
Expand Down
89 changes: 88 additions & 1 deletion toolz/tests/test_functoolz.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from operator import add, mul, itemgetter
from toolz.utils import raises
from functools import partial
from toolz.compatibility import reduce
from toolz.compatibility import reduce, PY3


def iseven(x):
Expand Down Expand Up @@ -313,6 +313,93 @@ def f(x, y=0):
assert cf(y=1)(y=2)(y=3)(1) == f(1, 3)


def test_curry_on_classmethods():
class A(object):
BASE = 10

def __init__(self, base):
self.BASE = base

@curry
def addmethod(self, x, y):
return self.BASE + x + y

@classmethod
@curry
def addclass(cls, x, y):
return cls.BASE + x + y

@staticmethod
@curry
def addstatic(x, y):
return x + y

a = A(100)
assert a.addmethod(3, 4) == 107
assert a.addmethod(3)(4) == 107
assert A.addmethod(a, 3, 4) == 107
assert A.addmethod(a)(3)(4) == 107

assert a.addclass(3, 4) == 17
assert a.addclass(3)(4) == 17
assert A.addclass(3, 4) == 17
assert A.addclass(3)(4) == 17

assert a.addstatic(3, 4) == 7
assert a.addstatic(3)(4) == 7
assert A.addstatic(3, 4) == 7
assert A.addstatic(3)(4) == 7

# we want this to be of type curry
assert isinstance(a.addmethod, curry)
assert isinstance(A.addmethod, curry)


def test_memoize_on_classmethods():
class A(object):
BASE = 10
HASH = 10

def __init__(self, base):
self.BASE = base

@memoize
def addmethod(self, x, y):
return self.BASE + x + y

@classmethod
@memoize
def addclass(cls, x, y):
return cls.BASE + x + y

@staticmethod
@memoize
def addstatic(x, y):
return x + y

def __hash__(self):
return self.HASH

a = A(100)
assert a.addmethod(3, 4) == 107
assert A.addmethod(a, 3, 4) == 107

a.BASE = 200
assert a.addmethod(3, 4) == 107
a.HASH = 200
assert a.addmethod(3, 4) == 207

assert a.addclass(3, 4) == 17
assert A.addclass(3, 4) == 17
A.BASE = 20
assert A.addclass(3, 4) == 17
A.HASH = 20 # hashing of class is handled by metaclass
assert A.addclass(3, 4) == 17 # hence, != 27

assert a.addstatic(3, 4) == 7
assert A.addstatic(3, 4) == 7


def test__num_required_args():
assert _num_required_args(map) != 0
assert _num_required_args(lambda x: x) == 1
Expand Down

0 comments on commit 785edcf

Please sign in to comment.