Author: Armin Rigo <[email protected]>
Branch:
Changeset: r77239:0c9627141b68
Date: 2015-05-09 10:01 +0200
http://bitbucket.org/pypy/pypy/changeset/0c9627141b68/
Log: Issue #2043 fix
Also fixes an issue with partial(..., self=...)
diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py
--- a/lib_pypy/_functools.py
+++ b/lib_pypy/_functools.py
@@ -8,16 +8,16 @@
partial(func, *args, **keywords) - new function with partial application
of the given arguments and keywords.
"""
-
- def __init__(self, *args, **keywords):
- if not args:
- raise TypeError('__init__() takes at least 2 arguments (1 given)')
- func, args = args[0], args[1:]
+ def __init__(*args, **keywords):
+ if len(args) < 2:
+ raise TypeError('__init__() takes at least 2 arguments (%d given)'
+ % len(args))
+ self, func, args = args[0], args[1], args[2:]
if not callable(func):
raise TypeError("the first argument must be callable")
self._func = func
self._args = args
- self._keywords = keywords or None
+ self._keywords = keywords
def __delattr__(self, key):
if key == '__dict__':
@@ -37,19 +37,22 @@
return self._keywords
def __call__(self, *fargs, **fkeywords):
- if self.keywords is not None:
- fkeywords = dict(self.keywords, **fkeywords)
- return self.func(*(self.args + fargs), **fkeywords)
+ if self._keywords:
+ fkeywords = dict(self._keywords, **fkeywords)
+ return self._func(*(self._args + fargs), **fkeywords)
def __reduce__(self):
d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in
('_func', '_args', '_keywords'))
if len(d) == 0:
d = None
- return (type(self), (self.func,),
- (self.func, self.args, self.keywords, d))
+ return (type(self), (self._func,),
+ (self._func, self._args, self._keywords, d))
def __setstate__(self, state):
- self._func, self._args, self._keywords, d = state
+ func, args, keywords, d = state
if d is not None:
self.__dict__.update(d)
+ self._func = func
+ self._args = args
+ self._keywords = keywords
diff --git a/pypy/module/test_lib_pypy/test_functools.py
b/pypy/module/test_lib_pypy/test_functools.py
--- a/pypy/module/test_lib_pypy/test_functools.py
+++ b/pypy/module/test_lib_pypy/test_functools.py
@@ -6,8 +6,10 @@
def test_partial_reduce():
partial = _functools.partial(test_partial_reduce)
state = partial.__reduce__()
+ d = state[2][2]
assert state == (type(partial), (test_partial_reduce,),
- (test_partial_reduce, (), None, None))
+ (test_partial_reduce, (), d, None))
+ assert d is None or d == {} # both are acceptable
def test_partial_setstate():
partial = _functools.partial(object)
@@ -30,3 +32,15 @@
assert str(exc.value) == "a partial object's dictionary may not be deleted"
with pytest.raises(AttributeError):
del partial.zzz
+
+def test_self_keyword():
+ partial = _functools.partial(dict, self=42)
+ assert partial(other=43) == {'self': 42, 'other': 43}
+
+def test_no_keywords():
+ kw1 = _functools.partial(dict).keywords
+ kw2 = _functools.partial(dict, **{}).keywords
+ # CPython gives different results for these two cases, which is not
+ # possible to emulate in pure Python; see issue #2043
+ assert kw1 == {} or kw1 is None
+ assert kw2 == {}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit