Skip to content

Commit 811b8eb

Browse files
committed
sync docs
1 parent 1fb5d8a commit 811b8eb

5 files changed

Lines changed: 59 additions & 51 deletions

File tree

Doc/extending/newtypes_tutorial.rst

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -250,16 +250,17 @@ Because we now have data to manage, we have to be more careful about object
250250
allocation and deallocation. At a minimum, we need a deallocation method::
251251

252252
static void
253-
Custom_dealloc(CustomObject *self)
253+
Custom_dealloc(PyObject *op)
254254
{
255+
CustomObject *self = (CustomObject *) op;
255256
Py_XDECREF(self->first);
256257
Py_XDECREF(self->last);
257-
Py_TYPE(self)->tp_free((PyObject *) self);
258+
Py_TYPE(self)->tp_free(op);
258259
}
259260

260261
which is assigned to the :c:member:`~PyTypeObject.tp_dealloc` member::
261262

262-
.tp_dealloc = (destructor) Custom_dealloc,
263+
.tp_dealloc = Custom_dealloc,
263264

264265
This method first clears the reference counts of the two Python attributes.
265266
:c:func:`Py_XDECREF` correctly handles the case where its argument is
@@ -270,11 +271,10 @@ the object's type might not be :class:`!CustomType`, because the object may
270271
be an instance of a subclass.
271272

272273
.. note::
273-
The explicit cast to ``destructor`` above is needed because we defined
274-
``Custom_dealloc`` to take a ``CustomObject *`` argument, but the ``tp_dealloc``
275-
function pointer expects to receive a ``PyObject *`` argument. Otherwise,
276-
the compiler will emit a warning. This is object-oriented polymorphism,
277-
in C!
274+
The explicit cast to ``CustomObject *`` above is needed because we defined
275+
``Custom_dealloc`` to take a ``PyObject *`` argument, as the ``tp_dealloc``
276+
function pointer expects to receive a ``PyObject *`` argument. Otherwise,
277+
this would result in an undefined behaviour at runtime!
278278

279279
We want to make sure that the first and last names are initialized to empty
280280
strings, so we provide a ``tp_new`` implementation::
@@ -352,8 +352,9 @@ We also define an initialization function which accepts arguments to provide
352352
initial values for our instance::
353353

354354
static int
355-
Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
355+
Custom_init(PyObject *op, PyObject *args, PyObject *kwds)
356356
{
357+
CustomObject *self = (CustomObject *) op;
357358
static char *kwlist[] = {"first", "last", "number", NULL};
358359
PyObject *first = NULL, *last = NULL, *tmp;
359360

@@ -379,7 +380,7 @@ initial values for our instance::
379380

380381
by filling the :c:member:`~PyTypeObject.tp_init` slot. ::
381382

382-
.tp_init = (initproc) Custom_init,
383+
.tp_init = Custom_init,
383384

384385
The :c:member:`~PyTypeObject.tp_init` slot is exposed in Python as the
385386
:meth:`~object.__init__` method. It is used to initialize an object after it's
@@ -451,8 +452,9 @@ We define a single method, :meth:`!Custom.name`, that outputs the objects name a
451452
concatenation of the first and last names. ::
452453

453454
static PyObject *
454-
Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))
455+
Custom_name(PyObject *op, PyObject *Py_UNUSED(dummy))
455456
{
457+
CustomObject *self = (CustomObject *) op;
456458
if (self->first == NULL) {
457459
PyErr_SetString(PyExc_AttributeError, "first");
458460
return NULL;
@@ -486,7 +488,7 @@ Now that we've defined the method, we need to create an array of method
486488
definitions::
487489

488490
static PyMethodDef Custom_methods[] = {
489-
{"name", (PyCFunction) Custom_name, METH_NOARGS,
491+
{"name", Custom_name, METH_NOARGS,
490492
"Return the name, combining the first and last name"
491493
},
492494
{NULL} /* Sentinel */
@@ -543,15 +545,17 @@ we'll use custom getter and setter functions. Here are the functions for
543545
getting and setting the :attr:`!first` attribute::
544546

545547
static PyObject *
546-
Custom_getfirst(CustomObject *self, void *closure)
548+
Custom_getfirst(PyObject *op, void *closure)
547549
{
550+
CustomObject *self = (CustomObject *) op;
548551
Py_INCREF(self->first);
549552
return self->first;
550553
}
551554

552555
static int
553-
Custom_setfirst(CustomObject *self, PyObject *value, void *closure)
556+
Custom_setfirst(PyObject *op, PyObject *value, void *closure)
554557
{
558+
CustomObject *self = (CustomObject *) op;
555559
PyObject *tmp;
556560
if (value == NULL) {
557561
PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
@@ -583,9 +587,9 @@ new value is not a string.
583587
We create an array of :c:type:`PyGetSetDef` structures::
584588

585589
static PyGetSetDef Custom_getsetters[] = {
586-
{"first", (getter) Custom_getfirst, (setter) Custom_setfirst,
590+
{"first", Custom_getfirst, Custom_setfirst,
587591
"first name", NULL},
588-
{"last", (getter) Custom_getlast, (setter) Custom_setlast,
592+
{"last", Custom_getlast, Custom_setlast,
589593
"last name", NULL},
590594
{NULL} /* Sentinel */
591595
};
@@ -609,8 +613,9 @@ We also need to update the :c:member:`~PyTypeObject.tp_init` handler to only
609613
allow strings [#]_ to be passed::
610614

611615
static int
612-
Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)
616+
Custom_init(PyObject *op, PyObject *args, PyObject *kwds)
613617
{
618+
CustomObject *self = (CustomObject *) op;
614619
static char *kwlist[] = {"first", "last", "number", NULL};
615620
PyObject *first = NULL, *last = NULL, *tmp;
616621

@@ -689,8 +694,9 @@ First, the traversal method lets the cyclic GC know about subobjects that could
689694
participate in cycles::
690695

691696
static int
692-
Custom_traverse(CustomObject *self, visitproc visit, void *arg)
697+
Custom_traverse(PyObject *op, visitproc visit, void *arg)
693698
{
699+
CustomObject *self = (CustomObject *) op;
694700
int vret;
695701
if (self->first) {
696702
vret = visit(self->first, arg);
@@ -716,8 +722,9 @@ functions. With :c:func:`Py_VISIT`, we can minimize the amount of boilerplate
716722
in ``Custom_traverse``::
717723

718724
static int
719-
Custom_traverse(CustomObject *self, visitproc visit, void *arg)
725+
Custom_traverse(PyObject *op, visitproc visit, void *arg)
720726
{
727+
CustomObject *self = (CustomObject *) op;
721728
Py_VISIT(self->first);
722729
Py_VISIT(self->last);
723730
return 0;
@@ -731,8 +738,9 @@ Second, we need to provide a method for clearing any subobjects that can
731738
participate in cycles::
732739

733740
static int
734-
Custom_clear(CustomObject *self)
741+
Custom_clear(PyObject *op)
735742
{
743+
CustomObject *self = (CustomObject *) op;
736744
Py_CLEAR(self->first);
737745
Py_CLEAR(self->last);
738746
return 0;
@@ -765,11 +773,11 @@ Here is our reimplemented deallocator using :c:func:`PyObject_GC_UnTrack`
765773
and ``Custom_clear``::
766774

767775
static void
768-
Custom_dealloc(CustomObject *self)
776+
Custom_dealloc(PyObject *op)
769777
{
770-
PyObject_GC_UnTrack(self);
771-
Custom_clear(self);
772-
Py_TYPE(self)->tp_free((PyObject *) self);
778+
PyObject_GC_UnTrack(op);
779+
(void)Custom_clear(op);
780+
Py_TYPE(op)->tp_free(op);
773781
}
774782

775783
Finally, we add the :c:macro:`Py_TPFLAGS_HAVE_GC` flag to the class flags::
@@ -825,9 +833,10 @@ When a Python object is a :class:`!SubList` instance, its ``PyObject *`` pointer
825833
can be safely cast to both ``PyListObject *`` and ``SubListObject *``::
826834

827835
static int
828-
SubList_init(SubListObject *self, PyObject *args, PyObject *kwds)
836+
SubList_init(PyObject *op, PyObject *args, PyObject *kwds)
829837
{
830-
if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0)
838+
SubListObject *self = (SubListObject *) op;
839+
if (PyList_Type.tp_init(op, args, kwds) < 0)
831840
return -1;
832841
self->state = 0;
833842
return 0;

Doc/includes/newtypes/custom2.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ typedef struct {
1212
static void
1313
Custom_dealloc(PyObject *op)
1414
{
15-
CustomObject *self = (CustomObject *)op;
15+
CustomObject *self = (CustomObject *) op;
1616
Py_XDECREF(self->first);
1717
Py_XDECREF(self->last);
1818
Py_TYPE(self)->tp_free(self);
@@ -42,7 +42,7 @@ Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4242
static int
4343
Custom_init(PyObject *op, PyObject *args, PyObject *kwds)
4444
{
45-
CustomObject *self = (CustomObject *)op;
45+
CustomObject *self = (CustomObject *) op;
4646
static char *kwlist[] = {"first", "last", "number", NULL};
4747
PyObject *first = NULL, *last = NULL;
4848

@@ -73,7 +73,7 @@ static PyMemberDef Custom_members[] = {
7373
static PyObject *
7474
Custom_name(PyObject *op, PyObject *Py_UNUSED(dummy))
7575
{
76-
CustomObject *self = (CustomObject *)op;
76+
CustomObject *self = (CustomObject *) op;
7777
if (self->first == NULL) {
7878
PyErr_SetString(PyExc_AttributeError, "first");
7979
return NULL;

Doc/includes/newtypes/custom3.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ typedef struct {
1212
static void
1313
Custom_dealloc(PyObject *op)
1414
{
15-
CustomObject *self = (CustomObject *)op;
15+
CustomObject *self = (CustomObject *) op;
1616
Py_XDECREF(self->first);
1717
Py_XDECREF(self->last);
1818
Py_TYPE(self)->tp_free(self);
@@ -42,7 +42,7 @@ Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
4242
static int
4343
Custom_init(PyObject *op, PyObject *args, PyObject *kwds)
4444
{
45-
CustomObject *self = (CustomObject *)op;
45+
CustomObject *self = (CustomObject *) op;
4646
static char *kwlist[] = {"first", "last", "number", NULL};
4747
PyObject *first = NULL, *last = NULL;
4848

@@ -69,14 +69,14 @@ static PyMemberDef Custom_members[] = {
6969
static PyObject *
7070
Custom_getfirst(PyObject *op, void *closure)
7171
{
72-
CustomObject *self = (CustomObject *)op;
72+
CustomObject *self = (CustomObject *) op;
7373
return Py_NewRef(self->first);
7474
}
7575

7676
static int
7777
Custom_setfirst(PyObject *op, PyObject *value, void *closure)
7878
{
79-
CustomObject *self = (CustomObject *)op;
79+
CustomObject *self = (CustomObject *) op;
8080
if (value == NULL) {
8181
PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
8282
return -1;
@@ -93,14 +93,14 @@ Custom_setfirst(PyObject *op, PyObject *value, void *closure)
9393
static PyObject *
9494
Custom_getlast(PyObject *op, void *closure)
9595
{
96-
CustomObject *self = (CustomObject *)op;
96+
CustomObject *self = (CustomObject *) op;
9797
return Py_NewRef(self->last);
9898
}
9999

100100
static int
101101
Custom_setlast(PyObject *op, PyObject *value, void *closure)
102102
{
103-
CustomObject *self = (CustomObject *)op;
103+
CustomObject *self = (CustomObject *) op;
104104
if (value == NULL) {
105105
PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
106106
return -1;
@@ -125,7 +125,7 @@ static PyGetSetDef Custom_getsetters[] = {
125125
static PyObject *
126126
Custom_name(PyObject *op, PyObject *Py_UNUSED(dummy))
127127
{
128-
CustomObject *self = (CustomObject *)op;
128+
CustomObject *self = (CustomObject *) op;
129129
return PyUnicode_FromFormat("%S %S", self->first, self->last);
130130
}
131131

Doc/includes/newtypes/custom4.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ typedef struct {
1212
static int
1313
Custom_traverse(PyObject *op, visitproc visit, void *arg)
1414
{
15-
CustomObject *self = (CustomObject *)op;
15+
CustomObject *self = (CustomObject *) op;
1616
Py_VISIT(self->first);
1717
Py_VISIT(self->last);
1818
return 0;
@@ -21,7 +21,7 @@ Custom_traverse(PyObject *op, visitproc visit, void *arg)
2121
static int
2222
Custom_clear(PyObject *op)
2323
{
24-
CustomObject *self = (CustomObject *)op;
24+
CustomObject *self = (CustomObject *) op;
2525
Py_CLEAR(self->first);
2626
Py_CLEAR(self->last);
2727
return 0;
@@ -30,10 +30,9 @@ Custom_clear(PyObject *op)
3030
static void
3131
Custom_dealloc(PyObject *op)
3232
{
33-
CustomObject *self = (CustomObject *)op;
34-
PyObject_GC_UnTrack(self);
35-
Custom_clear(self);
36-
Py_TYPE(self)->tp_free(self);
33+
PyObject_GC_UnTrack(op);
34+
(void)Custom_clear(op);
35+
Py_TYPE(op)->tp_free(op);
3736
}
3837

3938
static PyObject *
@@ -60,7 +59,7 @@ Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
6059
static int
6160
Custom_init(PyObject *op, PyObject *args, PyObject *kwds)
6261
{
63-
CustomObject *self = (CustomObject *)op;
62+
CustomObject *self = (CustomObject *) op;
6463
static char *kwlist[] = {"first", "last", "number", NULL};
6564
PyObject *first = NULL, *last = NULL;
6665

@@ -87,14 +86,14 @@ static PyMemberDef Custom_members[] = {
8786
static PyObject *
8887
Custom_getfirst(PyObject *op, void *closure)
8988
{
90-
CustomObject *self = (CustomObject *)op;
89+
CustomObject *self = (CustomObject *) op;
9190
return Py_NewRef(self->first);
9291
}
9392

9493
static int
9594
Custom_setfirst(PyObject *op, PyObject *value, void *closure)
9695
{
97-
CustomObject *self = (CustomObject *)op;
96+
CustomObject *self = (CustomObject *) op;
9897
if (value == NULL) {
9998
PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute");
10099
return -1;
@@ -111,14 +110,14 @@ Custom_setfirst(PyObject *op, PyObject *value, void *closure)
111110
static PyObject *
112111
Custom_getlast(PyObject *op, void *closure)
113112
{
114-
CustomObject *self = (CustomObject *)op;
113+
CustomObject *self = (CustomObject *) op;
115114
return Py_NewRef(self->last);
116115
}
117116

118117
static int
119118
Custom_setlast(PyObject *op, PyObject *value, void *closure)
120119
{
121-
CustomObject *self = (CustomObject *)op;
120+
CustomObject *self = (CustomObject *) op;
122121
if (value == NULL) {
123122
PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute");
124123
return -1;
@@ -143,7 +142,7 @@ static PyGetSetDef Custom_getsetters[] = {
143142
static PyObject *
144143
Custom_name(PyObject *op, PyObject *Py_UNUSED(dummy))
145144
{
146-
CustomObject *self = (CustomObject *)op;
145+
CustomObject *self = (CustomObject *) op;
147146
return PyUnicode_FromFormat("%S %S", self->first, self->last);
148147
}
149148

Doc/includes/newtypes/sublist.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ typedef struct {
99
static PyObject *
1010
SubList_increment(PyObject *op, PyObject *Py_UNUSED(dummy))
1111
{
12-
SubListObject *self = (SubListObject *)op;
12+
SubListObject *self = (SubListObject *) op;
1313
self->state++;
1414
return PyLong_FromLong(self->state);
1515
}
@@ -23,8 +23,8 @@ static PyMethodDef SubList_methods[] = {
2323
static int
2424
SubList_init(PyObject *op, PyObject *args, PyObject *kwds)
2525
{
26-
SubListObject *self = (SubListObject *)op;
27-
if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0)
26+
SubListObject *self = (SubListObject *) op;
27+
if (PyList_Type.tp_init(op, args, kwds) < 0)
2828
return -1;
2929
self->state = 0;
3030
return 0;

0 commit comments

Comments
 (0)