bpo-1635741: Port pyexpat to multi-phase init (PEP 489) (GH-22222)

This commit is contained in:
Mohamed Koubaa 2021-01-04 08:34:26 -06:00 committed by GitHub
parent bf06b209da
commit c8a87addb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 179 additions and 164 deletions

View File

@ -0,0 +1,2 @@
Port the :mod:`pyexpat` extension module to multi-phase initialization
(:pep:`489`).

View File

@ -11,32 +11,26 @@ PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__,
"`isfinal\' should be true at end of input."); "`isfinal\' should be true at end of input.");
#define PYEXPAT_XMLPARSER_PARSE_METHODDEF \ #define PYEXPAT_XMLPARSER_PARSE_METHODDEF \
{"Parse", (PyCFunction)(void(*)(void))pyexpat_xmlparser_Parse, METH_FASTCALL, pyexpat_xmlparser_Parse__doc__}, {"Parse", (PyCFunction)(void(*)(void))pyexpat_xmlparser_Parse, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_Parse__doc__},
static PyObject * static PyObject *
pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls,
int isfinal); PyObject *data, int isfinal);
static PyObject * static PyObject *
pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) pyexpat_xmlparser_Parse(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
static _PyArg_Parser _parser = {"O|i:Parse", _keywords, 0};
PyObject *data; PyObject *data;
int isfinal = 0; int isfinal = 0;
if (!_PyArg_CheckPositional("Parse", nargs, 1, 2)) { if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&data, &isfinal)) {
goto exit; goto exit;
} }
data = args[0]; return_value = pyexpat_xmlparser_Parse_impl(self, cls, data, isfinal);
if (nargs < 2) {
goto skip_optional;
}
isfinal = _PyLong_AsInt(args[1]);
if (isfinal == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional:
return_value = pyexpat_xmlparser_Parse_impl(self, data, isfinal);
exit: exit:
return return_value; return return_value;
@ -49,7 +43,29 @@ PyDoc_STRVAR(pyexpat_xmlparser_ParseFile__doc__,
"Parse XML data from file-like object."); "Parse XML data from file-like object.");
#define PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF \ #define PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF \
{"ParseFile", (PyCFunction)pyexpat_xmlparser_ParseFile, METH_O, pyexpat_xmlparser_ParseFile__doc__}, {"ParseFile", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ParseFile, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_ParseFile__doc__},
static PyObject *
pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls,
PyObject *file);
static PyObject *
pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {"O:ParseFile", _keywords, 0};
PyObject *file;
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&file)) {
goto exit;
}
return_value = pyexpat_xmlparser_ParseFile_impl(self, cls, file);
exit:
return return_value;
}
PyDoc_STRVAR(pyexpat_xmlparser_SetBase__doc__, PyDoc_STRVAR(pyexpat_xmlparser_SetBase__doc__,
"SetBase($self, base, /)\n" "SetBase($self, base, /)\n"
@ -135,59 +151,28 @@ PyDoc_STRVAR(pyexpat_xmlparser_ExternalEntityParserCreate__doc__,
"Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler."); "Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler.");
#define PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF \ #define PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF \
{"ExternalEntityParserCreate", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ExternalEntityParserCreate, METH_FASTCALL, pyexpat_xmlparser_ExternalEntityParserCreate__doc__}, {"ExternalEntityParserCreate", (PyCFunction)(void(*)(void))pyexpat_xmlparser_ExternalEntityParserCreate, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_ExternalEntityParserCreate__doc__},
static PyObject * static PyObject *
pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self,
PyTypeObject *cls,
const char *context, const char *context,
const char *encoding); const char *encoding);
static PyObject * static PyObject *
pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
static _PyArg_Parser _parser = {"z|s:ExternalEntityParserCreate", _keywords, 0};
const char *context; const char *context;
const char *encoding = NULL; const char *encoding = NULL;
if (!_PyArg_CheckPositional("ExternalEntityParserCreate", nargs, 1, 2)) { if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&context, &encoding)) {
goto exit; goto exit;
} }
if (args[0] == Py_None) { return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, cls, context, encoding);
context = NULL;
}
else if (PyUnicode_Check(args[0])) {
Py_ssize_t context_length;
context = PyUnicode_AsUTF8AndSize(args[0], &context_length);
if (context == NULL) {
goto exit;
}
if (strlen(context) != (size_t)context_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
}
else {
_PyArg_BadArgument("ExternalEntityParserCreate", "argument 1", "str or None", args[0]);
goto exit;
}
if (nargs < 2) {
goto skip_optional;
}
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("ExternalEntityParserCreate", "argument 2", "str", args[1]);
goto exit;
}
Py_ssize_t encoding_length;
encoding = PyUnicode_AsUTF8AndSize(args[1], &encoding_length);
if (encoding == NULL) {
goto exit;
}
if (strlen(encoding) != (size_t)encoding_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
skip_optional:
return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, context, encoding);
exit: exit:
return return_value; return return_value;
@ -239,29 +224,25 @@ PyDoc_STRVAR(pyexpat_xmlparser_UseForeignDTD__doc__,
"information to the parser. \'flag\' defaults to True if not provided."); "information to the parser. \'flag\' defaults to True if not provided.");
#define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF \ #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF \
{"UseForeignDTD", (PyCFunction)(void(*)(void))pyexpat_xmlparser_UseForeignDTD, METH_FASTCALL, pyexpat_xmlparser_UseForeignDTD__doc__}, {"UseForeignDTD", (PyCFunction)(void(*)(void))pyexpat_xmlparser_UseForeignDTD, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pyexpat_xmlparser_UseForeignDTD__doc__},
static PyObject * static PyObject *
pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag); pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls,
int flag);
static PyObject * static PyObject *
pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyObject *const *args, Py_ssize_t nargs) pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
static _PyArg_Parser _parser = {"|p:UseForeignDTD", _keywords, 0};
int flag = 1; int flag = 1;
if (!_PyArg_CheckPositional("UseForeignDTD", nargs, 0, 1)) { if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
&flag)) {
goto exit; goto exit;
} }
if (nargs < 1) { return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, cls, flag);
goto skip_optional;
}
flag = PyObject_IsTrue(args[0]);
if (flag < 0) {
goto exit;
}
skip_optional:
return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, flag);
exit: exit:
return return_value; return return_value;
@ -387,4 +368,4 @@ exit:
#ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */
/*[clinic end generated code: output=14e37efc4ec10be2 input=a9049054013a1b77]*/ /*[clinic end generated code: output=612b9d6a17a679a7 input=a9049054013a1b77]*/

View File

@ -47,7 +47,18 @@ enum HandlerTypes {
_DummyDecl _DummyDecl
}; };
static PyObject *ErrorObject; typedef struct {
PyTypeObject *xml_parse_type;
PyObject *error;
} pyexpat_state;
static inline pyexpat_state*
pyexpat_get_state(PyObject *module)
{
void *state = PyModule_GetState(module);
assert(state != NULL);
return (pyexpat_state *)state;
}
/* ----------------------------------------------------- */ /* ----------------------------------------------------- */
@ -73,8 +84,6 @@ typedef struct {
#define CHARACTER_DATA_BUFFER_SIZE 8192 #define CHARACTER_DATA_BUFFER_SIZE 8192
static PyTypeObject Xmlparsetype;
typedef void (*xmlhandlersetter)(XML_Parser self, void *meth); typedef void (*xmlhandlersetter)(XML_Parser self, void *meth);
typedef void* xmlhandler; typedef void* xmlhandler;
@ -107,7 +116,7 @@ set_error_attr(PyObject *err, const char *name, int value)
* information. Always returns NULL. * information. Always returns NULL.
*/ */
static PyObject * static PyObject *
set_error(xmlparseobject *self, enum XML_Error code) set_error(pyexpat_state *state, xmlparseobject *self, enum XML_Error code)
{ {
PyObject *err; PyObject *err;
PyObject *buffer; PyObject *buffer;
@ -119,13 +128,13 @@ set_error(xmlparseobject *self, enum XML_Error code)
XML_ErrorString(code), lineno, column); XML_ErrorString(code), lineno, column);
if (buffer == NULL) if (buffer == NULL)
return NULL; return NULL;
err = PyObject_CallOneArg(ErrorObject, buffer); err = PyObject_CallOneArg(state->error, buffer);
Py_DECREF(buffer); Py_DECREF(buffer);
if ( err != NULL if ( err != NULL
&& set_error_attr(err, "code", code) && set_error_attr(err, "code", code)
&& set_error_attr(err, "offset", column) && set_error_attr(err, "offset", column)
&& set_error_attr(err, "lineno", lineno)) { && set_error_attr(err, "lineno", lineno)) {
PyErr_SetObject(ErrorObject, err); PyErr_SetObject(state->error, err);
} }
Py_XDECREF(err); Py_XDECREF(err);
return NULL; return NULL;
@ -680,13 +689,13 @@ class pyexpat.xmlparser "xmlparseobject *" "&Xmlparsetype"
static PyObject * static PyObject *
get_parse_result(xmlparseobject *self, int rv) get_parse_result(pyexpat_state *state, xmlparseobject *self, int rv)
{ {
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }
if (rv == 0) { if (rv == 0) {
return set_error(self, XML_GetErrorCode(self->itself)); return set_error(state, self, XML_GetErrorCode(self->itself));
} }
if (flush_character_buffer(self) < 0) { if (flush_character_buffer(self) < 0) {
return NULL; return NULL;
@ -699,6 +708,7 @@ get_parse_result(xmlparseobject *self, int rv)
/*[clinic input] /*[clinic input]
pyexpat.xmlparser.Parse pyexpat.xmlparser.Parse
cls: defining_class
data: object data: object
isfinal: bool(accept={int}) = False isfinal: bool(accept={int}) = False
/ /
@ -709,14 +719,15 @@ Parse XML data.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyTypeObject *cls,
int isfinal) PyObject *data, int isfinal)
/*[clinic end generated code: output=f4db843dd1f4ed4b input=eb616027bfa9847f]*/ /*[clinic end generated code: output=8faffe07fe1f862a input=fc97f833558ca715]*/
{ {
const char *s; const char *s;
Py_ssize_t slen; Py_ssize_t slen;
Py_buffer view; Py_buffer view;
int rc; int rc;
pyexpat_state *state = PyType_GetModuleState(cls);
if (PyUnicode_Check(data)) { if (PyUnicode_Check(data)) {
view.buf = NULL; view.buf = NULL;
@ -745,9 +756,10 @@ pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data,
rc = XML_Parse(self->itself, s, (int)slen, isfinal); rc = XML_Parse(self->itself, s, (int)slen, isfinal);
done: done:
if (view.buf != NULL) if (view.buf != NULL) {
PyBuffer_Release(&view); PyBuffer_Release(&view);
return get_parse_result(self, rc); }
return get_parse_result(state, self, rc);
} }
/* File reading copied from cPickle */ /* File reading copied from cPickle */
@ -796,6 +808,7 @@ error:
/*[clinic input] /*[clinic input]
pyexpat.xmlparser.ParseFile pyexpat.xmlparser.ParseFile
cls: defining_class
file: object file: object
/ /
@ -803,13 +816,16 @@ Parse XML data from file-like object.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) pyexpat_xmlparser_ParseFile_impl(xmlparseobject *self, PyTypeObject *cls,
/*[clinic end generated code: output=2adc6a13100cc42b input=fbb5a12b6038d735]*/ PyObject *file)
/*[clinic end generated code: output=34780a094c8ca3ae input=ba4bc9c541684793]*/
{ {
int rv = 1; int rv = 1;
PyObject *readmethod = NULL; PyObject *readmethod = NULL;
_Py_IDENTIFIER(read); _Py_IDENTIFIER(read);
pyexpat_state *state = PyType_GetModuleState(cls);
if (_PyObject_LookupAttrId(file, &PyId_read, &readmethod) < 0) { if (_PyObject_LookupAttrId(file, &PyId_read, &readmethod) < 0) {
return NULL; return NULL;
} }
@ -823,7 +839,7 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file)
void *buf = XML_GetBuffer(self->itself, BUF_SIZE); void *buf = XML_GetBuffer(self->itself, BUF_SIZE);
if (buf == NULL) { if (buf == NULL) {
Py_XDECREF(readmethod); Py_XDECREF(readmethod);
return get_parse_result(self, 0); return get_parse_result(state, self, 0);
} }
bytes_read = readinst(buf, BUF_SIZE, readmethod); bytes_read = readinst(buf, BUF_SIZE, readmethod);
@ -841,7 +857,7 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file)
break; break;
} }
Py_XDECREF(readmethod); Py_XDECREF(readmethod);
return get_parse_result(self, rv); return get_parse_result(state, self, rv);
} }
/*[clinic input] /*[clinic input]
@ -907,6 +923,7 @@ pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self)
/*[clinic input] /*[clinic input]
pyexpat.xmlparser.ExternalEntityParserCreate pyexpat.xmlparser.ExternalEntityParserCreate
cls: defining_class
context: str(accept={str, NoneType}) context: str(accept={str, NoneType})
encoding: str = NULL encoding: str = NULL
/ /
@ -916,16 +933,21 @@ Create a parser for parsing an external entity based on the information passed t
static PyObject * static PyObject *
pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self,
PyTypeObject *cls,
const char *context, const char *context,
const char *encoding) const char *encoding)
/*[clinic end generated code: output=535cda9d7a0fbcd6 input=b906714cc122c322]*/ /*[clinic end generated code: output=01d4472b49cb3f92 input=ec70c6b9e6e9619a]*/
{ {
xmlparseobject *new_parser; xmlparseobject *new_parser;
int i; int i;
new_parser = PyObject_GC_New(xmlparseobject, &Xmlparsetype); pyexpat_state *state = PyType_GetModuleState(cls);
if (new_parser == NULL)
new_parser = PyObject_GC_New(xmlparseobject, state->xml_parse_type);
if (new_parser == NULL) {
return NULL; return NULL;
}
new_parser->buffer_size = self->buffer_size; new_parser->buffer_size = self->buffer_size;
new_parser->buffer_used = 0; new_parser->buffer_used = 0;
new_parser->buffer = NULL; new_parser->buffer = NULL;
@ -1006,6 +1028,7 @@ pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag)
/*[clinic input] /*[clinic input]
pyexpat.xmlparser.UseForeignDTD pyexpat.xmlparser.UseForeignDTD
cls: defining_class
flag: bool = True flag: bool = True
/ /
@ -1017,14 +1040,16 @@ information to the parser. 'flag' defaults to True if not provided.
[clinic start generated code]*/ [clinic start generated code]*/
static PyObject * static PyObject *
pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag) pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, PyTypeObject *cls,
/*[clinic end generated code: output=cfaa9aa50bb0f65c input=78144c519d116a6e]*/ int flag)
/*[clinic end generated code: output=d7d98252bd25a20f input=23440ecb0573fb29]*/
{ {
pyexpat_state *state = PyType_GetModuleState(cls);
enum XML_Error rc; enum XML_Error rc;
rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE); rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE);
if (rc != XML_ERROR_NONE) { if (rc != XML_ERROR_NONE) {
return set_error(self, rc); return set_error(state, self, rc);
} }
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -1104,12 +1129,13 @@ PyUnknownEncodingHandler(void *encodingHandlerData,
static PyObject * static PyObject *
newxmlparseobject(const char *encoding, const char *namespace_separator, PyObject *intern) newxmlparseobject(pyexpat_state *state, const char *encoding,
const char *namespace_separator, PyObject *intern)
{ {
int i; int i;
xmlparseobject *self; xmlparseobject *self;
self = PyObject_GC_New(xmlparseobject, &Xmlparsetype); self = PyObject_GC_New(xmlparseobject, state->xml_parse_type);
if (self == NULL) if (self == NULL)
return NULL; return NULL;
@ -1177,7 +1203,9 @@ xmlparse_dealloc(xmlparseobject *self)
self->buffer = NULL; self->buffer = NULL;
} }
Py_XDECREF(self->intern); Py_XDECREF(self->intern);
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_Del(self); PyObject_GC_Del(self);
Py_DECREF(tp);
} }
@ -1464,38 +1492,22 @@ xmlparse_clear(xmlparseobject *op)
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
static PyTypeObject Xmlparsetype = { static PyType_Slot _xml_parse_type_spec_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, xmlparse_dealloc},
"pyexpat.xmlparser", /*tp_name*/ {Py_tp_doc, (void *)Xmlparsetype__doc__},
sizeof(xmlparseobject), /*tp_basicsize*/ {Py_tp_traverse, xmlparse_traverse},
0, /*tp_itemsize*/ {Py_tp_clear, xmlparse_clear},
/* methods */ {Py_tp_methods, xmlparse_methods},
(destructor)xmlparse_dealloc, /*tp_dealloc*/ {Py_tp_members, xmlparse_members},
0, /*tp_vectorcall_offset*/ {Py_tp_getset, xmlparse_getsetlist},
0, /*tp_getattr*/ {0, 0}
0, /*tp_setattr*/ };
0, /*tp_as_async*/
(reprfunc)0, /*tp_repr*/ static PyType_Spec _xml_parse_type_spec = {
0, /*tp_as_number*/ .name = "pyexpat.xmlparser",
0, /*tp_as_sequence*/ .basicsize = sizeof(xmlparseobject),
0, /*tp_as_mapping*/ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
(hashfunc)0, /*tp_hash*/ .slots = _xml_parse_type_spec_slots,
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
(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 */
(traverseproc)xmlparse_traverse, /* tp_traverse */
(inquiry)xmlparse_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
xmlparse_methods, /* tp_methods */
xmlparse_members, /* tp_members */
xmlparse_getsetlist, /* tp_getset */
}; };
/* End of code for xmlparser objects */ /* End of code for xmlparser objects */
@ -1541,7 +1553,8 @@ pyexpat_ParserCreate_impl(PyObject *module, const char *encoding,
return NULL; return NULL;
} }
result = newxmlparseobject(encoding, namespace_separator, intern); pyexpat_state *state = pyexpat_get_state(module);
result = newxmlparseobject(state, encoding, namespace_separator, intern);
if (intern_decref) { if (intern_decref) {
Py_DECREF(intern); Py_DECREF(intern);
} }
@ -1583,14 +1596,10 @@ PyDoc_STRVAR(pyexpat_module_documentation,
#define MODULE_NAME "pyexpat" #define MODULE_NAME "pyexpat"
#endif #endif
#ifndef MODULE_INITFUNC static int init_handler_descrs(pyexpat_state *state)
#define MODULE_INITFUNC PyInit_pyexpat
#endif
static int init_handler_descrs(void)
{ {
int i; int i;
assert(!PyType_HasFeature(&Xmlparsetype, Py_TPFLAGS_VALID_VERSION_TAG)); assert(!PyType_HasFeature(state->xml_parse_type, Py_TPFLAGS_VALID_VERSION_TAG));
for (i = 0; handler_info[i].name != NULL; i++) { for (i = 0; handler_info[i].name != NULL; i++) {
struct HandlerInfo *hi = &handler_info[i]; struct HandlerInfo *hi = &handler_info[i];
hi->getset.name = hi->name; hi->getset.name = hi->name;
@ -1598,11 +1607,11 @@ static int init_handler_descrs(void)
hi->getset.set = (setter)xmlparse_handler_setter; hi->getset.set = (setter)xmlparse_handler_setter;
hi->getset.closure = &handler_info[i]; hi->getset.closure = &handler_info[i];
PyObject *descr = PyDescr_NewGetSet(&Xmlparsetype, &hi->getset); PyObject *descr = PyDescr_NewGetSet(state->xml_parse_type, &hi->getset);
if (descr == NULL) if (descr == NULL)
return -1; return -1;
if (PyDict_SetDefault(Xmlparsetype.tp_dict, PyDescr_NAME(descr), descr) == NULL) { if (PyDict_SetDefault(state->xml_parse_type->tp_dict, PyDescr_NAME(descr), descr) == NULL) {
Py_DECREF(descr); Py_DECREF(descr);
return -1; return -1;
} }
@ -1846,37 +1855,35 @@ pyexpat_destructor(PyObject *op)
static int static int
pyexpat_exec(PyObject *mod) pyexpat_exec(PyObject *mod)
{ {
if (PyType_Ready(&Xmlparsetype) < 0) { pyexpat_state *state = pyexpat_get_state(mod);
state->xml_parse_type = (PyTypeObject *)PyType_FromModuleAndSpec(
mod, &_xml_parse_type_spec, NULL);
if (state->xml_parse_type == NULL) {
return -1; return -1;
} }
if (init_handler_descrs() < 0) { if (init_handler_descrs(state) < 0) {
return -1;
}
state->error = PyErr_NewException("xml.parsers.expat.ExpatError",
NULL, NULL);
if (state->error == NULL) {
return -1; return -1;
} }
/* Add some symbolic constants to the module */ /* Add some symbolic constants to the module */
if (ErrorObject == NULL) {
ErrorObject = PyErr_NewException("xml.parsers.expat.ExpatError", if (PyModule_AddObjectRef(mod, "error", state->error) < 0) {
NULL, NULL);
}
if (ErrorObject == NULL) {
return -1; return -1;
} }
Py_INCREF(ErrorObject); if (PyModule_AddObjectRef(mod, "ExpatError", state->error) < 0) {
if (PyModule_AddObject(mod, "error", ErrorObject) < 0) {
Py_DECREF(ErrorObject);
return -1; return -1;
} }
Py_INCREF(ErrorObject);
if (PyModule_AddObject(mod, "ExpatError", ErrorObject) < 0) { if (PyModule_AddObjectRef(mod, "XMLParserType",
Py_DECREF(ErrorObject); (PyObject *) state->xml_parse_type) < 0) {
return -1;
}
Py_INCREF(&Xmlparsetype);
if (PyModule_AddObject(mod, "XMLParserType",
(PyObject *) &Xmlparsetype) < 0) {
Py_DECREF(&Xmlparsetype);
return -1; return -1;
} }
@ -1979,26 +1986,51 @@ pyexpat_exec(PyObject *mod)
return 0; return 0;
} }
static int
pyexpat_traverse(PyObject *module, visitproc visit, void *arg)
{
pyexpat_state *state = pyexpat_get_state(module);
Py_VISIT(state->xml_parse_type);
Py_VISIT(state->error);
return 0;
}
static int
pyexpat_clear(PyObject *module)
{
pyexpat_state *state = pyexpat_get_state(module);
Py_CLEAR(state->xml_parse_type);
Py_CLEAR(state->error);
return 0;
}
static void
pyexpat_free(void *module)
{
pyexpat_clear((PyObject *)module);
}
static PyModuleDef_Slot pyexpat_slots[] = {
{Py_mod_exec, pyexpat_exec},
{0, NULL}
};
static struct PyModuleDef pyexpatmodule = { static struct PyModuleDef pyexpatmodule = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
.m_name = MODULE_NAME, .m_name = MODULE_NAME,
.m_doc = pyexpat_module_documentation, .m_doc = pyexpat_module_documentation,
.m_size = -1, .m_size = sizeof(pyexpat_state),
.m_methods = pyexpat_methods, .m_methods = pyexpat_methods,
.m_slots = pyexpat_slots,
.m_traverse = pyexpat_traverse,
.m_clear = pyexpat_clear,
.m_free = pyexpat_free
}; };
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit_pyexpat(void) PyInit_pyexpat(void)
{ {
PyObject *mod = PyModule_Create(&pyexpatmodule); return PyModuleDef_Init(&pyexpatmodule);
if (mod == NULL)
return NULL;
if (pyexpat_exec(mod) < 0) {
Py_DECREF(mod);
return NULL;
}
return mod;
} }
static void static void