#3247: Get rid of Py_FindMethod:
Second step: keep tp_getattr functions when they are complex, but use PyObject_GenericGetAttr() as a fallback. These were the last occurrences of Py_FindMethod.
This commit is contained in:
parent
e43d33a4db
commit
ba4105c133
|
@ -43,8 +43,6 @@ struct PyMethodDef {
|
||||||
};
|
};
|
||||||
typedef struct PyMethodDef PyMethodDef;
|
typedef struct PyMethodDef PyMethodDef;
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) Py_FindMethod(PyMethodDef[], PyObject *, const char *);
|
|
||||||
|
|
||||||
#define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL)
|
#define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL)
|
||||||
PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
|
PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
|
||||||
PyObject *);
|
PyObject *);
|
||||||
|
@ -70,14 +68,6 @@ PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
|
||||||
|
|
||||||
#define METH_COEXIST 0x0040
|
#define METH_COEXIST 0x0040
|
||||||
|
|
||||||
typedef struct PyMethodChain {
|
|
||||||
PyMethodDef *methods; /* Methods of this type */
|
|
||||||
struct PyMethodChain *link; /* NULL or base type */
|
|
||||||
} PyMethodChain;
|
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) Py_FindMethodInChain(PyMethodChain *, PyObject *,
|
|
||||||
const char *);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
PyMethodDef *m_ml; /* Description of the C function to call */
|
PyMethodDef *m_ml; /* Description of the C function to call */
|
||||||
|
|
|
@ -1297,15 +1297,13 @@ static PyMethodDef element_methods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
element_getattr(ElementObject* self, char* name)
|
element_getattro(ElementObject* self, PyObject* nameobj)
|
||||||
{
|
{
|
||||||
PyObject* res;
|
PyObject* res;
|
||||||
|
char *name = "";
|
||||||
|
|
||||||
res = Py_FindMethod(element_methods, (PyObject*) self, name);
|
if (PyUnicode_Check(nameobj))
|
||||||
if (res)
|
name = PyUnicode_AsString(nameobj);
|
||||||
return res;
|
|
||||||
|
|
||||||
PyErr_Clear();
|
|
||||||
|
|
||||||
if (strcmp(name, "tag") == 0)
|
if (strcmp(name, "tag") == 0)
|
||||||
res = self->tag;
|
res = self->tag;
|
||||||
|
@ -1318,14 +1316,10 @@ element_getattr(ElementObject* self, char* name)
|
||||||
element_new_extra(self, NULL);
|
element_new_extra(self, NULL);
|
||||||
res = element_get_attrib(self);
|
res = element_get_attrib(self);
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
return PyObject_GenericGetAttr((PyObject*) self, nameobj);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res)
|
Py_XINCREF(res);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
Py_INCREF(res);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1382,12 +1376,29 @@ static PyTypeObject Element_Type = {
|
||||||
/* methods */
|
/* methods */
|
||||||
(destructor)element_dealloc, /* tp_dealloc */
|
(destructor)element_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
(getattrfunc)element_getattr, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
(setattrfunc)element_setattr, /* tp_setattr */
|
(setattrfunc)element_setattr, /* tp_setattr */
|
||||||
0, /* tp_compare */
|
0, /* tp_compare */
|
||||||
(reprfunc)element_repr, /* tp_repr */
|
(reprfunc)element_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
0, /* tp_as_number */
|
||||||
&element_as_sequence, /* tp_as_sequence */
|
&element_as_sequence, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
(getattrofunc)element_getattro, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||||
|
0, /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
element_methods, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -1783,19 +1794,35 @@ static PyMethodDef treebuilder_methods[] = {
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
treebuilder_getattr(TreeBuilderObject* self, char* name)
|
|
||||||
{
|
|
||||||
return Py_FindMethod(treebuilder_methods, (PyObject*) self, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyTypeObject TreeBuilder_Type = {
|
static PyTypeObject TreeBuilder_Type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"TreeBuilder", sizeof(TreeBuilderObject), 0,
|
"TreeBuilder", sizeof(TreeBuilderObject), 0,
|
||||||
/* methods */
|
/* methods */
|
||||||
(destructor)treebuilder_dealloc, /* tp_dealloc */
|
(destructor)treebuilder_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
(getattrfunc)treebuilder_getattr, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* tp_compare */
|
||||||
|
0, /* tp_repr */
|
||||||
|
0, /* tp_as_number */
|
||||||
|
0, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
0, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||||
|
0, /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
treebuilder_methods, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -2496,13 +2523,13 @@ static PyMethodDef xmlparser_methods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
xmlparser_getattr(XMLParserObject* self, char* name)
|
xmlparser_getattro(XMLParserObject* self, PyObject* nameobj)
|
||||||
{
|
{
|
||||||
PyObject* res;
|
PyObject* res;
|
||||||
|
char *name = "";
|
||||||
|
|
||||||
res = Py_FindMethod(xmlparser_methods, (PyObject*) self, name);
|
if (PyUnicode_Check(nameobj))
|
||||||
if (res)
|
name = PyUnicode_AsString(nameobj);
|
||||||
return res;
|
|
||||||
|
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
|
||||||
|
@ -2516,8 +2543,7 @@ xmlparser_getattr(XMLParserObject* self, char* name)
|
||||||
XML_MINOR_VERSION, XML_MICRO_VERSION);
|
XML_MINOR_VERSION, XML_MICRO_VERSION);
|
||||||
return PyBytes_FromString(buffer);
|
return PyBytes_FromString(buffer);
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
return PyObject_GenericGetAttr((PyObject*) self, nameobj);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(res);
|
Py_INCREF(res);
|
||||||
|
@ -2530,7 +2556,29 @@ static PyTypeObject XMLParser_Type = {
|
||||||
/* methods */
|
/* methods */
|
||||||
(destructor)xmlparser_dealloc, /* tp_dealloc */
|
(destructor)xmlparser_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
(getattrfunc)xmlparser_getattr, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
|
0, /* tp_setattr */
|
||||||
|
0, /* tp_compare */
|
||||||
|
0, /* tp_repr */
|
||||||
|
0, /* tp_as_number */
|
||||||
|
0, /* tp_as_sequence */
|
||||||
|
0, /* tp_as_mapping */
|
||||||
|
0, /* tp_hash */
|
||||||
|
0, /* tp_call */
|
||||||
|
0, /* tp_str */
|
||||||
|
(getattrofunc)xmlparser_getattro, /* tp_getattro */
|
||||||
|
0, /* tp_setattro */
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||||
|
0, /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
xmlparser_methods, /* tp_methods */
|
||||||
|
0, /* tp_members */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2572,10 +2620,14 @@ PyInit__elementtree(void)
|
||||||
struct PyExpat_CAPI* capi;
|
struct PyExpat_CAPI* capi;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Patch object type */
|
/* Initialize object types */
|
||||||
Py_TYPE(&Element_Type) = Py_TYPE(&TreeBuilder_Type) = &PyType_Type;
|
if (PyType_Ready(&TreeBuilder_Type) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (PyType_Ready(&Element_Type) < 0)
|
||||||
|
return NULL;
|
||||||
#if defined(USE_EXPAT)
|
#if defined(USE_EXPAT)
|
||||||
Py_TYPE(&XMLParser_Type) = &PyType_Type;
|
if (PyType_Ready(&XMLParser_Type) < 0)
|
||||||
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m = PyModule_Create(&_elementtreemodule);
|
m = PyModule_Create(&_elementtreemodule);
|
||||||
|
|
|
@ -1135,6 +1135,8 @@ xmlparse_UseForeignDTD(xmlparseobject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static PyObject *xmlparse_dir(PyObject *self, PyObject* noargs);
|
||||||
|
|
||||||
static struct PyMethodDef xmlparse_methods[] = {
|
static struct PyMethodDef xmlparse_methods[] = {
|
||||||
{"Parse", (PyCFunction)xmlparse_Parse,
|
{"Parse", (PyCFunction)xmlparse_Parse,
|
||||||
METH_VARARGS, xmlparse_Parse__doc__},
|
METH_VARARGS, xmlparse_Parse__doc__},
|
||||||
|
@ -1154,6 +1156,7 @@ static struct PyMethodDef xmlparse_methods[] = {
|
||||||
{"UseForeignDTD", (PyCFunction)xmlparse_UseForeignDTD,
|
{"UseForeignDTD", (PyCFunction)xmlparse_UseForeignDTD,
|
||||||
METH_VARARGS, xmlparse_UseForeignDTD__doc__},
|
METH_VARARGS, xmlparse_UseForeignDTD__doc__},
|
||||||
#endif
|
#endif
|
||||||
|
{"__dir__", xmlparse_dir, METH_NOARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1329,9 +1332,15 @@ get_pybool(int istrue)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
xmlparse_getattr(xmlparseobject *self, char *name)
|
xmlparse_getattro(xmlparseobject *self, PyObject *nameobj)
|
||||||
{
|
{
|
||||||
int handlernum = handlername2int(name);
|
char *name = "";
|
||||||
|
int handlernum = -1;
|
||||||
|
|
||||||
|
if (PyUnicode_Check(nameobj))
|
||||||
|
name = PyUnicode_AsString(nameobj);
|
||||||
|
|
||||||
|
handlernum = handlername2int(name);
|
||||||
|
|
||||||
if (handlernum != -1) {
|
if (handlernum != -1) {
|
||||||
PyObject *result = self->handlers[handlernum];
|
PyObject *result = self->handlers[handlernum];
|
||||||
|
@ -1390,7 +1399,7 @@ xmlparse_getattr(xmlparseobject *self, char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Py_FindMethod(xmlparse_methods, (PyObject *)self, name);
|
return PyObject_GenericGetAttr((PyObject*)self, nameobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -1603,11 +1612,6 @@ xmlparse_clear(xmlparseobject *op)
|
||||||
|
|
||||||
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
|
PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser");
|
||||||
|
|
||||||
static PyMethodDef xmlparse_tp_methods[] = {
|
|
||||||
{"__dir__", xmlparse_dir, METH_NOARGS},
|
|
||||||
{NULL, NULL} /* sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
static PyTypeObject Xmlparsetype = {
|
static PyTypeObject Xmlparsetype = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"pyexpat.xmlparser", /*tp_name*/
|
"pyexpat.xmlparser", /*tp_name*/
|
||||||
|
@ -1616,7 +1620,7 @@ static PyTypeObject Xmlparsetype = {
|
||||||
/* methods */
|
/* methods */
|
||||||
(destructor)xmlparse_dealloc, /*tp_dealloc*/
|
(destructor)xmlparse_dealloc, /*tp_dealloc*/
|
||||||
(printfunc)0, /*tp_print*/
|
(printfunc)0, /*tp_print*/
|
||||||
(getattrfunc)xmlparse_getattr, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
(setattrfunc)xmlparse_setattr, /*tp_setattr*/
|
(setattrfunc)xmlparse_setattr, /*tp_setattr*/
|
||||||
(cmpfunc)0, /*tp_compare*/
|
(cmpfunc)0, /*tp_compare*/
|
||||||
(reprfunc)0, /*tp_repr*/
|
(reprfunc)0, /*tp_repr*/
|
||||||
|
@ -1626,7 +1630,7 @@ static PyTypeObject Xmlparsetype = {
|
||||||
(hashfunc)0, /*tp_hash*/
|
(hashfunc)0, /*tp_hash*/
|
||||||
(ternaryfunc)0, /*tp_call*/
|
(ternaryfunc)0, /*tp_call*/
|
||||||
(reprfunc)0, /*tp_str*/
|
(reprfunc)0, /*tp_str*/
|
||||||
0, /* tp_getattro */
|
(getattrofunc)xmlparse_getattro, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
#ifdef Py_TPFLAGS_HAVE_GC
|
#ifdef Py_TPFLAGS_HAVE_GC
|
||||||
|
@ -1641,7 +1645,7 @@ static PyTypeObject Xmlparsetype = {
|
||||||
0, /* tp_weaklistoffset */
|
0, /* tp_weaklistoffset */
|
||||||
0, /* tp_iter */
|
0, /* tp_iter */
|
||||||
0, /* tp_iternext */
|
0, /* tp_iternext */
|
||||||
xmlparse_tp_methods /* tp_methods */
|
xmlparse_methods, /* tp_methods */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* End of code for xmlparser objects */
|
/* End of code for xmlparser objects */
|
||||||
|
@ -1794,7 +1798,8 @@ MODULE_INITFUNC(void)
|
||||||
if (modelmod_name == NULL)
|
if (modelmod_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_TYPE(&Xmlparsetype) = &PyType_Type;
|
if (PyType_Ready(&Xmlparsetype) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Create the module and add the functions */
|
/* Create the module and add the functions */
|
||||||
m = PyModule_Create(&pyexpatmodule);
|
m = PyModule_Create(&pyexpatmodule);
|
||||||
|
|
|
@ -280,43 +280,6 @@ PyTypeObject PyCFunction_Type = {
|
||||||
0, /* tp_dict */
|
0, /* tp_dict */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Find a method in a method chain */
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
|
|
||||||
{
|
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
|
||||||
if (strcmp(name, "__doc__") == 0) {
|
|
||||||
const char *doc = self->ob_type->tp_doc;
|
|
||||||
if (doc != NULL)
|
|
||||||
return PyUnicode_FromString(doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (chain != NULL) {
|
|
||||||
PyMethodDef *ml = chain->methods;
|
|
||||||
for (; ml->ml_name != NULL; ml++) {
|
|
||||||
if (name[0] == ml->ml_name[0] &&
|
|
||||||
strcmp(name+1, ml->ml_name+1) == 0)
|
|
||||||
/* XXX */
|
|
||||||
return PyCFunction_New(ml, self);
|
|
||||||
}
|
|
||||||
chain = chain->link;
|
|
||||||
}
|
|
||||||
PyErr_SetString(PyExc_AttributeError, name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find a method in a single method list */
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
|
|
||||||
{
|
|
||||||
PyMethodChain chain;
|
|
||||||
chain.methods = methods;
|
|
||||||
chain.link = NULL;
|
|
||||||
return Py_FindMethodInChain(&chain, self, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear out the free list */
|
/* Clear out the free list */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue