From e97b7bef4fbe71821d59d2f41f311e514fd29e39 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Tue, 22 Aug 2023 19:42:51 +0100
Subject: GH-92584: Remove distutils from the newtypes tutorial includes
(#108024)
---
Doc/extending/newtypes_tutorial.rst | 54 +++++-----
Doc/includes/custom.c | 43 --------
Doc/includes/custom2.c | 130 -----------------------
Doc/includes/custom3.c | 171 ------------------------------
Doc/includes/custom4.c | 189 ---------------------------------
Doc/includes/newtypes/custom.c | 43 ++++++++
Doc/includes/newtypes/custom2.c | 130 +++++++++++++++++++++++
Doc/includes/newtypes/custom3.c | 171 ++++++++++++++++++++++++++++++
Doc/includes/newtypes/custom4.c | 189 +++++++++++++++++++++++++++++++++
Doc/includes/newtypes/pyproject.toml | 7 ++
Doc/includes/newtypes/setup.py | 8 ++
Doc/includes/newtypes/sublist.c | 67 ++++++++++++
Doc/includes/newtypes/test.py | 192 +++++++++++++++++++++++++++++++++
Doc/includes/setup.py | 9 --
Doc/includes/sublist.c | 67 ------------
Doc/includes/test.py | 199 -----------------------------------
16 files changed, 834 insertions(+), 835 deletions(-)
delete mode 100644 Doc/includes/custom.c
delete mode 100644 Doc/includes/custom2.c
delete mode 100644 Doc/includes/custom3.c
delete mode 100644 Doc/includes/custom4.c
create mode 100644 Doc/includes/newtypes/custom.c
create mode 100644 Doc/includes/newtypes/custom2.c
create mode 100644 Doc/includes/newtypes/custom3.c
create mode 100644 Doc/includes/newtypes/custom4.c
create mode 100644 Doc/includes/newtypes/pyproject.toml
create mode 100644 Doc/includes/newtypes/setup.py
create mode 100644 Doc/includes/newtypes/sublist.c
create mode 100644 Doc/includes/newtypes/test.py
delete mode 100644 Doc/includes/setup.py
delete mode 100644 Doc/includes/sublist.c
delete mode 100644 Doc/includes/test.py
diff --git a/Doc/extending/newtypes_tutorial.rst b/Doc/extending/newtypes_tutorial.rst
index 209a4ab..7eba975 100644
--- a/Doc/extending/newtypes_tutorial.rst
+++ b/Doc/extending/newtypes_tutorial.rst
@@ -45,7 +45,7 @@ extension module :mod:`!custom`:
allows defining heap-allocated extension types using the
:c:func:`PyType_FromSpec` function, which isn't covered in this tutorial.
-.. literalinclude:: ../includes/custom.c
+.. literalinclude:: ../includes/newtypes/custom.c
Now that's quite a bit to take in at once, but hopefully bits will seem familiar
from the previous chapter. This file defines three things:
@@ -194,36 +194,32 @@ This adds the type to the module dictionary. This allows us to create
>>> mycustom = custom.Custom()
That's it! All that remains is to build it; put the above code in a file called
-:file:`custom.c` and:
+:file:`custom.c`,
+
+.. literalinclude:: ../includes/newtypes/pyproject.toml
+
+in a file called :file:`pyproject.toml`, and
.. code-block:: python
- from distutils.core import setup, Extension
- setup(name="custom", version="1.0",
- ext_modules=[Extension("custom", ["custom.c"])])
+ from setuptools import Extension, setup
+ setup(ext_modules=[Extension("custom", ["custom.c"])])
in a file called :file:`setup.py`; then typing
.. code-block:: shell-session
- $ python setup.py build
+ $ python -m pip install .
-at a shell should produce a file :file:`custom.so` in a subdirectory; move to
-that directory and fire up Python --- you should be able to ``import custom`` and
-play around with Custom objects.
+in a shell should produce a file :file:`custom.so` in a subdirectory
+and install it; now fire up Python --- you should be able to ``import custom``
+and play around with ``Custom`` objects.
That wasn't so hard, was it?
Of course, the current Custom type is pretty uninteresting. It has no data and
doesn't do anything. It can't even be subclassed.
-.. note::
- While this documentation showcases the standard :mod:`!distutils` module
- for building C extensions, it is recommended in real-world use cases to
- use the newer and better-maintained ``setuptools`` library. Documentation
- on how to do this is out of scope for this document and can be found in
- the `Python Packaging User's Guide `_.
-
Adding data and methods to the Basic example
============================================
@@ -232,7 +228,7 @@ Let's extend the basic example to add some data and methods. Let's also make
the type usable as a base class. We'll create a new module, :mod:`!custom2` that
adds these capabilities:
-.. literalinclude:: ../includes/custom2.c
+.. literalinclude:: ../includes/newtypes/custom2.c
This version of the module has a number of changes.
@@ -514,17 +510,21 @@ We rename :c:func:`!PyInit_custom` to :c:func:`!PyInit_custom2`, update the
module name in the :c:type:`PyModuleDef` struct, and update the full class
name in the :c:type:`PyTypeObject` struct.
-Finally, we update our :file:`setup.py` file to build the new module:
+Finally, we update our :file:`setup.py` file to include the new module,
.. code-block:: python
- from distutils.core import setup, Extension
- setup(name="custom", version="1.0",
- ext_modules=[
- Extension("custom", ["custom.c"]),
- Extension("custom2", ["custom2.c"]),
- ])
+ from setuptools import Extension, setup
+ setup(ext_modules=[
+ Extension("custom", ["custom.c"]),
+ Extension("custom2", ["custom2.c"]),
+ ])
+
+and then we re-install so that we can ``import custom2``:
+
+.. code-block:: shell-session
+ $ python -m pip install .
Providing finer control over data attributes
============================================
@@ -535,7 +535,7 @@ version of our module, the instance variables :attr:`!first` and :attr:`!last`
could be set to non-string values or even deleted. We want to make sure that
these attributes always contain strings.
-.. literalinclude:: ../includes/custom3.c
+.. literalinclude:: ../includes/newtypes/custom3.c
To provide greater control, over the :attr:`!first` and :attr:`!last` attributes,
@@ -682,7 +682,7 @@ To allow a :class:`!Custom` instance participating in a reference cycle to
be properly detected and collected by the cyclic GC, our :class:`!Custom` type
needs to fill two additional slots and to enable a flag that enables these slots:
-.. literalinclude:: ../includes/custom4.c
+.. literalinclude:: ../includes/newtypes/custom4.c
First, the traversal method lets the cyclic GC know about subobjects that could
@@ -806,7 +806,7 @@ increases an internal counter:
>>> print(s.increment())
2
-.. literalinclude:: ../includes/sublist.c
+.. literalinclude:: ../includes/newtypes/sublist.c
As you can see, the source code closely resembles the :class:`!Custom` examples in
diff --git a/Doc/includes/custom.c b/Doc/includes/custom.c
deleted file mode 100644
index 5253f87..0000000
--- a/Doc/includes/custom.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include
-
-typedef struct {
- PyObject_HEAD
- /* Type-specific fields go here. */
-} CustomObject;
-
-static PyTypeObject CustomType = {
- .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "custom.Custom",
- .tp_doc = PyDoc_STR("Custom objects"),
- .tp_basicsize = sizeof(CustomObject),
- .tp_itemsize = 0,
- .tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_new = PyType_GenericNew,
-};
-
-static PyModuleDef custommodule = {
- .m_base = 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;
-
- if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
diff --git a/Doc/includes/custom2.c b/Doc/includes/custom2.c
deleted file mode 100644
index a0222b1..0000000
--- a/Doc/includes/custom2.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include
-#include /* for offsetof() */
-
-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;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
- &first, &last,
- &self->number))
- return -1;
-
- if (first) {
- Py_XSETREF(self->first, Py_NewRef(first));
- }
- if (last) {
- Py_XSETREF(self->last, Py_NewRef(last));
- }
- return 0;
-}
-
-static PyMemberDef Custom_members[] = {
- {"first", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,
- "first name"},
- {"last", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,
- "last name"},
- {"number", Py_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 = {
- .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "custom2.Custom",
- .tp_doc = PyDoc_STR("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 = {
- .m_base =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;
-
- if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
diff --git a/Doc/includes/custom3.c b/Doc/includes/custom3.c
deleted file mode 100644
index 4aeebe0..0000000
--- a/Doc/includes/custom3.c
+++ /dev/null
@@ -1,171 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include
-#include /* for offsetof() */
-
-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;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
- &first, &last,
- &self->number))
- return -1;
-
- if (first) {
- Py_SETREF(self->first, Py_NewRef(first));
- }
- if (last) {
- Py_SETREF(self->last, Py_NewRef(last));
- }
- return 0;
-}
-
-static PyMemberDef Custom_members[] = {
- {"number", Py_T_INT, offsetof(CustomObject, number), 0,
- "custom number"},
- {NULL} /* Sentinel */
-};
-
-static PyObject *
-Custom_getfirst(CustomObject *self, void *closure)
-{
- return Py_NewRef(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_SETREF(self->first, Py_NewRef(value));
- return 0;
-}
-
-static PyObject *
-Custom_getlast(CustomObject *self, void *closure)
-{
- return Py_NewRef(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_SETREF(self->last, Py_NewRef(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 = {
- .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "custom3.Custom",
- .tp_doc = PyDoc_STR("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 = {
- .m_base = 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;
-
- if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
diff --git a/Doc/includes/custom4.c b/Doc/includes/custom4.c
deleted file mode 100644
index 3998918..0000000
--- a/Doc/includes/custom4.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include
-#include /* for offsetof() */
-
-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;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
- &first, &last,
- &self->number))
- return -1;
-
- if (first) {
- Py_SETREF(self->first, Py_NewRef(first));
- }
- if (last) {
- Py_SETREF(self->last, Py_NewRef(last));
- }
- return 0;
-}
-
-static PyMemberDef Custom_members[] = {
- {"number", Py_T_INT, offsetof(CustomObject, number), 0,
- "custom number"},
- {NULL} /* Sentinel */
-};
-
-static PyObject *
-Custom_getfirst(CustomObject *self, void *closure)
-{
- return Py_NewRef(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_XSETREF(self->first, Py_NewRef(value));
- return 0;
-}
-
-static PyObject *
-Custom_getlast(CustomObject *self, void *closure)
-{
- return Py_NewRef(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_XSETREF(self->last, Py_NewRef(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 = {
- .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "custom4.Custom",
- .tp_doc = PyDoc_STR("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 = {
- .m_base = 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;
-
- if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
diff --git a/Doc/includes/newtypes/custom.c b/Doc/includes/newtypes/custom.c
new file mode 100644
index 0000000..5253f87
--- /dev/null
+++ b/Doc/includes/newtypes/custom.c
@@ -0,0 +1,43 @@
+#define PY_SSIZE_T_CLEAN
+#include
+
+typedef struct {
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+} CustomObject;
+
+static PyTypeObject CustomType = {
+ .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "custom.Custom",
+ .tp_doc = PyDoc_STR("Custom objects"),
+ .tp_basicsize = sizeof(CustomObject),
+ .tp_itemsize = 0,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_new = PyType_GenericNew,
+};
+
+static PyModuleDef custommodule = {
+ .m_base = 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;
+
+ if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
+ return m;
+}
diff --git a/Doc/includes/newtypes/custom2.c b/Doc/includes/newtypes/custom2.c
new file mode 100644
index 0000000..a0222b1
--- /dev/null
+++ b/Doc/includes/newtypes/custom2.c
@@ -0,0 +1,130 @@
+#define PY_SSIZE_T_CLEAN
+#include
+#include /* for offsetof() */
+
+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;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist,
+ &first, &last,
+ &self->number))
+ return -1;
+
+ if (first) {
+ Py_XSETREF(self->first, Py_NewRef(first));
+ }
+ if (last) {
+ Py_XSETREF(self->last, Py_NewRef(last));
+ }
+ return 0;
+}
+
+static PyMemberDef Custom_members[] = {
+ {"first", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,
+ "first name"},
+ {"last", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,
+ "last name"},
+ {"number", Py_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 = {
+ .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "custom2.Custom",
+ .tp_doc = PyDoc_STR("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 = {
+ .m_base =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;
+
+ if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
+ return m;
+}
diff --git a/Doc/includes/newtypes/custom3.c b/Doc/includes/newtypes/custom3.c
new file mode 100644
index 0000000..4aeebe0
--- /dev/null
+++ b/Doc/includes/newtypes/custom3.c
@@ -0,0 +1,171 @@
+#define PY_SSIZE_T_CLEAN
+#include
+#include /* for offsetof() */
+
+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;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
+ &first, &last,
+ &self->number))
+ return -1;
+
+ if (first) {
+ Py_SETREF(self->first, Py_NewRef(first));
+ }
+ if (last) {
+ Py_SETREF(self->last, Py_NewRef(last));
+ }
+ return 0;
+}
+
+static PyMemberDef Custom_members[] = {
+ {"number", Py_T_INT, offsetof(CustomObject, number), 0,
+ "custom number"},
+ {NULL} /* Sentinel */
+};
+
+static PyObject *
+Custom_getfirst(CustomObject *self, void *closure)
+{
+ return Py_NewRef(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_SETREF(self->first, Py_NewRef(value));
+ return 0;
+}
+
+static PyObject *
+Custom_getlast(CustomObject *self, void *closure)
+{
+ return Py_NewRef(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_SETREF(self->last, Py_NewRef(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 = {
+ .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "custom3.Custom",
+ .tp_doc = PyDoc_STR("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 = {
+ .m_base = 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;
+
+ if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
+ return m;
+}
diff --git a/Doc/includes/newtypes/custom4.c b/Doc/includes/newtypes/custom4.c
new file mode 100644
index 0000000..3998918
--- /dev/null
+++ b/Doc/includes/newtypes/custom4.c
@@ -0,0 +1,189 @@
+#define PY_SSIZE_T_CLEAN
+#include
+#include /* for offsetof() */
+
+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;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist,
+ &first, &last,
+ &self->number))
+ return -1;
+
+ if (first) {
+ Py_SETREF(self->first, Py_NewRef(first));
+ }
+ if (last) {
+ Py_SETREF(self->last, Py_NewRef(last));
+ }
+ return 0;
+}
+
+static PyMemberDef Custom_members[] = {
+ {"number", Py_T_INT, offsetof(CustomObject, number), 0,
+ "custom number"},
+ {NULL} /* Sentinel */
+};
+
+static PyObject *
+Custom_getfirst(CustomObject *self, void *closure)
+{
+ return Py_NewRef(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_XSETREF(self->first, Py_NewRef(value));
+ return 0;
+}
+
+static PyObject *
+Custom_getlast(CustomObject *self, void *closure)
+{
+ return Py_NewRef(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_XSETREF(self->last, Py_NewRef(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 = {
+ .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "custom4.Custom",
+ .tp_doc = PyDoc_STR("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 = {
+ .m_base = 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;
+
+ if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
+ return m;
+}
diff --git a/Doc/includes/newtypes/pyproject.toml b/Doc/includes/newtypes/pyproject.toml
new file mode 100644
index 0000000..ea7937a
--- /dev/null
+++ b/Doc/includes/newtypes/pyproject.toml
@@ -0,0 +1,7 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "custom"
+version = "1"
diff --git a/Doc/includes/newtypes/setup.py b/Doc/includes/newtypes/setup.py
new file mode 100644
index 0000000..67f8367
--- /dev/null
+++ b/Doc/includes/newtypes/setup.py
@@ -0,0 +1,8 @@
+from setuptools import Extension, setup
+setup(ext_modules=[
+ Extension("custom", ["custom.c"]),
+ Extension("custom2", ["custom2.c"]),
+ Extension("custom3", ["custom3.c"]),
+ Extension("custom4", ["custom4.c"]),
+ Extension("sublist", ["sublist.c"]),
+])
diff --git a/Doc/includes/newtypes/sublist.c b/Doc/includes/newtypes/sublist.c
new file mode 100644
index 0000000..d8aba46
--- /dev/null
+++ b/Doc/includes/newtypes/sublist.c
@@ -0,0 +1,67 @@
+#define PY_SSIZE_T_CLEAN
+#include
+
+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 = PyDoc_STR("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;
+
+ if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
+ return m;
+}
diff --git a/Doc/includes/newtypes/test.py b/Doc/includes/newtypes/test.py
new file mode 100644
index 0000000..55a5cf9
--- /dev/null
+++ b/Doc/includes/newtypes/test.py
@@ -0,0 +1,192 @@
+"""Test module for the custom examples
+
+Custom 1:
+
+>>> import custom
+>>> c1 = custom.Custom()
+>>> c2 = custom.Custom()
+>>> del c1
+>>> del c2
+
+
+Custom 2
+
+>>> import custom2
+>>> c1 = custom2.Custom('jim', 'fulton', 42)
+>>> c1.first
+'jim'
+>>> c1.last
+'fulton'
+>>> c1.number
+42
+>>> c1.name()
+'jim fulton'
+>>> c1.first = 'will'
+>>> c1.name()
+'will fulton'
+>>> c1.last = 'tell'
+>>> c1.name()
+'will tell'
+>>> del c1.first
+>>> c1.name()
+Traceback (most recent call last):
+...
+AttributeError: first
+>>> c1.first
+Traceback (most recent call last):
+...
+AttributeError: first
+>>> c1.first = 'drew'
+>>> c1.first
+'drew'
+>>> del c1.number
+Traceback (most recent call last):
+...
+TypeError: can't delete numeric/char attribute
+>>> c1.number=2
+>>> c1.number
+2
+>>> c1.first = 42
+>>> c1.name()
+'42 tell'
+>>> c2 = custom2.Custom()
+>>> c2.name()
+' '
+>>> c2.first
+''
+>>> c2.last
+''
+>>> del c2.first
+>>> c2.first
+Traceback (most recent call last):
+...
+AttributeError: first
+>>> c2.first
+Traceback (most recent call last):
+...
+AttributeError: first
+>>> c2.name()
+Traceback (most recent call last):
+ File "", line 1, in ?
+AttributeError: first
+>>> c2.number
+0
+>>> n3 = custom2.Custom('jim', 'fulton', 'waaa')
+Traceback (most recent call last):
+ File "", line 1, in ?
+TypeError: an integer is required (got type str)
+>>> del c1
+>>> del c2
+
+
+Custom 3
+
+>>> import custom3
+>>> c1 = custom3.Custom('jim', 'fulton', 42)
+>>> c1 = custom3.Custom('jim', 'fulton', 42)
+>>> c1.name()
+'jim fulton'
+>>> del c1.first
+Traceback (most recent call last):
+ File "", line 1, in ?
+TypeError: Cannot delete the first attribute
+>>> c1.first = 42
+Traceback (most recent call last):
+ File "", line 1, in ?
+TypeError: The first attribute value must be a string
+>>> c1.first = 'will'
+>>> c1.name()
+'will fulton'
+>>> c2 = custom3.Custom()
+>>> c2 = custom3.Custom()
+>>> c2 = custom3.Custom()
+>>> n3 = custom3.Custom('jim', 'fulton', 'waaa')
+Traceback (most recent call last):
+ File "", line 1, in ?
+TypeError: an integer is required (got type str)
+>>> del c1
+>>> del c2
+
+Custom 4
+
+>>> import custom4
+>>> c1 = custom4.Custom('jim', 'fulton', 42)
+>>> c1.first
+'jim'
+>>> c1.last
+'fulton'
+>>> c1.number
+42
+>>> c1.name()
+'jim fulton'
+>>> c1.first = 'will'
+>>> c1.name()
+'will fulton'
+>>> c1.last = 'tell'
+>>> c1.name()
+'will tell'
+>>> del c1.first
+Traceback (most recent call last):
+...
+TypeError: Cannot delete the first attribute
+>>> c1.name()
+'will tell'
+>>> c1.first = 'drew'
+>>> c1.first
+'drew'
+>>> del c1.number
+Traceback (most recent call last):
+...
+TypeError: can't delete numeric/char attribute
+>>> c1.number=2
+>>> c1.number
+2
+>>> 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()
+' '
+>>> c2.first
+''
+>>> c2.last
+''
+>>> c2.number
+0
+>>> n3 = custom4.Custom('jim', 'fulton', 'waaa')
+Traceback (most recent call last):
+...
+TypeError: an integer is required (got type str)
+
+
+Test cyclic gc(?)
+
+>>> import gc
+>>> gc.disable()
+
+>>> 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()
+>>> sys.getrefcount(x)
+2
+
+>>> gc.enable()
+"""
+
+if __name__ == "__main__":
+ import doctest, __main__
+ doctest.testmod(__main__)
diff --git a/Doc/includes/setup.py b/Doc/includes/setup.py
deleted file mode 100644
index a38a39d..0000000
--- a/Doc/includes/setup.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from distutils.core import setup, Extension
-setup(name="noddy", version="1.0",
- ext_modules=[
- Extension("noddy", ["noddy.c"]),
- Extension("noddy2", ["noddy2.c"]),
- Extension("noddy3", ["noddy3.c"]),
- Extension("noddy4", ["noddy4.c"]),
- Extension("shoddy", ["shoddy.c"]),
- ])
diff --git a/Doc/includes/sublist.c b/Doc/includes/sublist.c
deleted file mode 100644
index d8aba46..0000000
--- a/Doc/includes/sublist.c
+++ /dev/null
@@ -1,67 +0,0 @@
-#define PY_SSIZE_T_CLEAN
-#include
-
-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 = PyDoc_STR("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;
-
- if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
- Py_DECREF(m);
- return NULL;
- }
-
- return m;
-}
diff --git a/Doc/includes/test.py b/Doc/includes/test.py
deleted file mode 100644
index 09ebe3f..0000000
--- a/Doc/includes/test.py
+++ /dev/null
@@ -1,199 +0,0 @@
-"""Test module for the custom examples
-
-Custom 1:
-
->>> import custom
->>> c1 = custom.Custom()
->>> c2 = custom.Custom()
->>> del c1
->>> del c2
-
-
-Custom 2
-
->>> import custom2
->>> c1 = custom2.Custom('jim', 'fulton', 42)
->>> c1.first
-'jim'
->>> c1.last
-'fulton'
->>> c1.number
-42
->>> c1.name()
-'jim fulton'
->>> c1.first = 'will'
->>> c1.name()
-'will fulton'
->>> c1.last = 'tell'
->>> c1.name()
-'will tell'
->>> del c1.first
->>> c1.name()
-Traceback (most recent call last):
-...
-AttributeError: first
->>> c1.first
-Traceback (most recent call last):
-...
-AttributeError: first
->>> c1.first = 'drew'
->>> c1.first
-'drew'
->>> del c1.number
-Traceback (most recent call last):
-...
-TypeError: can't delete numeric/char attribute
->>> c1.number=2
->>> c1.number
-2
->>> c1.first = 42
->>> c1.name()
-'42 tell'
->>> c2 = custom2.Custom()
->>> c2.name()
-' '
->>> c2.first
-''
->>> c2.last
-''
->>> del c2.first
->>> c2.first
-Traceback (most recent call last):
-...
-AttributeError: first
->>> c2.first
-Traceback (most recent call last):
-...
-AttributeError: first
->>> c2.name()
-Traceback (most recent call last):
- File "", line 1, in ?
-AttributeError: first
->>> c2.number
-0
->>> n3 = custom2.Custom('jim', 'fulton', 'waaa')
-Traceback (most recent call last):
- File "", line 1, in ?
-TypeError: an integer is required (got type str)
->>> del c1
->>> del c2
-
-
-Custom 3
-
->>> import custom3
->>> c1 = custom3.Custom('jim', 'fulton', 42)
->>> c1 = custom3.Custom('jim', 'fulton', 42)
->>> c1.name()
-'jim fulton'
->>> del c1.first
-Traceback (most recent call last):
- File "", line 1, in ?
-TypeError: Cannot delete the first attribute
->>> c1.first = 42
-Traceback (most recent call last):
- File "", line 1, in ?
-TypeError: The first attribute value must be a string
->>> c1.first = 'will'
->>> c1.name()
-'will fulton'
->>> c2 = custom3.Custom()
->>> c2 = custom3.Custom()
->>> c2 = custom3.Custom()
->>> n3 = custom3.Custom('jim', 'fulton', 'waaa')
-Traceback (most recent call last):
- File "", line 1, in ?
-TypeError: an integer is required (got type str)
->>> del c1
->>> del c2
-
-Custom 4
-
->>> import custom4
->>> c1 = custom4.Custom('jim', 'fulton', 42)
->>> c1.first
-'jim'
->>> c1.last
-'fulton'
->>> c1.number
-42
->>> c1.name()
-'jim fulton'
->>> c1.first = 'will'
->>> c1.name()
-'will fulton'
->>> c1.last = 'tell'
->>> c1.name()
-'will tell'
->>> del c1.first
-Traceback (most recent call last):
-...
-TypeError: Cannot delete the first attribute
->>> c1.name()
-'will tell'
->>> c1.first = 'drew'
->>> c1.first
-'drew'
->>> del c1.number
-Traceback (most recent call last):
-...
-TypeError: can't delete numeric/char attribute
->>> c1.number=2
->>> c1.number
-2
->>> 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()
-' '
->>> c2.first
-''
->>> c2.last
-''
->>> c2.number
-0
->>> n3 = custom4.Custom('jim', 'fulton', 'waaa')
-Traceback (most recent call last):
-...
-TypeError: an integer is required (got type str)
-
-
-Test cyclic gc(?)
-
->>> import gc
->>> gc.disable()
-
->>> 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()
->>> sys.getrefcount(x)
-2
-
->>> gc.enable()
-"""
-
-import os
-import sys
-from distutils.util import get_platform
-PLAT_SPEC = "%s-%d.%d" % (get_platform(), *sys.version_info[:2])
-src = os.path.join("build", "lib.%s" % PLAT_SPEC)
-sys.path.append(src)
-
-if __name__ == "__main__":
- import doctest, __main__
- doctest.testmod(__main__)
--
cgit v0.12