[pypy-commit] pypy stdlib-2.7.8: Made functools.partial objects immutable

alex_gaynor noreply at buildbot.pypy.org
Sat Aug 23 17:14:36 CEST 2014


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: stdlib-2.7.8
Changeset: r72997:e23159188497
Date: 2014-08-23 08:12 -0700
http://bitbucket.org/pypy/pypy/changeset/e23159188497/

Log:	Made functools.partial objects immutable

diff --git a/lib-python/2.7/test/test_functools.py b/lib-python/2.7/test/test_functools.py
--- a/lib-python/2.7/test/test_functools.py
+++ b/lib-python/2.7/test/test_functools.py
@@ -43,9 +43,9 @@
         self.assertEqual(p.args, (1, 2))
         self.assertEqual(p.keywords, dict(a=10, b=20))
         # attributes should not be writable
-        self.assertRaises(TypeError, setattr, p, 'func', map)
-        self.assertRaises(TypeError, setattr, p, 'args', (1, 2))
-        self.assertRaises(TypeError, setattr, p, 'keywords', dict(a=1, b=2))
+        self.assertRaises((TypeError, AttributeError), setattr, p, 'func', map)
+        self.assertRaises((TypeError, AttributeError), setattr, p, 'args', (1, 2))
+        self.assertRaises((TypeError, AttributeError), setattr, p, 'keywords', dict(a=1, b=2))
 
         p = self.thetype(hex)
         try:
diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py
--- a/lib_pypy/_functools.py
+++ b/lib_pypy/_functools.py
@@ -12,9 +12,21 @@
     def __init__(self, func, *args, **keywords):
         if not callable(func):
             raise TypeError("the first argument must be callable")
-        self.func = func
-        self.args = args
-        self.keywords = keywords or None
+        self._func = func
+        self._args = args
+        self._keywords = keywords or None
+
+    @property
+    def func(self):
+        return self._func
+
+    @property
+    def args(self):
+        return self._args
+
+    @property
+    def keywords(self):
+        return self._keywords
 
     def __call__(self, *fargs, **fkeywords):
         if self.keywords is not None:
@@ -23,13 +35,13 @@
 
     def __reduce__(self):
         d = dict((k, v) for k, v in self.__dict__.iteritems() if k not in
-                ('func', 'args', 'keywords'))
+                ('_func', '_args', '_keywords'))
         if len(d) == 0:
             d = None
         return (type(self), (self.func,),
                 (self.func, self.args, self.keywords, d))
 
     def __setstate__(self, state):
-        self.func, self.args, self.keywords, d = state
+        self._func, self._args, self._keywords, d = state
         if d is not None:
             self.__dict__.update(d)
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
@@ -1,5 +1,8 @@
+import pytest
+
 from lib_pypy import _functools
 
+
 def test_partial_reduce():
     partial = _functools.partial(test_partial_reduce)
     state = partial.__reduce__()
@@ -17,3 +20,8 @@
     string = pickle.dumps(partial1)
     partial2 = pickle.loads(string)
     assert partial1.func == partial2.func
+
+def test_immutable_attributes():
+    partial = _functools.partial(object)
+    with pytest.raises((TypeError, AttributeError)):
+        partial.func = sum


More information about the pypy-commit mailing list