Method and getattr wierdness in a C extension
Ignacio Vazquez-Abrams
ignacio at openservices.net
Sat Aug 18 20:30:12 EDT 2001
I'm building a Python 1.5 module for libxml2 (not so much for public
consumption so much as to teach myself both libxml2 and Python extensions) and
I'm coming across something odd.
Here's the relevant C code:
---
typedef struct libxml_doc {
PyObject_HEAD
PyObject *dict;
xmlDocPtr doc;
} xmlDocObject;
static PyObject *xmlPyParseFile(PyObject *self, PyObject *args)
{
char *filename=NULL;
xmlDocObject *doc;
xmlDocPtr tree;
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
Py_BEGIN_ALLOW_THREADS
tree=xmlParseFile(filename);
Py_END_ALLOW_THREADS
if (tree==NULL)
{
return NULL;
};
doc=xmlDoc_new(tree);
return ((PyObject *)doc);
};
static struct PyMethodDef libxml_methods[]=
{
{"ParseFile", xmlPyParseFile, METH_VARARGS},
{NULL, NULL}
};
static xmlDocObject *xmlDoc_new(xmlDocPtr doc)
{
xmlDocObject *result=PyObject_NEW(xmlDocObject, &xmlDoc_Type);
PyObject *dict=NULL, *name=NULL;
if (result==NULL)
return NULL;
dict=PyDict_New();
if (dict==NULL)
{
Py_XDECREF(result);
return NULL;
};
PyDict_SetItemString(dict, "...", (PyObject *)<someobj>);
... // Not important
result->doc=doc;
result->dict=dict;
return result;
};
static PyObject *xmlDoc_copy(PyObject *self, PyObject *args)
{
xmlDocObject *old=(xmlDocObject *)self;
xmlDocObject *doc=NULL;
PyArg_ParseTuple(args, "");
doc=PyObject_NEW(xmlDocObject, &xmlDoc_Type);
doc->doc=xmlCopyDoc(old->doc, 1);
doc->dict=PyDict_New();
return (PyObject *)doc;
};
static PyMethodDef xmlDoc_methods[]=
{
{"copy", xmlDoc_copy, METH_VARARGS},
{NULL, NULL}
};
static int xmlDoc_print(PyObject *self, FILE *fp, int flags)
{
xmlDocObject *doc=(xmlDocObject *)self;
xmlChar *out=NULL;
if (flags & Py_PRINT_RAW)
{
out=xmlDoc_Dump(doc->doc);
fprintf(fp, out);
}
else
{
fprintf(fp, "<xmlDocument at %lx>", (long int)self);
};
return 0;
};
static PyObject *xmlDoc_getattr(PyObject *self, char *name)
{
PyObject *result=NULL;
result=Py_FindMethod(xmlDoc_methods, self, name);
return result;
};
static void xmlDoc_dealloc(PyObject *self)
{
xmlFreeDoc(((xmlDocObject *)self)->doc);
Py_XDECREF(((xmlDocObject *)self)->dict);
PyMem_DEL(self);
};
static PyTypeObject xmlDoc_Type=
{
PyObject_HEAD_INIT(NULL)
0,
"xmlDocument",
sizeof(xmlDocObject),
0,
xmlDoc_dealloc, /* dealloc */
xmlDoc_print, /* print */
xmlDoc_getattr, /* getattr */
0, /* setattr */
...
};
void initlibxml(void)
{
PyObject *module, *dict, *str;
xmlDoc_Type.ob_type=&PyType_Type;
module=Py_InitModule("libxml", libxml_methods);
dict=PyModule_GetDict(module);
if (PyDict_SetItemString(dict, "xmlDocumentType", (PyObject *)
&xmlDoc_Type))
Py_FatalError("Cannot add to libxml dictionary");
};
---
Here's the python script I used to test it:
---
#! /usr/bin/python1.5 -i
import libxml
doc=libxml.ParseFile('<somefile>')
---
Here's what I'm getting at the prompt:
---
>>> doc.copy(123)
<xmlDocument at 80f4fc0>
>>> doc.copy(123)
TypeError: function requires exactly 0 arguments; 1 given
>>> doc.copy(123)
<xmlDocument at 80eac00>
>>> doc.copy(123)
TypeError: function requires exactly 0 arguments; 1 given
>>>
---
Why is it alternating between working and not working?
The actual code is larger and more complete than what's given above; if you
need to see more, just ask.
--
Ignacio Vazquez-Abrams <ignacio at openservices.net>
More information about the Python-list
mailing list