bpo-35911: add cell constructor (GH-11771)
Add a cell constructor, expose the cell type in the types module.
This commit is contained in:
parent
f289084c83
commit
df8d2cde63
|
@ -136,6 +136,14 @@ Standard names are defined for the following types:
|
||||||
The type for code objects such as returned by :func:`compile`.
|
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
|
.. data:: MethodType
|
||||||
|
|
||||||
The type of methods of user-defined class instances.
|
The type of methods of user-defined class instances.
|
||||||
|
|
|
@ -539,7 +539,9 @@ Callable types
|
||||||
the value of the cell, as well as set the value.
|
the value of the cell, as well as set the value.
|
||||||
|
|
||||||
Additional information about a function's definition can be retrieved from its
|
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
|
Instance methods
|
||||||
.. index::
|
.. index::
|
||||||
|
|
|
@ -83,6 +83,15 @@ class FunctionPropertiesTest(FuncAttrsTest):
|
||||||
self.assertEqual(c[0].__class__.__name__, "cell")
|
self.assertEqual(c[0].__class__.__name__, "cell")
|
||||||
self.cannot_set_attr(f, "__closure__", c, AttributeError)
|
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 test_empty_cell(self):
|
||||||
def f(): print(a)
|
def f(): print(a)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -15,6 +15,13 @@ CodeType = type(_f.__code__)
|
||||||
MappingProxyType = type(type.__dict__)
|
MappingProxyType = type(type.__dict__)
|
||||||
SimpleNamespace = type(sys.implementation)
|
SimpleNamespace = type(sys.implementation)
|
||||||
|
|
||||||
|
def _cell_factory():
|
||||||
|
a = 1
|
||||||
|
def f():
|
||||||
|
nonlocal a
|
||||||
|
return f.__closure__[0]
|
||||||
|
CellType = type(_cell_factory())
|
||||||
|
|
||||||
def _g():
|
def _g():
|
||||||
yield 1
|
yield 1
|
||||||
GeneratorType = type(_g())
|
GeneratorType = type(_g())
|
||||||
|
|
|
@ -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.
|
|
@ -20,6 +20,37 @@ PyCell_New(PyObject *obj)
|
||||||
return (PyObject *)op;
|
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 *
|
PyObject *
|
||||||
PyCell_Get(PyObject *op)
|
PyCell_Get(PyObject *op)
|
||||||
{
|
{
|
||||||
|
@ -146,7 +177,7 @@ PyTypeObject PyCell_Type = {
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||||
0, /* tp_doc */
|
cell_new_doc, /* tp_doc */
|
||||||
(traverseproc)cell_traverse, /* tp_traverse */
|
(traverseproc)cell_traverse, /* tp_traverse */
|
||||||
(inquiry)cell_clear, /* tp_clear */
|
(inquiry)cell_clear, /* tp_clear */
|
||||||
cell_richcompare, /* tp_richcompare */
|
cell_richcompare, /* tp_richcompare */
|
||||||
|
@ -156,4 +187,13 @@ PyTypeObject PyCell_Type = {
|
||||||
0, /* tp_methods */
|
0, /* tp_methods */
|
||||||
0, /* tp_members */
|
0, /* tp_members */
|
||||||
cell_getsetlist, /* tp_getset */
|
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 */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue