diff options
author | Antoine Pitrou <pitrou@free.fr> | 2018-04-07 16:14:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-07 16:14:03 (GMT) |
commit | 1d80a561734b9932961c546b0897405a3bfbf3e6 (patch) | |
tree | 737793472ed6d3745d31fb56f2cb1f2b66429c69 /Doc/includes | |
parent | b405752dab95fa5dc65a19d94e798844d0378c61 (diff) | |
download | cpython-1d80a561734b9932961c546b0897405a3bfbf3e6.zip cpython-1d80a561734b9932961c546b0897405a3bfbf3e6.tar.gz cpython-1d80a561734b9932961c546b0897405a3bfbf3e6.tar.bz2 |
bpo-33201: Modernize "Extension types" doc (GH-6337)
* bpo-33201: Modernize "Extension types" doc
* Split tutorial and other topics
* Some small fixes
* Address some review comments
* Rename noddy* to custom* and shoddy to sublist
* Fix markup
Diffstat (limited to 'Doc/includes')
-rw-r--r-- | Doc/includes/custom.c | 39 | ||||
-rw-r--r-- | Doc/includes/custom2.c | 132 | ||||
-rw-r--r-- | Doc/includes/custom3.c | 183 | ||||
-rw-r--r-- | Doc/includes/custom4.c | 197 | ||||
-rw-r--r-- | Doc/includes/noddy.c | 72 | ||||
-rw-r--r-- | Doc/includes/noddy2.c | 172 | ||||
-rw-r--r-- | Doc/includes/noddy3.c | 225 | ||||
-rw-r--r-- | Doc/includes/noddy4.c | 208 | ||||
-rw-r--r-- | Doc/includes/shoddy.c | 99 | ||||
-rw-r--r-- | Doc/includes/sublist.c | 63 | ||||
-rw-r--r-- | Doc/includes/test.py | 218 |
11 files changed, 716 insertions, 892 deletions
diff --git a/Doc/includes/custom.c b/Doc/includes/custom.c new file mode 100644 index 0000000..fb2c7b2 --- /dev/null +++ b/Doc/includes/custom.c @@ -0,0 +1,39 @@ +#include <Python.h> + +typedef struct { + PyObject_HEAD + /* Type-specific fields go here. */ +} CustomObject; + +static PyTypeObject CustomType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "custom.Custom", + .tp_doc = "Custom objects", + .tp_basicsize = sizeof(CustomObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_new = PyType_GenericNew, +}; + +static PyModuleDef custommodule = { + PyModuleDef_HEAD_INIT, + .m_name = "custom", + .m_doc = "Example module that creates an extension type.", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_custom(void) +{ + PyObject *m; + if (PyType_Ready(&CustomType) < 0) + return NULL; + + m = PyModule_Create(&custommodule); + if (m == NULL) + return NULL; + + Py_INCREF(&CustomType); + PyModule_AddObject(m, "Custom", (PyObject *) &CustomType); + return m; +} diff --git a/Doc/includes/custom2.c b/Doc/includes/custom2.c new file mode 100644 index 0000000..51ab4b8 --- /dev/null +++ b/Doc/includes/custom2.c @@ -0,0 +1,132 @@ +#include <Python.h> +#include "structmember.h" + +typedef struct { + PyObject_HEAD + PyObject *first; /* first name */ + PyObject *last; /* last name */ + int number; +} CustomObject; + +static void +Custom_dealloc(CustomObject *self) +{ + Py_XDECREF(self->first); + Py_XDECREF(self->last); + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + CustomObject *self; + self = (CustomObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->first = PyUnicode_FromString(""); + if (self->first == NULL) { + Py_DECREF(self); + return NULL; + } + self->last = PyUnicode_FromString(""); + if (self->last == NULL) { + Py_DECREF(self); + return NULL; + } + self->number = 0; + } + return (PyObject *) self; +} + +static int +Custom_init(CustomObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"first", "last", "number", NULL}; + PyObject *first = NULL, *last = NULL, *tmp; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, + &first, &last, + &self->number)) + return -1; + + if (first) { + tmp = self->first; + Py_INCREF(first); + self->first = first; + Py_XDECREF(tmp); + } + if (last) { + tmp = self->last; + Py_INCREF(last); + self->last = last; + Py_XDECREF(tmp); + } + return 0; +} + +static PyMemberDef Custom_members[] = { + {"first", T_OBJECT_EX, offsetof(CustomObject, first), 0, + "first name"}, + {"last", T_OBJECT_EX, offsetof(CustomObject, last), 0, + "last name"}, + {"number", T_INT, offsetof(CustomObject, number), 0, + "custom number"}, + {NULL} /* Sentinel */ +}; + +static PyObject * +Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored)) +{ + if (self->first == NULL) { + PyErr_SetString(PyExc_AttributeError, "first"); + return NULL; + } + if (self->last == NULL) { + PyErr_SetString(PyExc_AttributeError, "last"); + return NULL; + } + return PyUnicode_FromFormat("%S %S", self->first, self->last); +} + +static PyMethodDef Custom_methods[] = { + {"name", (PyCFunction) Custom_name, METH_NOARGS, + "Return the name, combining the first and last name" + }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject CustomType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "custom2.Custom", + .tp_doc = "Custom objects", + .tp_basicsize = sizeof(CustomObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = Custom_new, + .tp_init = (initproc) Custom_init, + .tp_dealloc = (destructor) Custom_dealloc, + .tp_members = Custom_members, + .tp_methods = Custom_methods, +}; + +static PyModuleDef custommodule = { + PyModuleDef_HEAD_INIT, + .m_name = "custom2", + .m_doc = "Example module that creates an extension type.", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_custom2(void) +{ + PyObject *m; + if (PyType_Ready(&CustomType) < 0) + return NULL; + + m = PyModule_Create(&custommodule); + if (m == NULL) + return NULL; + + Py_INCREF(&CustomType); + PyModule_AddObject(m, "Custom", (PyObject *) &CustomType); + return m; +} diff --git a/Doc/includes/custom3.c b/Doc/includes/custom3.c new file mode 100644 index 0000000..09e8735 --- /dev/null +++ b/Doc/includes/custom3.c @@ -0,0 +1,183 @@ +#include <Python.h> +#include "structmember.h" + +typedef struct { + PyObject_HEAD + PyObject *first; /* first name */ + PyObject *last; /* last name */ + int number; +} CustomObject; + +static void +Custom_dealloc(CustomObject *self) +{ + Py_XDECREF(self->first); + Py_XDECREF(self->last); + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + CustomObject *self; + self = (CustomObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->first = PyUnicode_FromString(""); + if (self->first == NULL) { + Py_DECREF(self); + return NULL; + } + self->last = PyUnicode_FromString(""); + if (self->last == NULL) { + Py_DECREF(self); + return NULL; + } + self->number = 0; + } + return (PyObject *) self; +} + +static int +Custom_init(CustomObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"first", "last", "number", NULL}; + PyObject *first = NULL, *last = NULL, *tmp; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist, + &first, &last, + &self->number)) + return -1; + + if (first) { + tmp = self->first; + Py_INCREF(first); + self->first = first; + Py_DECREF(tmp); + } + if (last) { + tmp = self->last; + Py_INCREF(last); + self->last = last; + Py_DECREF(tmp); + } + return 0; +} + +static PyMemberDef Custom_members[] = { + {"number", T_INT, offsetof(CustomObject, number), 0, + "custom number"}, + {NULL} /* Sentinel */ +}; + +static PyObject * +Custom_getfirst(CustomObject *self, void *closure) +{ + Py_INCREF(self->first); + return self->first; +} + +static int +Custom_setfirst(CustomObject *self, PyObject *value, void *closure) +{ + PyObject *tmp; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The first attribute value must be a string"); + return -1; + } + tmp = self->first; + Py_INCREF(value); + self->first = value; + Py_DECREF(tmp); + return 0; +} + +static PyObject * +Custom_getlast(CustomObject *self, void *closure) +{ + Py_INCREF(self->last); + return self->last; +} + +static int +Custom_setlast(CustomObject *self, PyObject *value, void *closure) +{ + PyObject *tmp; + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The last attribute value must be a string"); + return -1; + } + tmp = self->last; + Py_INCREF(value); + self->last = value; + Py_DECREF(tmp); + return 0; +} + +static PyGetSetDef Custom_getsetters[] = { + {"first", (getter) Custom_getfirst, (setter) Custom_setfirst, + "first name", NULL}, + {"last", (getter) Custom_getlast, (setter) Custom_setlast, + "last name", NULL}, + {NULL} /* Sentinel */ +}; + +static PyObject * +Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromFormat("%S %S", self->first, self->last); +} + +static PyMethodDef Custom_methods[] = { + {"name", (PyCFunction) Custom_name, METH_NOARGS, + "Return the name, combining the first and last name" + }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject CustomType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "custom3.Custom", + .tp_doc = "Custom objects", + .tp_basicsize = sizeof(CustomObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = Custom_new, + .tp_init = (initproc) Custom_init, + .tp_dealloc = (destructor) Custom_dealloc, + .tp_members = Custom_members, + .tp_methods = Custom_methods, + .tp_getset = Custom_getsetters, +}; + +static PyModuleDef custommodule = { + PyModuleDef_HEAD_INIT, + .m_name = "custom3", + .m_doc = "Example module that creates an extension type.", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_custom3(void) +{ + PyObject *m; + if (PyType_Ready(&CustomType) < 0) + return NULL; + + m = PyModule_Create(&custommodule); + if (m == NULL) + return NULL; + + Py_INCREF(&CustomType); + PyModule_AddObject(m, "Custom", (PyObject *) &CustomType); + return m; +} diff --git a/Doc/includes/custom4.c b/Doc/includes/custom4.c new file mode 100644 index 0000000..0994d8f --- /dev/null +++ b/Doc/includes/custom4.c @@ -0,0 +1,197 @@ +#include <Python.h> +#include "structmember.h" + +typedef struct { + PyObject_HEAD + PyObject *first; /* first name */ + PyObject *last; /* last name */ + int number; +} CustomObject; + +static int +Custom_traverse(CustomObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->first); + Py_VISIT(self->last); + return 0; +} + +static int +Custom_clear(CustomObject *self) +{ + Py_CLEAR(self->first); + Py_CLEAR(self->last); + return 0; +} + +static void +Custom_dealloc(CustomObject *self) +{ + PyObject_GC_UnTrack(self); + Custom_clear(self); + Py_TYPE(self)->tp_free((PyObject *) self); +} + +static PyObject * +Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + CustomObject *self; + self = (CustomObject *) type->tp_alloc(type, 0); + if (self != NULL) { + self->first = PyUnicode_FromString(""); + if (self->first == NULL) { + Py_DECREF(self); + return NULL; + } + self->last = PyUnicode_FromString(""); + if (self->last == NULL) { + Py_DECREF(self); + return NULL; + } + self->number = 0; + } + return (PyObject *) self; +} + +static int +Custom_init(CustomObject *self, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"first", "last", "number", NULL}; + PyObject *first = NULL, *last = NULL, *tmp; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist, + &first, &last, + &self->number)) + return -1; + + if (first) { + tmp = self->first; + Py_INCREF(first); + self->first = first; + Py_DECREF(tmp); + } + if (last) { + tmp = self->last; + Py_INCREF(last); + self->last = last; + Py_DECREF(tmp); + } + return 0; +} + +static PyMemberDef Custom_members[] = { + {"number", T_INT, offsetof(CustomObject, number), 0, + "custom number"}, + {NULL} /* Sentinel */ +}; + +static PyObject * +Custom_getfirst(CustomObject *self, void *closure) +{ + Py_INCREF(self->first); + return self->first; +} + +static int +Custom_setfirst(CustomObject *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The first attribute value must be a string"); + return -1; + } + Py_INCREF(value); + Py_CLEAR(self->first); + self->first = value; + return 0; +} + +static PyObject * +Custom_getlast(CustomObject *self, void *closure) +{ + Py_INCREF(self->last); + return self->last; +} + +static int +Custom_setlast(CustomObject *self, PyObject *value, void *closure) +{ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); + return -1; + } + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "The last attribute value must be a string"); + return -1; + } + Py_INCREF(value); + Py_CLEAR(self->last); + self->last = value; + return 0; +} + +static PyGetSetDef Custom_getsetters[] = { + {"first", (getter) Custom_getfirst, (setter) Custom_setfirst, + "first name", NULL}, + {"last", (getter) Custom_getlast, (setter) Custom_setlast, + "last name", NULL}, + {NULL} /* Sentinel */ +}; + +static PyObject * +Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored)) +{ + return PyUnicode_FromFormat("%S %S", self->first, self->last); +} + +static PyMethodDef Custom_methods[] = { + {"name", (PyCFunction) Custom_name, METH_NOARGS, + "Return the name, combining the first and last name" + }, + {NULL} /* Sentinel */ +}; + +static PyTypeObject CustomType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "custom4.Custom", + .tp_doc = "Custom objects", + .tp_basicsize = sizeof(CustomObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .tp_new = Custom_new, + .tp_init = (initproc) Custom_init, + .tp_dealloc = (destructor) Custom_dealloc, + .tp_traverse = (traverseproc) Custom_traverse, + .tp_clear = (inquiry) Custom_clear, + .tp_members = Custom_members, + .tp_methods = Custom_methods, + .tp_getset = Custom_getsetters, +}; + +static PyModuleDef custommodule = { + PyModuleDef_HEAD_INIT, + .m_name = "custom4", + .m_doc = "Example module that creates an extension type.", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_custom4(void) +{ + PyObject *m; + if (PyType_Ready(&CustomType) < 0) + return NULL; + + m = PyModule_Create(&custommodule); + if (m == NULL) + return NULL; + + Py_INCREF(&CustomType); + PyModule_AddObject(m, "Custom", (PyObject *) &CustomType); + return m; +} diff --git a/Doc/includes/noddy.c b/Doc/includes/noddy.c deleted file mode 100644 index 07b5d5a..0000000 --- a/Doc/includes/noddy.c +++ /dev/null @@ -1,72 +0,0 @@ -#include <Python.h> - -typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ -} noddy_NoddyObject; - -static PyTypeObject noddy_NoddyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "noddy.Noddy", /* tp_name */ - sizeof(noddy_NoddyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "Noddy objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* 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 */ - PyType_GenericNew, /* tp_new */ -}; - -static PyModuleDef noddymodule = { - PyModuleDef_HEAD_INIT, - "noddy", - "Example module that creates an extension type.", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC -PyInit_noddy(void) -{ - PyObject* m; - - if (PyType_Ready(&noddy_NoddyType) < 0) - return NULL; - - m = PyModule_Create(&noddymodule); - if (m == NULL) - return NULL; - - Py_INCREF(&noddy_NoddyType); - PyModule_AddObject(m, "Noddy", (PyObject *)&noddy_NoddyType); - return m; -} diff --git a/Doc/includes/noddy2.c b/Doc/includes/noddy2.c deleted file mode 100644 index 9641558..0000000 --- a/Doc/includes/noddy2.c +++ /dev/null @@ -1,172 +0,0 @@ -#include <Python.h> -#include "structmember.h" - -typedef struct { - PyObject_HEAD - PyObject *first; /* first name */ - PyObject *last; /* last name */ - int number; -} Noddy; - -static void -Noddy_dealloc(Noddy* self) -{ - Py_XDECREF(self->first); - Py_XDECREF(self->last); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Noddy *self; - - self = (Noddy *)type->tp_alloc(type, 0); - if (self != NULL) { - self->first = PyUnicode_FromString(""); - if (self->first == NULL) { - Py_DECREF(self); - return NULL; - } - - self->last = PyUnicode_FromString(""); - if (self->last == NULL) { - Py_DECREF(self); - return NULL; - } - - self->number = 0; - } - - return (PyObject *)self; -} - -static int -Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) -{ - PyObject *first=NULL, *last=NULL, *tmp; - - static char *kwlist[] = {"first", "last", "number", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, - &first, &last, - &self->number)) - return -1; - - if (first) { - tmp = self->first; - Py_INCREF(first); - self->first = first; - Py_XDECREF(tmp); - } - - if (last) { - tmp = self->last; - Py_INCREF(last); - self->last = last; - Py_XDECREF(tmp); - } - - return 0; -} - - -static PyMemberDef Noddy_members[] = { - {"first", T_OBJECT_EX, offsetof(Noddy, first), 0, - "first name"}, - {"last", T_OBJECT_EX, offsetof(Noddy, last), 0, - "last name"}, - {"number", T_INT, offsetof(Noddy, number), 0, - "noddy number"}, - {NULL} /* Sentinel */ -}; - -static PyObject * -Noddy_name(Noddy* self) -{ - if (self->first == NULL) { - PyErr_SetString(PyExc_AttributeError, "first"); - return NULL; - } - - if (self->last == NULL) { - PyErr_SetString(PyExc_AttributeError, "last"); - return NULL; - } - - return PyUnicode_FromFormat("%S %S", self->first, self->last); -} - -static PyMethodDef Noddy_methods[] = { - {"name", (PyCFunction)Noddy_name, METH_NOARGS, - "Return the name, combining the first and last name" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject NoddyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "noddy.Noddy", /* tp_name */ - sizeof(Noddy), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Noddy_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - "Noddy objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Noddy_methods, /* tp_methods */ - Noddy_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Noddy_init, /* tp_init */ - 0, /* tp_alloc */ - Noddy_new, /* tp_new */ -}; - -static PyModuleDef noddy2module = { - PyModuleDef_HEAD_INIT, - "noddy2", - "Example module that creates an extension type.", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC -PyInit_noddy2(void) -{ - PyObject* m; - - if (PyType_Ready(&NoddyType) < 0) - return NULL; - - m = PyModule_Create(&noddy2module); - if (m == NULL) - return NULL; - - Py_INCREF(&NoddyType); - PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType); - return m; -} diff --git a/Doc/includes/noddy3.c b/Doc/includes/noddy3.c deleted file mode 100644 index 8a5a753..0000000 --- a/Doc/includes/noddy3.c +++ /dev/null @@ -1,225 +0,0 @@ -#include <Python.h> -#include "structmember.h" - -typedef struct { - PyObject_HEAD - PyObject *first; - PyObject *last; - int number; -} Noddy; - -static void -Noddy_dealloc(Noddy* self) -{ - Py_XDECREF(self->first); - Py_XDECREF(self->last); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Noddy *self; - - self = (Noddy *)type->tp_alloc(type, 0); - if (self != NULL) { - self->first = PyUnicode_FromString(""); - if (self->first == NULL) { - Py_DECREF(self); - return NULL; - } - - self->last = PyUnicode_FromString(""); - if (self->last == NULL) { - Py_DECREF(self); - return NULL; - } - - self->number = 0; - } - - return (PyObject *)self; -} - -static int -Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) -{ - PyObject *first=NULL, *last=NULL, *tmp; - - static char *kwlist[] = {"first", "last", "number", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|SSi", kwlist, - &first, &last, - &self->number)) - return -1; - - if (first) { - tmp = self->first; - Py_INCREF(first); - self->first = first; - Py_DECREF(tmp); - } - - if (last) { - tmp = self->last; - Py_INCREF(last); - self->last = last; - Py_DECREF(tmp); - } - - return 0; -} - -static PyMemberDef Noddy_members[] = { - {"number", T_INT, offsetof(Noddy, number), 0, - "noddy number"}, - {NULL} /* Sentinel */ -}; - -static PyObject * -Noddy_getfirst(Noddy *self, void *closure) -{ - Py_INCREF(self->first); - return self->first; -} - -static int -Noddy_setfirst(Noddy *self, PyObject *value, void *closure) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); - return -1; - } - - if (! PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "The first attribute value must be a string"); - return -1; - } - - Py_DECREF(self->first); - Py_INCREF(value); - self->first = value; - - return 0; -} - -static PyObject * -Noddy_getlast(Noddy *self, void *closure) -{ - Py_INCREF(self->last); - return self->last; -} - -static int -Noddy_setlast(Noddy *self, PyObject *value, void *closure) -{ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); - return -1; - } - - if (! PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "The last attribute value must be a string"); - return -1; - } - - Py_DECREF(self->last); - Py_INCREF(value); - self->last = value; - - return 0; -} - -static PyGetSetDef Noddy_getseters[] = { - {"first", - (getter)Noddy_getfirst, (setter)Noddy_setfirst, - "first name", - NULL}, - {"last", - (getter)Noddy_getlast, (setter)Noddy_setlast, - "last name", - NULL}, - {NULL} /* Sentinel */ -}; - -static PyObject * -Noddy_name(Noddy* self) -{ - return PyUnicode_FromFormat("%S %S", self->first, self->last); -} - -static PyMethodDef Noddy_methods[] = { - {"name", (PyCFunction)Noddy_name, METH_NOARGS, - "Return the name, combining the first and last name" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject NoddyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "noddy.Noddy", /* tp_name */ - sizeof(Noddy), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Noddy_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - "Noddy objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Noddy_methods, /* tp_methods */ - Noddy_members, /* tp_members */ - Noddy_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Noddy_init, /* tp_init */ - 0, /* tp_alloc */ - Noddy_new, /* tp_new */ -}; - -static PyModuleDef noddy3module = { - PyModuleDef_HEAD_INIT, - "noddy3", - "Example module that creates an extension type.", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC -PyInit_noddy3(void) -{ - PyObject* m; - - if (PyType_Ready(&NoddyType) < 0) - return NULL; - - m = PyModule_Create(&noddy3module); - if (m == NULL) - return NULL; - - Py_INCREF(&NoddyType); - PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType); - return m; -} diff --git a/Doc/includes/noddy4.c b/Doc/includes/noddy4.c deleted file mode 100644 index 08ba4c3..0000000 --- a/Doc/includes/noddy4.c +++ /dev/null @@ -1,208 +0,0 @@ -#include <Python.h> -#include "structmember.h" - -typedef struct { - PyObject_HEAD - PyObject *first; - PyObject *last; - int number; -} Noddy; - -static int -Noddy_traverse(Noddy *self, visitproc visit, void *arg) -{ - int vret; - - if (self->first) { - vret = visit(self->first, arg); - if (vret != 0) - return vret; - } - if (self->last) { - vret = visit(self->last, arg); - if (vret != 0) - return vret; - } - - return 0; -} - -static int -Noddy_clear(Noddy *self) -{ - PyObject *tmp; - - tmp = self->first; - self->first = NULL; - Py_XDECREF(tmp); - - tmp = self->last; - self->last = NULL; - Py_XDECREF(tmp); - - return 0; -} - -static void -Noddy_dealloc(Noddy* self) -{ - PyObject_GC_UnTrack(self); - Noddy_clear(self); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - Noddy *self; - - self = (Noddy *)type->tp_alloc(type, 0); - if (self != NULL) { - self->first = PyUnicode_FromString(""); - if (self->first == NULL) { - Py_DECREF(self); - return NULL; - } - - self->last = PyUnicode_FromString(""); - if (self->last == NULL) { - Py_DECREF(self); - return NULL; - } - - self->number = 0; - } - - return (PyObject *)self; -} - -static int -Noddy_init(Noddy *self, PyObject *args, PyObject *kwds) -{ - PyObject *first=NULL, *last=NULL, *tmp; - - static char *kwlist[] = {"first", "last", "number", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, - &first, &last, - &self->number)) - return -1; - - if (first) { - tmp = self->first; - Py_INCREF(first); - self->first = first; - Py_XDECREF(tmp); - } - - if (last) { - tmp = self->last; - Py_INCREF(last); - self->last = last; - Py_XDECREF(tmp); - } - - return 0; -} - - -static PyMemberDef Noddy_members[] = { - {"first", T_OBJECT_EX, offsetof(Noddy, first), 0, - "first name"}, - {"last", T_OBJECT_EX, offsetof(Noddy, last), 0, - "last name"}, - {"number", T_INT, offsetof(Noddy, number), 0, - "noddy number"}, - {NULL} /* Sentinel */ -}; - -static PyObject * -Noddy_name(Noddy* self) -{ - if (self->first == NULL) { - PyErr_SetString(PyExc_AttributeError, "first"); - return NULL; - } - - if (self->last == NULL) { - PyErr_SetString(PyExc_AttributeError, "last"); - return NULL; - } - - return PyUnicode_FromFormat("%S %S", self->first, self->last); -} - -static PyMethodDef Noddy_methods[] = { - {"name", (PyCFunction)Noddy_name, METH_NOARGS, - "Return the name, combining the first and last name" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject NoddyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "noddy.Noddy", /* tp_name */ - sizeof(Noddy), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Noddy_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - "Noddy objects", /* tp_doc */ - (traverseproc)Noddy_traverse, /* tp_traverse */ - (inquiry)Noddy_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Noddy_methods, /* tp_methods */ - Noddy_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Noddy_init, /* tp_init */ - 0, /* tp_alloc */ - Noddy_new, /* tp_new */ -}; - -static PyModuleDef noddy4module = { - PyModuleDef_HEAD_INIT, - "noddy4", - "Example module that creates an extension type.", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC -PyInit_noddy4(void) -{ - PyObject* m; - - if (PyType_Ready(&NoddyType) < 0) - return NULL; - - m = PyModule_Create(&noddy4module); - if (m == NULL) - return NULL; - - Py_INCREF(&NoddyType); - PyModule_AddObject(m, "Noddy", (PyObject *)&NoddyType); - return m; -} diff --git a/Doc/includes/shoddy.c b/Doc/includes/shoddy.c deleted file mode 100644 index 0ef4765..0000000 --- a/Doc/includes/shoddy.c +++ /dev/null @@ -1,99 +0,0 @@ -#include <Python.h> - -typedef struct { - PyListObject list; - int state; -} Shoddy; - - -static PyObject * -Shoddy_increment(Shoddy *self, PyObject *unused) -{ - self->state++; - return PyLong_FromLong(self->state); -} - - -static PyMethodDef Shoddy_methods[] = { - {"increment", (PyCFunction)Shoddy_increment, METH_NOARGS, - PyDoc_STR("increment state counter")}, - {NULL}, -}; - -static int -Shoddy_init(Shoddy *self, PyObject *args, PyObject *kwds) -{ - if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0) - return -1; - self->state = 0; - return 0; -} - - -static PyTypeObject ShoddyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "shoddy.Shoddy", /* tp_name */ - sizeof(Shoddy), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Shoddy_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Shoddy_init, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -static PyModuleDef shoddymodule = { - PyModuleDef_HEAD_INIT, - "shoddy", - "Shoddy module", - -1, - NULL, NULL, NULL, NULL, NULL -}; - -PyMODINIT_FUNC -PyInit_shoddy(void) -{ - PyObject *m; - - ShoddyType.tp_base = &PyList_Type; - if (PyType_Ready(&ShoddyType) < 0) - return NULL; - - m = PyModule_Create(&shoddymodule); - if (m == NULL) - return NULL; - - Py_INCREF(&ShoddyType); - PyModule_AddObject(m, "Shoddy", (PyObject *) &ShoddyType); - return m; -} diff --git a/Doc/includes/sublist.c b/Doc/includes/sublist.c new file mode 100644 index 0000000..376dddf --- /dev/null +++ b/Doc/includes/sublist.c @@ -0,0 +1,63 @@ +#include <Python.h> + +typedef struct { + PyListObject list; + int state; +} SubListObject; + +static PyObject * +SubList_increment(SubListObject *self, PyObject *unused) +{ + self->state++; + return PyLong_FromLong(self->state); +} + +static PyMethodDef SubList_methods[] = { + {"increment", (PyCFunction) SubList_increment, METH_NOARGS, + PyDoc_STR("increment state counter")}, + {NULL}, +}; + +static int +SubList_init(SubListObject *self, PyObject *args, PyObject *kwds) +{ + if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0) + return -1; + self->state = 0; + return 0; +} + +static PyTypeObject SubListType = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "sublist.SubList", + .tp_doc = "SubList objects", + .tp_basicsize = sizeof(SubListObject), + .tp_itemsize = 0, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_init = (initproc) SubList_init, + .tp_methods = SubList_methods, +}; + +static PyModuleDef sublistmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "sublist", + .m_doc = "Example module that creates an extension type.", + .m_size = -1, +}; + +PyMODINIT_FUNC +PyInit_sublist(void) +{ + PyObject *m; + SubListType.tp_base = &PyList_Type; + if (PyType_Ready(&SubListType) < 0) + return NULL; + + m = PyModule_Create(&sublistmodule); + if (m == NULL) + return NULL; + + Py_INCREF(&SubListType); + PyModule_AddObject(m, "SubList", (PyObject *) &SubListType); + return m; +} diff --git a/Doc/includes/test.py b/Doc/includes/test.py index 9e9d4a6..09ebe3f 100644 --- a/Doc/includes/test.py +++ b/Doc/includes/test.py @@ -1,181 +1,168 @@ -"""Test module for the noddy examples +"""Test module for the custom examples -Noddy 1: +Custom 1: ->>> import noddy ->>> n1 = noddy.Noddy() ->>> n2 = noddy.Noddy() ->>> del n1 ->>> del n2 +>>> import custom +>>> c1 = custom.Custom() +>>> c2 = custom.Custom() +>>> del c1 +>>> del c2 -Noddy 2 +Custom 2 ->>> import noddy2 ->>> n1 = noddy2.Noddy('jim', 'fulton', 42) ->>> n1.first +>>> import custom2 +>>> c1 = custom2.Custom('jim', 'fulton', 42) +>>> c1.first 'jim' ->>> n1.last +>>> c1.last 'fulton' ->>> n1.number +>>> c1.number 42 ->>> n1.name() +>>> c1.name() 'jim fulton' ->>> n1.first = 'will' ->>> n1.name() +>>> c1.first = 'will' +>>> c1.name() 'will fulton' ->>> n1.last = 'tell' ->>> n1.name() +>>> c1.last = 'tell' +>>> c1.name() 'will tell' ->>> del n1.first ->>> n1.name() +>>> del c1.first +>>> c1.name() Traceback (most recent call last): ... AttributeError: first ->>> n1.first +>>> c1.first Traceback (most recent call last): ... AttributeError: first ->>> n1.first = 'drew' ->>> n1.first +>>> c1.first = 'drew' +>>> c1.first 'drew' ->>> del n1.number +>>> del c1.number Traceback (most recent call last): ... TypeError: can't delete numeric/char attribute ->>> n1.number=2 ->>> n1.number +>>> c1.number=2 +>>> c1.number 2 ->>> n1.first = 42 ->>> n1.name() +>>> c1.first = 42 +>>> c1.name() '42 tell' ->>> n2 = noddy2.Noddy() ->>> n2.name() +>>> c2 = custom2.Custom() +>>> c2.name() ' ' ->>> n2.first +>>> c2.first '' ->>> n2.last +>>> c2.last '' ->>> del n2.first ->>> n2.first +>>> del c2.first +>>> c2.first Traceback (most recent call last): ... AttributeError: first ->>> n2.first +>>> c2.first Traceback (most recent call last): ... AttributeError: first ->>> n2.name() +>>> c2.name() Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: first ->>> n2.number +>>> c2.number 0 ->>> n3 = noddy2.Noddy('jim', 'fulton', 'waaa') +>>> n3 = custom2.Custom('jim', 'fulton', 'waaa') Traceback (most recent call last): File "<stdin>", line 1, in ? -TypeError: an integer is required ->>> del n1 ->>> del n2 +TypeError: an integer is required (got type str) +>>> del c1 +>>> del c2 -Noddy 3 +Custom 3 ->>> import noddy3 ->>> n1 = noddy3.Noddy('jim', 'fulton', 42) ->>> n1 = noddy3.Noddy('jim', 'fulton', 42) ->>> n1.name() +>>> import custom3 +>>> c1 = custom3.Custom('jim', 'fulton', 42) +>>> c1 = custom3.Custom('jim', 'fulton', 42) +>>> c1.name() 'jim fulton' ->>> del n1.first +>>> del c1.first Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Cannot delete the first attribute ->>> n1.first = 42 +>>> c1.first = 42 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: The first attribute value must be a string ->>> n1.first = 'will' ->>> n1.name() +>>> c1.first = 'will' +>>> c1.name() 'will fulton' ->>> n2 = noddy3.Noddy() ->>> n2 = noddy3.Noddy() ->>> n2 = noddy3.Noddy() ->>> n3 = noddy3.Noddy('jim', 'fulton', 'waaa') +>>> c2 = custom3.Custom() +>>> c2 = custom3.Custom() +>>> c2 = custom3.Custom() +>>> n3 = custom3.Custom('jim', 'fulton', 'waaa') Traceback (most recent call last): File "<stdin>", line 1, in ? -TypeError: an integer is required ->>> del n1 ->>> del n2 +TypeError: an integer is required (got type str) +>>> del c1 +>>> del c2 -Noddy 4 +Custom 4 ->>> import noddy4 ->>> n1 = noddy4.Noddy('jim', 'fulton', 42) ->>> n1.first +>>> import custom4 +>>> c1 = custom4.Custom('jim', 'fulton', 42) +>>> c1.first 'jim' ->>> n1.last +>>> c1.last 'fulton' ->>> n1.number +>>> c1.number 42 ->>> n1.name() +>>> c1.name() 'jim fulton' ->>> n1.first = 'will' ->>> n1.name() +>>> c1.first = 'will' +>>> c1.name() 'will fulton' ->>> n1.last = 'tell' ->>> n1.name() +>>> c1.last = 'tell' +>>> c1.name() 'will tell' ->>> del n1.first ->>> n1.name() +>>> del c1.first Traceback (most recent call last): ... -AttributeError: first ->>> n1.first -Traceback (most recent call last): -... -AttributeError: first ->>> n1.first = 'drew' ->>> n1.first +TypeError: Cannot delete the first attribute +>>> c1.name() +'will tell' +>>> c1.first = 'drew' +>>> c1.first 'drew' ->>> del n1.number +>>> del c1.number Traceback (most recent call last): ... TypeError: can't delete numeric/char attribute ->>> n1.number=2 ->>> n1.number +>>> c1.number=2 +>>> c1.number 2 ->>> n1.first = 42 ->>> n1.name() -'42 tell' ->>> n2 = noddy4.Noddy() ->>> n2 = noddy4.Noddy() ->>> n2 = noddy4.Noddy() ->>> n2 = noddy4.Noddy() ->>> n2.name() +>>> c1.first = 42 +Traceback (most recent call last): +... +TypeError: The first attribute value must be a string +>>> c1.name() +'drew tell' +>>> c2 = custom4.Custom() +>>> c2 = custom4.Custom() +>>> c2 = custom4.Custom() +>>> c2 = custom4.Custom() +>>> c2.name() ' ' ->>> n2.first +>>> c2.first '' ->>> n2.last +>>> c2.last '' ->>> del n2.first ->>> n2.first -Traceback (most recent call last): -... -AttributeError: first ->>> n2.first -Traceback (most recent call last): -... -AttributeError: first ->>> n2.name() -Traceback (most recent call last): - File "<stdin>", line 1, in ? -AttributeError: first ->>> n2.number +>>> c2.number 0 ->>> n3 = noddy4.Noddy('jim', 'fulton', 'waaa') +>>> n3 = custom4.Custom('jim', 'fulton', 'waaa') Traceback (most recent call last): - File "<stdin>", line 1, in ? -TypeError: an integer is required +... +TypeError: an integer is required (got type str) Test cyclic gc(?) @@ -183,15 +170,14 @@ Test cyclic gc(?) >>> import gc >>> gc.disable() ->>> x = [] ->>> l = [x] ->>> n2.first = l ->>> n2.first -[[]] ->>> l.append(n2) ->>> del l ->>> del n1 ->>> del n2 +>>> class Subclass(custom4.Custom): pass +... +>>> s = Subclass() +>>> s.cycle = [s] +>>> s.cycle.append(s.cycle) +>>> x = object() +>>> s.x = x +>>> del s >>> sys.getrefcount(x) 3 >>> ignore = gc.collect() |