summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-10-19 15:00:51 (GMT)
committerGitHub <noreply@github.com>2018-10-19 15:00:51 (GMT)
commit55f8249d65af3f1b83df81fa46f6fc6e452ed944 (patch)
tree7b8f28fe7f6fc302105fe0683a9ad20ae826ec28 /Modules
parent6543912c90ffa579dc4c01e811f9609cf92197d3 (diff)
downloadcpython-55f8249d65af3f1b83df81fa46f6fc6e452ed944.zip
cpython-55f8249d65af3f1b83df81fa46f6fc6e452ed944.tar.gz
cpython-55f8249d65af3f1b83df81fa46f6fc6e452ed944.tar.bz2
bpo-34741: Get rid of tp_getattro and tp_setattro in pyexpat.xmlparser. (GH-9422)
Use tp_members and tp_getset instead.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/clinic/pyexpat.c.h19
-rw-r--r--Modules/pyexpat.c595
2 files changed, 269 insertions, 345 deletions
diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h
index 777b6f3..b7687e5 100644
--- a/Modules/clinic/pyexpat.c.h
+++ b/Modules/clinic/pyexpat.c.h
@@ -208,23 +208,6 @@ exit:
#endif /* (XML_COMBINED_VERSION >= 19505) */
-PyDoc_STRVAR(pyexpat_xmlparser___dir____doc__,
-"__dir__($self, /)\n"
-"--\n"
-"\n");
-
-#define PYEXPAT_XMLPARSER___DIR___METHODDEF \
- {"__dir__", (PyCFunction)pyexpat_xmlparser___dir__, METH_NOARGS, pyexpat_xmlparser___dir____doc__},
-
-static PyObject *
-pyexpat_xmlparser___dir___impl(xmlparseobject *self);
-
-static PyObject *
-pyexpat_xmlparser___dir__(xmlparseobject *self, PyObject *Py_UNUSED(ignored))
-{
- return pyexpat_xmlparser___dir___impl(self);
-}
-
PyDoc_STRVAR(pyexpat_ParserCreate__doc__,
"ParserCreate($module, /, encoding=None, namespace_separator=None,\n"
" intern=None)\n"
@@ -289,4 +272,4 @@ exit:
#ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */
-/*[clinic end generated code: output=34d02345deee104c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6bdf1faf8ba1af32 input=a9049054013a1b77]*/
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index ab3dac6..10d5aed 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -1,6 +1,7 @@
#include "Python.h"
#include <ctype.h>
+#include "structmember.h"
#include "frameobject.h"
#include "expat.h"
@@ -81,8 +82,7 @@ struct HandlerInfo {
const char *name;
xmlhandlersetter setter;
xmlhandler handler;
- PyCodeObject *tb_code;
- PyObject *nameobj;
+ PyGetSetDef getset;
};
static struct HandlerInfo handler_info[64];
@@ -138,19 +138,6 @@ have_handler(xmlparseobject *self, int type)
return handler != NULL;
}
-static PyObject *
-get_handler_name(struct HandlerInfo *hinfo)
-{
- PyObject *name = hinfo->nameobj;
- if (name == NULL) {
- name = PyUnicode_FromString(hinfo->name);
- hinfo->nameobj = name;
- }
- Py_XINCREF(name);
- return name;
-}
-
-
/* Convert a string of XML_Chars into a Unicode string.
Returns None if str is a null pointer. */
@@ -651,6 +638,7 @@ VOID_HANDLER(Default,
VOID_HANDLER(DefaultHandlerExpand,
(void *userData, const XML_Char *s, int len),
("(N)", (conv_string_len_to_unicode(s,len))))
+#define my_DefaultHandlerExpand my_DefaultHandlerExpandHandler
INT_HANDLER(NotStandalone,
(void *userData),
@@ -1036,57 +1024,6 @@ pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag)
}
#endif
-/*[clinic input]
-pyexpat.xmlparser.__dir__
-[clinic start generated code]*/
-
-static PyObject *
-pyexpat_xmlparser___dir___impl(xmlparseobject *self)
-/*[clinic end generated code: output=bc22451efb9e4d17 input=76aa455f2a661384]*/
-{
-#define APPEND(list, str) \
- do { \
- PyObject *o = PyUnicode_FromString(str); \
- if (o != NULL) \
- PyList_Append(list, o); \
- Py_XDECREF(o); \
- } while (0)
-
- int i;
- PyObject *rc = PyList_New(0);
- if (!rc)
- return NULL;
- for (i = 0; handler_info[i].name != NULL; i++) {
- PyObject *o = get_handler_name(&handler_info[i]);
- if (o != NULL)
- PyList_Append(rc, o);
- Py_XDECREF(o);
- }
- APPEND(rc, "ErrorCode");
- APPEND(rc, "ErrorLineNumber");
- APPEND(rc, "ErrorColumnNumber");
- APPEND(rc, "ErrorByteIndex");
- APPEND(rc, "CurrentLineNumber");
- APPEND(rc, "CurrentColumnNumber");
- APPEND(rc, "CurrentByteIndex");
- APPEND(rc, "buffer_size");
- APPEND(rc, "buffer_text");
- APPEND(rc, "buffer_used");
- APPEND(rc, "namespace_prefixes");
- APPEND(rc, "ordered_attributes");
- APPEND(rc, "specified_attributes");
- APPEND(rc, "intern");
-
-#undef APPEND
-
- if (PyErr_Occurred()) {
- Py_DECREF(rc);
- rc = NULL;
- }
-
- return rc;
-}
-
static struct PyMethodDef xmlparse_methods[] = {
PYEXPAT_XMLPARSER_PARSE_METHODDEF
PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF
@@ -1098,7 +1035,6 @@ static struct PyMethodDef xmlparse_methods[] = {
#if XML_COMBINED_VERSION >= 19505
PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#endif
- PYEXPAT_XMLPARSER___DIR___METHODDEF
{NULL, NULL} /* sentinel */
};
@@ -1238,221 +1174,153 @@ xmlparse_dealloc(xmlparseobject *self)
PyObject_GC_Del(self);
}
-static int
-handlername2int(PyObject *name)
-{
- int i;
- for (i = 0; handler_info[i].name != NULL; i++) {
- if (_PyUnicode_EqualToASCIIString(name, handler_info[i].name)) {
- return i;
- }
- }
- return -1;
-}
static PyObject *
-get_pybool(int istrue)
+xmlparse_handler_getter(xmlparseobject *self, struct HandlerInfo *hi)
{
- PyObject *result = istrue ? Py_True : Py_False;
+ int handlernum = hi - handler_info;
+ PyObject *result = self->handlers[handlernum];
+ if (result == NULL)
+ result = Py_None;
Py_INCREF(result);
return result;
}
-static PyObject *
-xmlparse_getattro(xmlparseobject *self, PyObject *nameobj)
+static int
+xmlparse_handler_setter(xmlparseobject *self, PyObject *v, struct HandlerInfo *hi)
{
- Py_UCS4 first_char;
- int handlernum = -1;
-
- if (!PyUnicode_Check(nameobj))
- goto generic;
- if (PyUnicode_READY(nameobj))
- return NULL;
+ int handlernum = hi - handler_info;
+ if (v == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
+ return -1;
+ }
+ if (handlernum == CharacterData) {
+ /* If we're changing the character data handler, flush all
+ * cached data with the old handler. Not sure there's a
+ * "right" thing to do, though, but this probably won't
+ * happen.
+ */
+ if (flush_character_buffer(self) < 0)
+ return -1;
+ }
- handlernum = handlername2int(nameobj);
+ xmlhandler c_handler = NULL;
+ if (v == Py_None) {
+ /* If this is the character data handler, and a character
+ data handler is already active, we need to be more
+ careful. What we can safely do is replace the existing
+ character data handler callback function with a no-op
+ function that will refuse to call Python. The downside
+ is that this doesn't completely remove the character
+ data handler from the C layer if there's any callback
+ active, so Expat does a little more work than it
+ otherwise would, but that's really an odd case. A more
+ elaborate system of handlers and state could remove the
+ C handler more effectively. */
+ if (handlernum == CharacterData && self->in_callback)
+ c_handler = noop_character_data_handler;
+ v = NULL;
+ }
+ else if (v != NULL) {
+ Py_INCREF(v);
+ c_handler = handler_info[handlernum].handler;
+ }
+ Py_XSETREF(self->handlers[handlernum], v);
+ handler_info[handlernum].setter(self->itself, c_handler);
+ return 0;
+}
- if (handlernum != -1) {
- PyObject *result = self->handlers[handlernum];
- if (result == NULL)
- result = Py_None;
- Py_INCREF(result);
- return result;
+#define INT_GETTER(name) \
+ static PyObject * \
+ xmlparse_##name##_getter(xmlparseobject *self, void *closure) \
+ { \
+ return PyLong_FromLong((long) XML_Get##name(self->itself)); \
}
+INT_GETTER(ErrorCode)
+INT_GETTER(ErrorLineNumber)
+INT_GETTER(ErrorColumnNumber)
+INT_GETTER(ErrorByteIndex)
+INT_GETTER(CurrentLineNumber)
+INT_GETTER(CurrentColumnNumber)
+INT_GETTER(CurrentByteIndex)
- first_char = PyUnicode_READ_CHAR(nameobj, 0);
- if (first_char == 'E') {
- if (_PyUnicode_EqualToASCIIString(nameobj, "ErrorCode"))
- return PyLong_FromLong((long)
- XML_GetErrorCode(self->itself));
- if (_PyUnicode_EqualToASCIIString(nameobj, "ErrorLineNumber"))
- return PyLong_FromLong((long)
- XML_GetErrorLineNumber(self->itself));
- if (_PyUnicode_EqualToASCIIString(nameobj, "ErrorColumnNumber"))
- return PyLong_FromLong((long)
- XML_GetErrorColumnNumber(self->itself));
- if (_PyUnicode_EqualToASCIIString(nameobj, "ErrorByteIndex"))
- return PyLong_FromLong((long)
- XML_GetErrorByteIndex(self->itself));
- }
- if (first_char == 'C') {
- if (_PyUnicode_EqualToASCIIString(nameobj, "CurrentLineNumber"))
- return PyLong_FromLong((long)
- XML_GetCurrentLineNumber(self->itself));
- if (_PyUnicode_EqualToASCIIString(nameobj, "CurrentColumnNumber"))
- return PyLong_FromLong((long)
- XML_GetCurrentColumnNumber(self->itself));
- if (_PyUnicode_EqualToASCIIString(nameobj, "CurrentByteIndex"))
- return PyLong_FromLong((long)
- XML_GetCurrentByteIndex(self->itself));
- }
- if (first_char == 'b') {
- if (_PyUnicode_EqualToASCIIString(nameobj, "buffer_size"))
- return PyLong_FromLong((long) self->buffer_size);
- if (_PyUnicode_EqualToASCIIString(nameobj, "buffer_text"))
- return get_pybool(self->buffer != NULL);
- if (_PyUnicode_EqualToASCIIString(nameobj, "buffer_used"))
- return PyLong_FromLong((long) self->buffer_used);
- }
- if (_PyUnicode_EqualToASCIIString(nameobj, "namespace_prefixes"))
- return get_pybool(self->ns_prefixes);
- if (_PyUnicode_EqualToASCIIString(nameobj, "ordered_attributes"))
- return get_pybool(self->ordered_attributes);
- if (_PyUnicode_EqualToASCIIString(nameobj, "specified_attributes"))
- return get_pybool((long) self->specified_attributes);
- if (_PyUnicode_EqualToASCIIString(nameobj, "intern")) {
- if (self->intern == NULL) {
- Py_RETURN_NONE;
- }
- else {
- Py_INCREF(self->intern);
- return self->intern;
- }
- }
- generic:
- return PyObject_GenericGetAttr((PyObject*)self, nameobj);
-}
+#undef INT_GETTER
-static int
-sethandler(xmlparseobject *self, PyObject *name, PyObject* v)
+static PyObject *
+xmlparse_buffer_text_getter(xmlparseobject *self, void *closure)
{
- int handlernum = handlername2int(name);
- if (handlernum >= 0) {
- xmlhandler c_handler = NULL;
-
- if (v == Py_None) {
- /* If this is the character data handler, and a character
- data handler is already active, we need to be more
- careful. What we can safely do is replace the existing
- character data handler callback function with a no-op
- function that will refuse to call Python. The downside
- is that this doesn't completely remove the character
- data handler from the C layer if there's any callback
- active, so Expat does a little more work than it
- otherwise would, but that's really an odd case. A more
- elaborate system of handlers and state could remove the
- C handler more effectively. */
- if (handlernum == CharacterData && self->in_callback)
- c_handler = noop_character_data_handler;
- v = NULL;
- }
- else if (v != NULL) {
- Py_INCREF(v);
- c_handler = handler_info[handlernum].handler;
- }
- Py_XSETREF(self->handlers[handlernum], v);
- handler_info[handlernum].setter(self->itself, c_handler);
- return 1;
- }
- return 0;
+ return PyBool_FromLong(self->buffer != NULL);
}
static int
-xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v)
+xmlparse_buffer_text_setter(xmlparseobject *self, PyObject *v, void *closure)
{
- /* Set attribute 'name' to value 'v'. v==NULL means delete */
- if (!PyUnicode_Check(name)) {
- PyErr_Format(PyExc_TypeError,
- "attribute name must be string, not '%.200s'",
- name->ob_type->tp_name);
- return -1;
- }
if (v == NULL) {
PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
return -1;
}
- if (_PyUnicode_EqualToASCIIString(name, "buffer_text")) {
- int b = PyObject_IsTrue(v);
- if (b < 0)
- return -1;
- if (b) {
+ int b = PyObject_IsTrue(v);
+ if (b < 0)
+ return -1;
+ if (b) {
+ if (self->buffer == NULL) {
+ self->buffer = PyMem_Malloc(self->buffer_size);
if (self->buffer == NULL) {
- self->buffer = PyMem_Malloc(self->buffer_size);
- if (self->buffer == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- self->buffer_used = 0;
- }
- }
- else if (self->buffer != NULL) {
- if (flush_character_buffer(self) < 0)
+ PyErr_NoMemory();
return -1;
- PyMem_Free(self->buffer);
- self->buffer = NULL;
+ }
+ self->buffer_used = 0;
}
- return 0;
- }
- if (_PyUnicode_EqualToASCIIString(name, "namespace_prefixes")) {
- int b = PyObject_IsTrue(v);
- if (b < 0)
- return -1;
- self->ns_prefixes = b;
- XML_SetReturnNSTriplet(self->itself, self->ns_prefixes);
- return 0;
}
- if (_PyUnicode_EqualToASCIIString(name, "ordered_attributes")) {
- int b = PyObject_IsTrue(v);
- if (b < 0)
- return -1;
- self->ordered_attributes = b;
- return 0;
- }
- if (_PyUnicode_EqualToASCIIString(name, "specified_attributes")) {
- int b = PyObject_IsTrue(v);
- if (b < 0)
+ else if (self->buffer != NULL) {
+ if (flush_character_buffer(self) < 0)
return -1;
- self->specified_attributes = b;
- return 0;
+ PyMem_Free(self->buffer);
+ self->buffer = NULL;
}
+ return 0;
+}
- if (_PyUnicode_EqualToASCIIString(name, "buffer_size")) {
- long new_buffer_size;
- if (!PyLong_Check(v)) {
+static PyObject *
+xmlparse_buffer_size_getter(xmlparseobject *self, void *closure)
+{
+ return PyLong_FromLong((long) self->buffer_size);
+}
+
+static int
+xmlparse_buffer_size_setter(xmlparseobject *self, PyObject *v, void *closure)
+{
+ if (v == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
+ return -1;
+ }
+ long new_buffer_size;
+ if (!PyLong_Check(v)) {
PyErr_SetString(PyExc_TypeError, "buffer_size must be an integer");
return -1;
- }
+ }
- new_buffer_size = PyLong_AsLong(v);
- if (new_buffer_size <= 0) {
+ new_buffer_size = PyLong_AsLong(v);
+ if (new_buffer_size <= 0) {
if (!PyErr_Occurred())
- PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero");
+ PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero");
return -1;
- }
+ }
- /* trivial case -- no change */
- if (new_buffer_size == self->buffer_size) {
+ /* trivial case -- no change */
+ if (new_buffer_size == self->buffer_size) {
return 0;
- }
+ }
- /* check maximum */
- if (new_buffer_size > INT_MAX) {
+ /* check maximum */
+ if (new_buffer_size > INT_MAX) {
char errmsg[100];
sprintf(errmsg, "buffer_size must not be greater than %i", INT_MAX);
PyErr_SetString(PyExc_ValueError, errmsg);
return -1;
- }
+ }
- if (self->buffer != NULL) {
+ if (self->buffer != NULL) {
/* there is already a buffer */
if (self->buffer_used != 0) {
if (flush_character_buffer(self) < 0) {
@@ -1461,32 +1329,114 @@ xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v)
}
/* free existing buffer */
PyMem_Free(self->buffer);
- }
- self->buffer = PyMem_Malloc(new_buffer_size);
- if (self->buffer == NULL) {
+ }
+ self->buffer = PyMem_Malloc(new_buffer_size);
+ if (self->buffer == NULL) {
PyErr_NoMemory();
return -1;
- }
- self->buffer_size = new_buffer_size;
- return 0;
}
+ self->buffer_size = new_buffer_size;
+ return 0;
+}
- if (_PyUnicode_EqualToASCIIString(name, "CharacterDataHandler")) {
- /* If we're changing the character data handler, flush all
- * cached data with the old handler. Not sure there's a
- * "right" thing to do, though, but this probably won't
- * happen.
- */
- if (flush_character_buffer(self) < 0)
- return -1;
+static PyObject *
+xmlparse_buffer_used_getter(xmlparseobject *self, void *closure)
+{
+ return PyLong_FromLong((long) self->buffer_used);
+}
+
+static PyObject *
+xmlparse_namespace_prefixes_getter(xmlparseobject *self, void *closure)
+{
+ return PyBool_FromLong(self->ns_prefixes);
+}
+
+static int
+xmlparse_namespace_prefixes_setter(xmlparseobject *self, PyObject *v, void *closure)
+{
+ if (v == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
+ return -1;
}
- if (sethandler(self, name, v)) {
- return 0;
+ int b = PyObject_IsTrue(v);
+ if (b < 0)
+ return -1;
+ self->ns_prefixes = b;
+ XML_SetReturnNSTriplet(self->itself, self->ns_prefixes);
+ return 0;
+}
+
+static PyObject *
+xmlparse_ordered_attributes_getter(xmlparseobject *self, void *closure)
+{
+ return PyBool_FromLong(self->ordered_attributes);
+}
+
+static int
+xmlparse_ordered_attributes_setter(xmlparseobject *self, PyObject *v, void *closure)
+{
+ if (v == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
+ return -1;
}
- PyErr_SetObject(PyExc_AttributeError, name);
- return -1;
+ int b = PyObject_IsTrue(v);
+ if (b < 0)
+ return -1;
+ self->ordered_attributes = b;
+ return 0;
+}
+
+static PyObject *
+xmlparse_specified_attributes_getter(xmlparseobject *self, void *closure)
+{
+ return PyBool_FromLong((long) self->specified_attributes);
+}
+
+static int
+xmlparse_specified_attributes_setter(xmlparseobject *self, PyObject *v, void *closure)
+{
+ if (v == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute");
+ return -1;
+ }
+ int b = PyObject_IsTrue(v);
+ if (b < 0)
+ return -1;
+ self->specified_attributes = b;
+ return 0;
}
+static PyMemberDef xmlparse_members[] = {
+ {"intern", T_OBJECT, offsetof(xmlparseobject, intern), READONLY, NULL},
+ {NULL}
+};
+
+#define XMLPARSE_GETTER_DEF(name) \
+ {#name, (getter)xmlparse_##name##_getter, NULL, NULL},
+#define XMLPARSE_GETTER_SETTER_DEF(name) \
+ {#name, (getter)xmlparse_##name##_getter, \
+ (setter)xmlparse_##name##_setter, NULL},
+
+static PyGetSetDef xmlparse_getsetlist[] = {
+ XMLPARSE_GETTER_DEF(ErrorCode)
+ XMLPARSE_GETTER_DEF(ErrorLineNumber)
+ XMLPARSE_GETTER_DEF(ErrorColumnNumber)
+ XMLPARSE_GETTER_DEF(ErrorByteIndex)
+ XMLPARSE_GETTER_DEF(CurrentLineNumber)
+ XMLPARSE_GETTER_DEF(CurrentColumnNumber)
+ XMLPARSE_GETTER_DEF(CurrentByteIndex)
+ XMLPARSE_GETTER_SETTER_DEF(buffer_size)
+ XMLPARSE_GETTER_SETTER_DEF(buffer_text)
+ XMLPARSE_GETTER_DEF(buffer_used)
+ XMLPARSE_GETTER_SETTER_DEF(namespace_prefixes)
+ XMLPARSE_GETTER_SETTER_DEF(ordered_attributes)
+ XMLPARSE_GETTER_SETTER_DEF(specified_attributes)
+ {NULL},
+};
+
+#undef XMLPARSE_GETTER_DEF
+#undef XMLPARSE_GETTER_SETTER_DEF
+
static int
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
{
@@ -1524,8 +1474,8 @@ static PyTypeObject Xmlparsetype = {
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
- (getattrofunc)xmlparse_getattro, /* tp_getattro */
- (setattrofunc)xmlparse_setattro, /* tp_setattro */
+ (getattrofunc)0, /* tp_getattro */
+ (setattrofunc)0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Xmlparsetype__doc__, /* tp_doc - Documentation string */
@@ -1536,6 +1486,8 @@ static PyTypeObject Xmlparsetype = {
0, /* tp_iter */
0, /* tp_iternext */
xmlparse_methods, /* tp_methods */
+ xmlparse_members, /* tp_members */
+ xmlparse_getsetlist, /* tp_getset */
};
/* End of code for xmlparser objects */
@@ -1639,6 +1591,33 @@ static struct PyModuleDef pyexpatmodule = {
NULL
};
+static int init_handler_descrs(void)
+{
+ int i;
+ assert(!PyType_HasFeature(&Xmlparsetype, Py_TPFLAGS_VALID_VERSION_TAG));
+ for (i = 0; handler_info[i].name != NULL; i++) {
+ struct HandlerInfo *hi = &handler_info[i];
+ hi->getset.name = hi->name;
+ hi->getset.get = (getter)xmlparse_handler_getter;
+ hi->getset.set = (setter)xmlparse_handler_setter;
+ hi->getset.closure = &handler_info[i];
+
+ PyObject *descr;
+ if (PyDict_GetItemString(Xmlparsetype.tp_dict, hi->name))
+ continue;
+ descr = PyDescr_NewGetSet(&Xmlparsetype, &hi->getset);
+
+ if (descr == NULL)
+ return -1;
+ if (PyDict_SetItem(Xmlparsetype.tp_dict, PyDescr_NAME(descr), descr) < 0) {
+ Py_DECREF(descr);
+ return -1;
+ }
+ Py_DECREF(descr);
+ }
+ return 0;
+}
+
PyMODINIT_FUNC
MODULE_INITFUNC(void)
{
@@ -1660,7 +1639,7 @@ MODULE_INITFUNC(void)
if (modelmod_name == NULL)
return NULL;
- if (PyType_Ready(&Xmlparsetype) < 0)
+ if (PyType_Ready(&Xmlparsetype) < 0 || init_handler_descrs() < 0)
return NULL;
/* Create the module and add the functions */
@@ -1910,74 +1889,36 @@ clear_handlers(xmlparseobject *self, int initial)
}
static struct HandlerInfo handler_info[] = {
- {"StartElementHandler",
- (xmlhandlersetter)XML_SetStartElementHandler,
- (xmlhandler)my_StartElementHandler},
- {"EndElementHandler",
- (xmlhandlersetter)XML_SetEndElementHandler,
- (xmlhandler)my_EndElementHandler},
- {"ProcessingInstructionHandler",
- (xmlhandlersetter)XML_SetProcessingInstructionHandler,
- (xmlhandler)my_ProcessingInstructionHandler},
- {"CharacterDataHandler",
- (xmlhandlersetter)XML_SetCharacterDataHandler,
- (xmlhandler)my_CharacterDataHandler},
- {"UnparsedEntityDeclHandler",
- (xmlhandlersetter)XML_SetUnparsedEntityDeclHandler,
- (xmlhandler)my_UnparsedEntityDeclHandler},
- {"NotationDeclHandler",
- (xmlhandlersetter)XML_SetNotationDeclHandler,
- (xmlhandler)my_NotationDeclHandler},
- {"StartNamespaceDeclHandler",
- (xmlhandlersetter)XML_SetStartNamespaceDeclHandler,
- (xmlhandler)my_StartNamespaceDeclHandler},
- {"EndNamespaceDeclHandler",
- (xmlhandlersetter)XML_SetEndNamespaceDeclHandler,
- (xmlhandler)my_EndNamespaceDeclHandler},
- {"CommentHandler",
- (xmlhandlersetter)XML_SetCommentHandler,
- (xmlhandler)my_CommentHandler},
- {"StartCdataSectionHandler",
- (xmlhandlersetter)XML_SetStartCdataSectionHandler,
- (xmlhandler)my_StartCdataSectionHandler},
- {"EndCdataSectionHandler",
- (xmlhandlersetter)XML_SetEndCdataSectionHandler,
- (xmlhandler)my_EndCdataSectionHandler},
- {"DefaultHandler",
- (xmlhandlersetter)XML_SetDefaultHandler,
- (xmlhandler)my_DefaultHandler},
- {"DefaultHandlerExpand",
- (xmlhandlersetter)XML_SetDefaultHandlerExpand,
- (xmlhandler)my_DefaultHandlerExpandHandler},
- {"NotStandaloneHandler",
- (xmlhandlersetter)XML_SetNotStandaloneHandler,
- (xmlhandler)my_NotStandaloneHandler},
- {"ExternalEntityRefHandler",
- (xmlhandlersetter)XML_SetExternalEntityRefHandler,
- (xmlhandler)my_ExternalEntityRefHandler},
- {"StartDoctypeDeclHandler",
- (xmlhandlersetter)XML_SetStartDoctypeDeclHandler,
- (xmlhandler)my_StartDoctypeDeclHandler},
- {"EndDoctypeDeclHandler",
- (xmlhandlersetter)XML_SetEndDoctypeDeclHandler,
- (xmlhandler)my_EndDoctypeDeclHandler},
- {"EntityDeclHandler",
- (xmlhandlersetter)XML_SetEntityDeclHandler,
- (xmlhandler)my_EntityDeclHandler},
- {"XmlDeclHandler",
- (xmlhandlersetter)XML_SetXmlDeclHandler,
- (xmlhandler)my_XmlDeclHandler},
- {"ElementDeclHandler",
- (xmlhandlersetter)XML_SetElementDeclHandler,
- (xmlhandler)my_ElementDeclHandler},
- {"AttlistDeclHandler",
- (xmlhandlersetter)XML_SetAttlistDeclHandler,
- (xmlhandler)my_AttlistDeclHandler},
+
+#define HANDLER_INFO(name) \
+ {#name, (xmlhandlersetter)XML_Set##name, (xmlhandler)my_##name},
+
+ HANDLER_INFO(StartElementHandler)
+ HANDLER_INFO(EndElementHandler)
+ HANDLER_INFO(ProcessingInstructionHandler)
+ HANDLER_INFO(CharacterDataHandler)
+ HANDLER_INFO(UnparsedEntityDeclHandler)
+ HANDLER_INFO(NotationDeclHandler)
+ HANDLER_INFO(StartNamespaceDeclHandler)
+ HANDLER_INFO(EndNamespaceDeclHandler)
+ HANDLER_INFO(CommentHandler)
+ HANDLER_INFO(StartCdataSectionHandler)
+ HANDLER_INFO(EndCdataSectionHandler)
+ HANDLER_INFO(DefaultHandler)
+ HANDLER_INFO(DefaultHandlerExpand)
+ HANDLER_INFO(NotStandaloneHandler)
+ HANDLER_INFO(ExternalEntityRefHandler)
+ HANDLER_INFO(StartDoctypeDeclHandler)
+ HANDLER_INFO(EndDoctypeDeclHandler)
+ HANDLER_INFO(EntityDeclHandler)
+ HANDLER_INFO(XmlDeclHandler)
+ HANDLER_INFO(ElementDeclHandler)
+ HANDLER_INFO(AttlistDeclHandler)
#if XML_COMBINED_VERSION >= 19504
- {"SkippedEntityHandler",
- (xmlhandlersetter)XML_SetSkippedEntityHandler,
- (xmlhandler)my_SkippedEntityHandler},
+ HANDLER_INFO(SkippedEntityHandler)
#endif
+#undef HANDLER_INFO
+
{NULL, NULL, NULL} /* sentinel */
};