Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Objects/cellobject.c
12 views
1
/* Cell object implementation */
2
3
#include "Python.h"
4
#include "pycore_object.h"
5
6
PyObject *
7
PyCell_New(PyObject *obj)
8
{
9
PyCellObject *op;
10
11
op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
12
if (op == NULL)
13
return NULL;
14
op->ob_ref = Py_XNewRef(obj);
15
16
_PyObject_GC_TRACK(op);
17
return (PyObject *)op;
18
}
19
20
PyDoc_STRVAR(cell_new_doc,
21
"cell([contents])\n"
22
"--\n"
23
"\n"
24
"Create a new cell object.\n"
25
"\n"
26
" contents\n"
27
" the contents of the cell. If not specified, the cell will be empty,\n"
28
" and \n further attempts to access its cell_contents attribute will\n"
29
" raise a ValueError.");
30
31
32
static PyObject *
33
cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
34
{
35
PyObject *return_value = NULL;
36
PyObject *obj = NULL;
37
38
if (!_PyArg_NoKeywords("cell", kwargs)) {
39
goto exit;
40
}
41
/* min = 0: we allow the cell to be empty */
42
if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
43
goto exit;
44
}
45
return_value = PyCell_New(obj);
46
47
exit:
48
return return_value;
49
}
50
51
PyObject *
52
PyCell_Get(PyObject *op)
53
{
54
if (!PyCell_Check(op)) {
55
PyErr_BadInternalCall();
56
return NULL;
57
}
58
PyObject *value = PyCell_GET(op);
59
return Py_XNewRef(value);
60
}
61
62
int
63
PyCell_Set(PyObject *op, PyObject *value)
64
{
65
if (!PyCell_Check(op)) {
66
PyErr_BadInternalCall();
67
return -1;
68
}
69
PyObject *old_value = PyCell_GET(op);
70
PyCell_SET(op, Py_XNewRef(value));
71
Py_XDECREF(old_value);
72
return 0;
73
}
74
75
static void
76
cell_dealloc(PyCellObject *op)
77
{
78
_PyObject_GC_UNTRACK(op);
79
Py_XDECREF(op->ob_ref);
80
PyObject_GC_Del(op);
81
}
82
83
static PyObject *
84
cell_richcompare(PyObject *a, PyObject *b, int op)
85
{
86
/* neither argument should be NULL, unless something's gone wrong */
87
assert(a != NULL && b != NULL);
88
89
/* both arguments should be instances of PyCellObject */
90
if (!PyCell_Check(a) || !PyCell_Check(b)) {
91
Py_RETURN_NOTIMPLEMENTED;
92
}
93
94
/* compare cells by contents; empty cells come before anything else */
95
a = ((PyCellObject *)a)->ob_ref;
96
b = ((PyCellObject *)b)->ob_ref;
97
if (a != NULL && b != NULL)
98
return PyObject_RichCompare(a, b, op);
99
100
Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
101
}
102
103
static PyObject *
104
cell_repr(PyCellObject *op)
105
{
106
if (op->ob_ref == NULL)
107
return PyUnicode_FromFormat("<cell at %p: empty>", op);
108
109
return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
110
op, Py_TYPE(op->ob_ref)->tp_name,
111
op->ob_ref);
112
}
113
114
static int
115
cell_traverse(PyCellObject *op, visitproc visit, void *arg)
116
{
117
Py_VISIT(op->ob_ref);
118
return 0;
119
}
120
121
static int
122
cell_clear(PyCellObject *op)
123
{
124
Py_CLEAR(op->ob_ref);
125
return 0;
126
}
127
128
static PyObject *
129
cell_get_contents(PyCellObject *op, void *closure)
130
{
131
if (op->ob_ref == NULL)
132
{
133
PyErr_SetString(PyExc_ValueError, "Cell is empty");
134
return NULL;
135
}
136
return Py_NewRef(op->ob_ref);
137
}
138
139
static int
140
cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored))
141
{
142
Py_XSETREF(op->ob_ref, Py_XNewRef(obj));
143
return 0;
144
}
145
146
static PyGetSetDef cell_getsetlist[] = {
147
{"cell_contents", (getter)cell_get_contents,
148
(setter)cell_set_contents, NULL},
149
{NULL} /* sentinel */
150
};
151
152
PyTypeObject PyCell_Type = {
153
PyVarObject_HEAD_INIT(&PyType_Type, 0)
154
"cell",
155
sizeof(PyCellObject),
156
0,
157
(destructor)cell_dealloc, /* tp_dealloc */
158
0, /* tp_vectorcall_offset */
159
0, /* tp_getattr */
160
0, /* tp_setattr */
161
0, /* tp_as_async */
162
(reprfunc)cell_repr, /* tp_repr */
163
0, /* tp_as_number */
164
0, /* tp_as_sequence */
165
0, /* tp_as_mapping */
166
0, /* tp_hash */
167
0, /* tp_call */
168
0, /* tp_str */
169
PyObject_GenericGetAttr, /* tp_getattro */
170
0, /* tp_setattro */
171
0, /* tp_as_buffer */
172
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
173
cell_new_doc, /* tp_doc */
174
(traverseproc)cell_traverse, /* tp_traverse */
175
(inquiry)cell_clear, /* tp_clear */
176
cell_richcompare, /* tp_richcompare */
177
0, /* tp_weaklistoffset */
178
0, /* tp_iter */
179
0, /* tp_iternext */
180
0, /* tp_methods */
181
0, /* tp_members */
182
cell_getsetlist, /* tp_getset */
183
0, /* tp_base */
184
0, /* tp_dict */
185
0, /* tp_descr_get */
186
0, /* tp_descr_set */
187
0, /* tp_dictoffset */
188
0, /* tp_init */
189
0, /* tp_alloc */
190
(newfunc)cell_new, /* tp_new */
191
0, /* tp_free */
192
};
193
194