+++ /dev/null
-#include "Python.h"\r
-#include "structmember.h"\r
-\r
-PyDoc_STRVAR(xxsubtype__doc__,\r
-"xxsubtype is an example module showing how to subtype builtin types from C.\n"\r
-"test_descr.py in the standard test suite requires it in order to complete.\n"\r
-"If you don't care about the examples, and don't intend to run the Python\n"\r
-"test suite, you can recompile Python without Modules/xxsubtype.c.");\r
-\r
-/* We link this module statically for convenience. If compiled as a shared\r
- library instead, some compilers don't allow addresses of Python objects\r
- defined in other libraries to be used in static initializers here. The\r
- DEFERRED_ADDRESS macro is used to tag the slots where such addresses\r
- appear; the module init function must fill in the tagged slots at runtime.\r
- The argument is for documentation -- the macro ignores it.\r
-*/\r
-#define DEFERRED_ADDRESS(ADDR) 0\r
-\r
-/* spamlist -- a list subtype */\r
-\r
-typedef struct {\r
- PyListObject list;\r
- int state;\r
-} spamlistobject;\r
-\r
-static PyObject *\r
-spamlist_getstate(spamlistobject *self, PyObject *args)\r
-{\r
- if (!PyArg_ParseTuple(args, ":getstate"))\r
- return NULL;\r
- return PyInt_FromLong(self->state);\r
-}\r
-\r
-static PyObject *\r
-spamlist_setstate(spamlistobject *self, PyObject *args)\r
-{\r
- int state;\r
-\r
- if (!PyArg_ParseTuple(args, "i:setstate", &state))\r
- return NULL;\r
- self->state = state;\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-\r
-static PyObject *\r
-spamlist_specialmeth(PyObject *self, PyObject *args, PyObject *kw)\r
-{\r
- PyObject *result = PyTuple_New(3);\r
-\r
- if (result != NULL) {\r
- if (self == NULL)\r
- self = Py_None;\r
- if (kw == NULL)\r
- kw = Py_None;\r
- Py_INCREF(self);\r
- PyTuple_SET_ITEM(result, 0, self);\r
- Py_INCREF(args);\r
- PyTuple_SET_ITEM(result, 1, args);\r
- Py_INCREF(kw);\r
- PyTuple_SET_ITEM(result, 2, kw);\r
- }\r
- return result;\r
-}\r
-\r
-static PyMethodDef spamlist_methods[] = {\r
- {"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,\r
- PyDoc_STR("getstate() -> state")},\r
- {"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,\r
- PyDoc_STR("setstate(state)")},\r
- /* These entries differ only in the flags; they are used by the tests\r
- in test.test_descr. */\r
- {"classmeth", (PyCFunction)spamlist_specialmeth,\r
- METH_VARARGS | METH_KEYWORDS | METH_CLASS,\r
- PyDoc_STR("classmeth(*args, **kw)")},\r
- {"staticmeth", (PyCFunction)spamlist_specialmeth,\r
- METH_VARARGS | METH_KEYWORDS | METH_STATIC,\r
- PyDoc_STR("staticmeth(*args, **kw)")},\r
- {NULL, NULL},\r
-};\r
-\r
-static int\r
-spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)\r
-{\r
- if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)\r
- return -1;\r
- self->state = 0;\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-spamlist_state_get(spamlistobject *self)\r
-{\r
- return PyInt_FromLong(self->state);\r
-}\r
-\r
-static PyGetSetDef spamlist_getsets[] = {\r
- {"state", (getter)spamlist_state_get, NULL,\r
- PyDoc_STR("an int variable for demonstration purposes")},\r
- {0}\r
-};\r
-\r
-static PyTypeObject spamlist_type = {\r
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)\r
- "xxsubtype.spamlist",\r
- sizeof(spamlistobject),\r
- 0,\r
- 0, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- 0, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- 0, /* tp_doc */\r
- 0, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- 0, /* tp_iter */\r
- 0, /* tp_iternext */\r
- spamlist_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- spamlist_getsets, /* tp_getset */\r
- DEFERRED_ADDRESS(&PyList_Type), /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- (initproc)spamlist_init, /* tp_init */\r
- 0, /* tp_alloc */\r
- 0, /* tp_new */\r
-};\r
-\r
-/* spamdict -- a dict subtype */\r
-\r
-typedef struct {\r
- PyDictObject dict;\r
- int state;\r
-} spamdictobject;\r
-\r
-static PyObject *\r
-spamdict_getstate(spamdictobject *self, PyObject *args)\r
-{\r
- if (!PyArg_ParseTuple(args, ":getstate"))\r
- return NULL;\r
- return PyInt_FromLong(self->state);\r
-}\r
-\r
-static PyObject *\r
-spamdict_setstate(spamdictobject *self, PyObject *args)\r
-{\r
- int state;\r
-\r
- if (!PyArg_ParseTuple(args, "i:setstate", &state))\r
- return NULL;\r
- self->state = state;\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-\r
-static PyMethodDef spamdict_methods[] = {\r
- {"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,\r
- PyDoc_STR("getstate() -> state")},\r
- {"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,\r
- PyDoc_STR("setstate(state)")},\r
- {NULL, NULL},\r
-};\r
-\r
-static int\r
-spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)\r
-{\r
- if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)\r
- return -1;\r
- self->state = 0;\r
- return 0;\r
-}\r
-\r
-static PyMemberDef spamdict_members[] = {\r
- {"state", T_INT, offsetof(spamdictobject, state), READONLY,\r
- PyDoc_STR("an int variable for demonstration purposes")},\r
- {0}\r
-};\r
-\r
-static PyTypeObject spamdict_type = {\r
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)\r
- "xxsubtype.spamdict",\r
- sizeof(spamdictobject),\r
- 0,\r
- 0, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- 0, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- 0, /* tp_doc */\r
- 0, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- 0, /* tp_iter */\r
- 0, /* tp_iternext */\r
- spamdict_methods, /* tp_methods */\r
- spamdict_members, /* tp_members */\r
- 0, /* tp_getset */\r
- DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- (initproc)spamdict_init, /* tp_init */\r
- 0, /* tp_alloc */\r
- 0, /* tp_new */\r
-};\r
-\r
-static PyObject *\r
-spam_bench(PyObject *self, PyObject *args)\r
-{\r
- PyObject *obj, *name, *res;\r
- int n = 1000;\r
- time_t t0, t1;\r
-\r
- if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))\r
- return NULL;\r
- t0 = clock();\r
- while (--n >= 0) {\r
- res = PyObject_GetAttr(obj, name);\r
- if (res == NULL)\r
- return NULL;\r
- Py_DECREF(res);\r
- }\r
- t1 = clock();\r
- return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);\r
-}\r
-\r
-static PyMethodDef xxsubtype_functions[] = {\r
- {"bench", spam_bench, METH_VARARGS},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyMODINIT_FUNC\r
-initxxsubtype(void)\r
-{\r
- PyObject *m;\r
-\r
- /* Fill in deferred data addresses. This must be done before\r
- PyType_Ready() is called. Note that PyType_Ready() automatically\r
- initializes the ob.ob_type field to &PyType_Type if it's NULL,\r
- so it's not necessary to fill in ob_type first. */\r
- spamdict_type.tp_base = &PyDict_Type;\r
- if (PyType_Ready(&spamdict_type) < 0)\r
- return;\r
-\r
- spamlist_type.tp_base = &PyList_Type;\r
- if (PyType_Ready(&spamlist_type) < 0)\r
- return;\r
-\r
- m = Py_InitModule3("xxsubtype",\r
- xxsubtype_functions,\r
- xxsubtype__doc__);\r
- if (m == NULL)\r
- return;\r
-\r
- if (PyType_Ready(&spamlist_type) < 0)\r
- return;\r
- if (PyType_Ready(&spamdict_type) < 0)\r
- return;\r
-\r
- Py_INCREF(&spamlist_type);\r
- if (PyModule_AddObject(m, "spamlist",\r
- (PyObject *) &spamlist_type) < 0)\r
- return;\r
-\r
- Py_INCREF(&spamdict_type);\r
- if (PyModule_AddObject(m, "spamdict",\r
- (PyObject *) &spamdict_type) < 0)\r
- return;\r
-}\r