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