bpo-34741: Get rid of tp_getattro and tp_setattro in pyexpat.xmlparser. (GH-9422)
Use tp_members and tp_getset instead.
This commit is contained in:
parent
6543912c90
commit
55f8249d65
|
@ -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]*/
|
||||
|
|
|
@ -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,240 +1174,27 @@ 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)
|
||||
{
|
||||
Py_UCS4 first_char;
|
||||
int handlernum = -1;
|
||||
|
||||
if (!PyUnicode_Check(nameobj))
|
||||
goto generic;
|
||||
if (PyUnicode_READY(nameobj))
|
||||
return NULL;
|
||||
|
||||
handlernum = handlername2int(nameobj);
|
||||
|
||||
if (handlernum != -1) {
|
||||
PyObject *result = self->handlers[handlernum];
|
||||
if (result == NULL)
|
||||
result = Py_None;
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
sethandler(xmlparseobject *self, PyObject *name, PyObject* v)
|
||||
xmlparse_handler_setter(xmlparseobject *self, PyObject *v, struct HandlerInfo *hi)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
int handlernum = hi - handler_info;
|
||||
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) {
|
||||
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)
|
||||
return -1;
|
||||
PyMem_Free(self->buffer);
|
||||
self->buffer = NULL;
|
||||
}
|
||||
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)
|
||||
return -1;
|
||||
self->specified_attributes = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_PyUnicode_EqualToASCIIString(name, "buffer_size")) {
|
||||
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) {
|
||||
if (!PyErr_Occurred())
|
||||
PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* trivial case -- no change */
|
||||
if (new_buffer_size == self->buffer_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* there is already a buffer */
|
||||
if (self->buffer_used != 0) {
|
||||
if (flush_character_buffer(self) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* free existing buffer */
|
||||
PyMem_Free(self->buffer);
|
||||
}
|
||||
self->buffer = PyMem_Malloc(new_buffer_size);
|
||||
if (self->buffer == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
self->buffer_size = new_buffer_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_PyUnicode_EqualToASCIIString(name, "CharacterDataHandler")) {
|
||||
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
|
||||
|
@ -1480,13 +1203,240 @@ xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v)
|
|||
if (flush_character_buffer(self) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (sethandler(self, name, v)) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
#undef INT_GETTER
|
||||
|
||||
static PyObject *
|
||||
xmlparse_buffer_text_getter(xmlparseobject *self, void *closure)
|
||||
{
|
||||
return PyBool_FromLong(self->buffer != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
xmlparse_buffer_text_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;
|
||||
if (b) {
|
||||
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)
|
||||
return -1;
|
||||
PyMem_Free(self->buffer);
|
||||
self->buffer = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!PyErr_Occurred())
|
||||
PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* trivial case -- no change */
|
||||
if (new_buffer_size == self->buffer_size) {
|
||||
return 0;
|
||||
}
|
||||
PyErr_SetObject(PyExc_AttributeError, name);
|
||||
return -1;
|
||||
|
||||
/* 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) {
|
||||
/* there is already a buffer */
|
||||
if (self->buffer_used != 0) {
|
||||
if (flush_character_buffer(self) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* free existing buffer */
|
||||
PyMem_Free(self->buffer);
|
||||
}
|
||||
self->buffer = PyMem_Malloc(new_buffer_size);
|
||||
if (self->buffer == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
self->buffer_size = new_buffer_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue