]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-30486: Allow setting cell value (#1840)
authorLisa Roach <lisaroach14@gmail.com>
Thu, 8 Jun 2017 11:43:26 +0000 (04:43 -0700)
committerSerhiy Storchaka <storchaka@gmail.com>
Thu, 8 Jun 2017 11:43:26 +0000 (14:43 +0300)
The cell_contents attribute of the cell object is now writable.

Doc/reference/datamodel.rst
Lib/test/test_funcattrs.py
Misc/NEWS
Objects/cellobject.c

index 9708688c5ce1a52792aa6a4d14ed0ea3621a2faa..24a2618b01e61be18f048a935c1e690073247279 100644 (file)
@@ -510,6 +510,9 @@ Callable types
       | :attr:`__closure__`     | ``None`` or a tuple of cells  | Read-only |
       |                         | that contain bindings for the |           |
       |                         | function's free variables.    |           |
+      |                         | See below for information on  |           |
+      |                         | the ``cell_contents``         |           |
+      |                         | attribute.                    |           |
       +-------------------------+-------------------------------+-----------+
       | :attr:`__annotations__` | A dict containing annotations | Writable  |
       |                         | of parameters.  The keys of   |           |
@@ -530,6 +533,9 @@ Callable types
       implementation only supports function attributes on user-defined functions.
       Function attributes on built-in functions may be supported in the future.*
 
+      A cell object has the attribute ``cell_contents``. This can be used to get
+      the value of the cell, as well as set the value.
+
       Additional information about a function's definition can be retrieved from its
       code object; see the description of internal types below.
 
index 8f481bb64e18e60207c919e02ed80e99312dc576..35fd657ec0ba56721ddafd72f5f7c2ff2a8128f3 100644 (file)
@@ -93,6 +93,26 @@ class FunctionPropertiesTest(FuncAttrsTest):
             self.fail("shouldn't be able to read an empty cell")
         a = 12
 
+    def test_set_cell(self):
+        a = 12
+        def f(): return a
+        c = f.__closure__
+        c[0].cell_contents = 9
+        self.assertEqual(c[0].cell_contents, 9)
+        self.assertEqual(f(), 9)
+        self.assertEqual(a, 9)
+        del c[0].cell_contents
+        try:
+            c[0].cell_contents
+        except ValueError:
+            pass
+        else:
+            self.fail("shouldn't be able to read an empty cell")
+        with self.assertRaises(NameError):
+            f()
+        with self.assertRaises(UnboundLocalError):
+            print(a)
+
     def test___name__(self):
         self.assertEqual(self.b.__name__, 'b')
         self.b.__name__ = 'c'
index 0bc33bb2345d1f17043e4f3e39a2f37ef47909d8..29c0005638d6c3babc7a44561c712b1e1993afac 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,11 @@ What's New in Python 3.7.0 alpha 1?
 Core and Builtins
 -----------------
 
+- bpo-30486: Allows setting cell values for __closure__. Patch by Lisa Roach.
+
+- bpo-30537: itertools.islice now accepts integer-like objects (having
+  an __index__ method) as start, stop, and slice arguments
+
 - bpo-25324: Tokens needed for parsing in Python moved to C. ``COMMENT``,
   ``NL`` and ``ENCODING``. This way the tokens and tok_names in the token
   module don't get changed when you import the tokenize module.
@@ -128,9 +133,6 @@ Core and Builtins
 
 - bpo-29546: Improve from-import error message with location
 
-- bpo-30537: itertools.islice now accepts integer-like objects (having
-  an __index__ method) as start, stop, and slice arguments
-
 - Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0].
 
 - Issue #29337: Fixed possible BytesWarning when compare the code objects.
index 9f4eddb846835c3b32b76622cb78e63076e0115e..6af93b0030815ec682da00d705fad58ae070faab 100644 (file)
@@ -140,8 +140,17 @@ cell_get_contents(PyCellObject *op, void *closure)
     return op->ob_ref;
 }
 
+int
+cell_set_contents(PyCellObject *op, PyObject *obj)
+{
+    Py_XINCREF(obj);
+    Py_XSETREF(op->ob_ref, obj);
+    return 0;
+}
+
 static PyGetSetDef cell_getsetlist[] = {
-    {"cell_contents", (getter)cell_get_contents, NULL},
+    {"cell_contents", (getter)cell_get_contents, 
+                      (setter)cell_set_contents, NULL},
     {NULL} /* sentinel */
 };