[Python-checkins] bpo-35911: add cell constructor (GH-11771)

Antoine Pitrou webhook-mailer at python.org
Thu Feb 7 14:36:59 EST 2019


https://github.com/python/cpython/commit/df8d2cde63c865446468351f8f648e1c7bd45109
commit: df8d2cde63c865446468351f8f648e1c7bd45109
branch: master
author: Pierre Glaser <pierreglaser at msn.com>
committer: Antoine Pitrou <pitrou at free.fr>
date: 2019-02-07T19:36:48Z
summary:

bpo-35911: add cell constructor (GH-11771)

Add a cell constructor, expose the cell type in the types module.

files:
A Misc/NEWS.d/next/Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst
M Doc/library/types.rst
M Doc/reference/datamodel.rst
M Lib/test/test_funcattrs.py
M Lib/types.py
M Objects/cellobject.c

diff --git a/Doc/library/types.rst b/Doc/library/types.rst
index b19aa0273ef5..07c3a2e7f682 100644
--- a/Doc/library/types.rst
+++ b/Doc/library/types.rst
@@ -136,6 +136,14 @@ Standard names are defined for the following types:
    The type for code objects such as returned by :func:`compile`.
 
 
+.. data:: CellType
+
+   The type for cell objects: such objects are used as containers for
+   a function's free variables.
+
+   .. versionadded:: 3.8
+
+
 .. data:: MethodType
 
    The type of methods of user-defined class instances.
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 83e1d239b34a..9961aee14e06 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -539,7 +539,9 @@ Callable types
       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.
+      code object; see the description of internal types below. The
+      :data:`cell <types.CellType>` type can be accessed in the :mod:`types`
+      module.
 
    Instance methods
       .. index::
diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py
index 35fd657ec0ba..11d68cc75e20 100644
--- a/Lib/test/test_funcattrs.py
+++ b/Lib/test/test_funcattrs.py
@@ -83,6 +83,15 @@ def f(): print(a)
         self.assertEqual(c[0].__class__.__name__, "cell")
         self.cannot_set_attr(f, "__closure__", c, AttributeError)
 
+    def test_cell_new(self):
+        cell_obj = types.CellType(1)
+        self.assertEqual(cell_obj.cell_contents, 1)
+
+        cell_obj = types.CellType()
+        msg = "shouldn't be able to read an empty cell"
+        with self.assertRaises(ValueError, msg=msg):
+            cell_obj.cell_contents
+
     def test_empty_cell(self):
         def f(): print(a)
         try:
diff --git a/Lib/types.py b/Lib/types.py
index ce4652f37189..53b588da7569 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -15,6 +15,13 @@ def _f(): pass
 MappingProxyType = type(type.__dict__)
 SimpleNamespace = type(sys.implementation)
 
+def _cell_factory():
+    a = 1
+    def f():
+        nonlocal a
+    return f.__closure__[0]
+CellType = type(_cell_factory())
+
 def _g():
     yield 1
 GeneratorType = type(_g())
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst b/Misc/NEWS.d/next/Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst
new file mode 100644
index 000000000000..458ccb49fa41
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst	
@@ -0,0 +1,3 @@
+Enable the creation of cell objects by adding a ``cell.__new__`` method, and
+expose the type ``cell`` in ``Lib/types.py`` under the name CellType. Patch by
+Pierre Glaser.
diff --git a/Objects/cellobject.c b/Objects/cellobject.c
index 86bebb9604a5..4e359f889fdc 100644
--- a/Objects/cellobject.c
+++ b/Objects/cellobject.c
@@ -20,6 +20,37 @@ PyCell_New(PyObject *obj)
     return (PyObject *)op;
 }
 
+PyDoc_STRVAR(cell_new_doc,
+"cell([contents])\n"
+"--\n"
+"\n"
+"Create a new cell object.\n"
+"\n"
+"  contents\n"
+"    the contents of the cell. If not specified, the cell will be empty,\n"
+"    and \n further attempts to access its cell_contents attribute will\n"
+"    raise a ValueError.");
+
+
+static PyObject *
+cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+    PyObject *return_value = NULL;
+    PyObject *obj = NULL;
+
+    if (!_PyArg_NoKeywords("cell", kwargs)) {
+        goto exit;
+    }
+    /* min = 0: we allow the cell to be empty */
+    if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
+        goto exit;
+    }
+    return_value = PyCell_New(obj);
+
+exit:
+    return return_value;
+}
+
 PyObject *
 PyCell_Get(PyObject *op)
 {
@@ -146,7 +177,7 @@ PyTypeObject PyCell_Type = {
     0,                                          /* tp_setattro */
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
+    cell_new_doc,                               /* tp_doc */
     (traverseproc)cell_traverse,                /* tp_traverse */
     (inquiry)cell_clear,                        /* tp_clear */
     cell_richcompare,                           /* tp_richcompare */
@@ -156,4 +187,13 @@ PyTypeObject PyCell_Type = {
     0,                                          /* tp_methods */
     0,                                          /* tp_members */
     cell_getsetlist,                            /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    0,                                          /* tp_alloc */
+    (newfunc)cell_new,                          /* tp_new */
+    0,                                          /* tp_free */
 };



More information about the Python-checkins mailing list