From a17c56c8b191a89278912094d1baa8dae4d4f295 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Tue, 5 Feb 2019 16:02:49 +0100 Subject: [PATCH 1/7] add a cell constructor, expose cell in Lib/types --- Lib/types.py | 7 +++++++ Objects/cellobject.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Lib/types.py b/Lib/types.py index ce4652f37189763..53b588da75696bf 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/Objects/cellobject.c b/Objects/cellobject.c index 86bebb9604a579b..9a232ff76bb5591 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -20,6 +20,25 @@ PyCell_New(PyObject *obj) return (PyObject *)op; } +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) { @@ -156,4 +175,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 */ }; From 2f26429c4eeb37ba93ff1b6a91ee545ae742e6af Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 6 Feb 2019 17:27:13 +0100 Subject: [PATCH 2/7] TST add test for cell construction --- Lib/test/test_funcattrs.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index 35fd657ec0ba567..11d68cc75e20899 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: From 3954496121dc40734cc87453ec713f8a1e7a70b4 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 6 Feb 2019 17:27:31 +0100 Subject: [PATCH 3/7] DOC docs for cell type and in the Types section --- Doc/library/types.rst | 5 +++++ Objects/cellobject.c | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Doc/library/types.rst b/Doc/library/types.rst index b19aa0273ef52cd..a231fc860cc969d 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -135,6 +135,11 @@ 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. + .. data:: MethodType diff --git a/Objects/cellobject.c b/Objects/cellobject.c index 9a232ff76bb5591..efd22970f6a41d1 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -20,6 +20,18 @@ 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 attemps to access its cell_contents attribute will\n" +" raise a ValueError."); + + static PyObject * cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { @@ -165,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 */ From d6e0b5c6517e4841a78957222e39a77d04391f89 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 6 Feb 2019 17:55:33 +0100 Subject: [PATCH 4/7] DOC add a News section --- .../Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-02-06-17-50-59.bpo-35911.oiWE8.rst 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 000000000000000..458ccb49fa4121e --- /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. From 06d285c422eed3d3938eabb12a09b0fa75b76d55 Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Wed, 6 Feb 2019 17:55:50 +0100 Subject: [PATCH 5/7] DOC .. versionadded directive --- Doc/library/types.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/types.rst b/Doc/library/types.rst index a231fc860cc969d..3b3455e54b3cfb3 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -140,6 +140,7 @@ Standard names are defined for the following types: The type for cell objects: such objects are used as containers for a function's free variables. + .. versionadded:: 3.8 .. data:: MethodType From 646a01fbdef4279620152dc082f5ddcc214dc2bb Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 7 Feb 2019 14:46:48 +0100 Subject: [PATCH 6/7] DOC cross-reference CellType in datamodel.rst --- Doc/reference/datamodel.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 83e1d239b34a754..9961aee14e06524 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 ` type can be accessed in the :mod:`types` + module. Instance methods .. index:: From 48a4f11b306c241c05ef8861ae7b308e1bc882bf Mon Sep 17 00:00:00 2001 From: Pierre Glaser Date: Thu, 7 Feb 2019 14:48:03 +0100 Subject: [PATCH 7/7] CLN typos and newlines --- Doc/library/types.rst | 2 ++ Objects/cellobject.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 3b3455e54b3cfb3..07c3a2e7f68276d 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -135,6 +135,7 @@ 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 @@ -142,6 +143,7 @@ Standard names are defined for the following types: .. versionadded:: 3.8 + .. data:: MethodType The type of methods of user-defined class instances. diff --git a/Objects/cellobject.c b/Objects/cellobject.c index efd22970f6a41d1..4e359f889fdc81c 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -28,7 +28,7 @@ PyDoc_STRVAR(cell_new_doc, "\n" " contents\n" " the contents of the cell. If not specified, the cell will be empty,\n" -" and \n further attemps to access its cell_contents attribute will\n" +" and \n further attempts to access its cell_contents attribute will\n" " raise a ValueError.");