> attached goes a patch adding gnome_vfs_async support to gnome-python.
> The actual code goes in vfs-async-handle.c, also attached [1].
Doh!, wrong file sent. Attached goes the latest and greatest
vfs-async-handle.c
Regards,
Iñaki
/* -*- mode: C; c-basic-offset: 4 -*- */
#include <pygobject.h>
#include "pygnomevfs-private.h"
#include <libgnomevfs/gnome-vfs-async-ops.h>
#include <libgnomevfs/gnome-vfs-job-limit.h>
typedef struct {
PyObject_HEAD;
GnomeVFSAsyncHandle *fd;
} PyGnomeVFSAsyncHandle;
extern PyTypeObject PyGnomeVFSAsyncHandle_Type;
static PyObject *
pygnome_vfs_async_handle_new(GnomeVFSAsyncHandle *fd)
{
PyGnomeVFSAsyncHandle *self;
self = PyObject_NEW(PyGnomeVFSAsyncHandle, &PyGnomeVFSAsyncHandle_Type);
if (self == NULL) return NULL;
self->fd = fd;
return (PyObject *)self;
}
static void
async_pass (void)
{
}
/* Get the exception in case any error has occured. Return 1 in case
any error happened. */
static PyObject *
fetch_exception (GnomeVFSResult result, gboolean *error_happened)
{
PyObject *retval;
if (pygnome_vfs_result_check(result)) {
retval = PyErr_Occurred();
if (error_happened)
*error_happened = TRUE;
} else {
retval = Py_None;
if (error_happened)
*error_happened = FALSE;
}
Py_INCREF (retval);
PyErr_Clear ();
return retval;
}
static void
pygvhandle_dealloc(PyGnomeVFSAsyncHandle *self)
{
/* XXXX: unblock threads here */
if (self->fd) {
gnome_vfs_async_close(self->fd,
(GnomeVFSAsyncCloseCallback)async_pass, NULL);
}
PyObject_FREE(self);
}
typedef struct {
PyObject *func, *data;
PyGnomeVFSAsyncHandle *self;
enum {
ASYNC_NOTIFY_OPEN,
ASYNC_NOTIFY_READ,
ASYNC_NOTIFY_WRITE,
ASYNC_NOTIFY_CLOSE,
ASYNC_NOTIFY_G_INFO,
ASYNC_NOTIFY_LOAD_DIRECTORY,
ASYNC_NOTIFY_CREATE,
ASYNC_NOTIFY_CREATE_SYMLINK
} origin;
PyObject *extra;
} PyGVFSAsyncNotify;
static PyGVFSAsyncNotify *
async_notify_new (PyObject *func, void *self,
PyObject *data, int origin)
{
PyGVFSAsyncNotify *result = g_new0(PyGVFSAsyncNotify, 1);
result->func = func;
result->self = (PyGnomeVFSAsyncHandle *)self;
result->data = data;
result->origin = origin;
Py_INCREF (func);
Py_INCREF ((PyGnomeVFSAsyncHandle*)self);
Py_XINCREF (data);
return result;
}
static void
async_notify_free (PyGVFSAsyncNotify *notify)
{
Py_DECREF (notify->func);
Py_DECREF (notify->self);
Py_XDECREF(notify->data);
Py_XDECREF(notify->extra);
g_free (notify);
}
/* Remember to decref the returned object after using it */
static GnomeVFSURI *
_object_to_uri (const char *name, PyObject *uri)
{
if (PyObject_TypeCheck(uri, &PyGnomeVFSURI_Type)) {
return gnome_vfs_uri_ref (pygnome_vfs_uri_get (uri));
} else if (PyString_Check (uri)) {
GnomeVFSURI *c_uri = gnome_vfs_uri_new (PyString_AsString (uri));
if (c_uri == NULL)
PyErr_SetString(PyExc_TypeError, "Cannot build a gnome.vfs.URI");
return c_uri;
} else {
gchar * buffer =
g_strdup_printf ("'%s' must be a gnome.vfs.URI or a string",
name);
PyErr_SetString(PyExc_TypeError, buffer);
g_free (buffer);
}
return NULL;
}
#define object_to_uri(OBJECT) _object_to_uri(#OBJECT, OBJECT)
static int
pygvhandle_init(PyGnomeVFSAsyncHandle *self, PyObject *args, PyObject *kwargs)
{
return 0;
}
static void
callback_marshal (GnomeVFSAsyncHandle *handle,
GnomeVFSResult result,
PyGVFSAsyncNotify *notify)
{
PyObject *retobj;
PyObject *exception;
gboolean error_happened;
pyg_block_threads ();
exception = fetch_exception (result, &error_happened);
if (error_happened &&
(notify->origin == ASYNC_NOTIFY_OPEN ||
notify->origin == ASYNC_NOTIFY_CREATE)) {
notify->self->fd = NULL;
}
if (notify->origin == ASYNC_NOTIFY_CREATE_SYMLINK)
notify->self->fd = NULL;
if (notify->data)
retobj = PyEval_CallFunction (notify->func, "(OOO)",
notify->self,
exception,
notify->data);
else
retobj = PyObject_CallFunction (notify->func, "(OO)",
notify->self,
exception);
if (retobj == NULL) {
PyErr_Print();
PyErr_Clear();
}
Py_XDECREF (retobj);
Py_DECREF (exception);
async_notify_free (notify);
pyg_unblock_threads ();
}
static PyObject*
pygvfs_async_open(PyObject *self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "uri", "callback", "open_mode", "priority",
"data", NULL };
PyObject *uri;
GnomeVFSOpenMode open_mode = GNOME_VFS_OPEN_READ;
PyObject *callback;
PyObject *data = NULL;
int priority = GNOME_VFS_PRIORITY_DEFAULT;
PyObject *pyself;
GnomeVFSURI *c_uri;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OO|iiO:gnome.vfs.async.open",
kwlist, &uri, &callback, &open_mode,
&priority, &data))
return NULL;
/* XXXX: unblock threads here */
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
c_uri = object_to_uri (uri);
if (c_uri == NULL)
return NULL;
pyself = pygnome_vfs_async_handle_new (NULL);
gnome_vfs_async_open_uri(&((PyGnomeVFSAsyncHandle*)pyself)->fd,
c_uri,
open_mode,
priority,
(GnomeVFSAsyncOpenCallback)callback_marshal,
async_notify_new (callback, pyself, data,
ASYNC_NOTIFY_OPEN));
gnome_vfs_uri_unref (c_uri);
return pyself;
}
static PyObject*
pygvhandle_close(PyGnomeVFSAsyncHandle *self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "callback", "data", NULL };
PyObject *callback;
PyObject *data = NULL;
if (!self->fd) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed handle");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"O|O:gnome.vfs.async.Handle.close",
kwlist, &callback, &data))
return NULL;
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
gnome_vfs_async_close(self->fd,
(GnomeVFSAsyncCloseCallback)callback_marshal,
async_notify_new (callback, self, data,
ASYNC_NOTIFY_CLOSE));
self->fd = NULL;
Py_INCREF (Py_None);
return Py_None;
}
static void
read_write_marshal (GnomeVFSAsyncHandle *handle,
GnomeVFSResult result,
gpointer buffer,
GnomeVFSFileSize requested,
GnomeVFSFileSize done,
PyGVFSAsyncNotify *notify)
{
PyObject *retobj;
PyObject *pyvalue;
PyObject *exception;
gboolean error_happened;
pyg_block_threads ();
exception = fetch_exception (result, &error_happened);
if (notify->origin == ASYNC_NOTIFY_READ)
pyvalue = PyString_FromStringAndSize (buffer, done);
else
pyvalue = PyInt_FromLong (done);
if (notify->data)
retobj = PyEval_CallFunction (notify->func, "(OOOO)",
notify->self,
pyvalue,
exception,
notify->data);
else
retobj = PyObject_CallFunction (notify->func, "(OOO)",
notify->self,
pyvalue,
exception);
if (retobj == NULL) {
PyErr_Print();
PyErr_Clear();
}
Py_XDECREF (retobj);
Py_DECREF (pyvalue);
Py_DECREF (exception);
if (notify->origin == ASYNC_NOTIFY_READ)
g_free (buffer);
async_notify_free (notify);
pyg_unblock_threads ();
}
static PyObject*
pygvhandle_read (PyGnomeVFSAsyncHandle *self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "bytes", "callback", "data", NULL };
glong bytes;
PyObject *data = NULL;
PyObject *callback;
if (!self->fd) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed handle");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"lO|O:gnome.vfs.async.Handle.read",
kwlist, &bytes, &callback, &data))
return NULL;
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "third argument not callable");
return NULL;
}
gnome_vfs_async_read (self->fd, g_malloc(bytes), bytes,
(GnomeVFSAsyncReadCallback)read_write_marshal,
async_notify_new (callback, self, data,
ASYNC_NOTIFY_READ));
Py_INCREF (Py_None);
return Py_None;
}
static PyObject*
pygvhandle_write (PyGnomeVFSAsyncHandle *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "buffer", "callback", "data", NULL };
PyObject *buffer;
PyObject *data = NULL;
PyObject *callback;
PyGVFSAsyncNotify *notify;
if (!self->fd) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed handle");
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OO|O:gnome.vfs.async.Handle.write",
kwlist, &buffer, &callback, &data))
return NULL;
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
if (!PyString_Check(buffer)) {
PyErr_SetString(PyExc_TypeError, "'buffer' must be a string object");
return NULL;
}
Py_INCREF (buffer);
notify = async_notify_new (callback, self, data, ASYNC_NOTIFY_WRITE);
notify->extra = buffer;
gnome_vfs_async_write (self->fd, PyString_AsString(buffer),
PyString_Size (buffer),
(GnomeVFSAsyncWriteCallback)read_write_marshal,
notify);
Py_INCREF (Py_None);
return Py_None;
}
static void
get_info_marshal (GnomeVFSAsyncHandle *handle,
GList *results,
PyGVFSAsyncNotify *notify)
{
PyObject *retobj;
PyObject *pyresults; /* a list of (uri, exception, info) tuples */
gint length;
gint i;
pyg_block_threads ();
notify->self->fd = NULL;
length = g_list_length (results);
pyresults = PyList_New (length);
for (i=0; i<length; i++, results = results->next) {
PyObject *item = PyTuple_New(3);
GnomeVFSGetFileInfoResult *r = results->data;
gnome_vfs_uri_ref (r->uri);
PyTuple_SetItem (item, 0, pygnome_vfs_uri_new (r->uri));
PyTuple_SetItem (item, 1, fetch_exception (r->result, NULL));
gnome_vfs_file_info_ref (r->file_info);
PyTuple_SetItem (item, 2, pygnome_vfs_file_info_new (r->file_info));
PyList_SetItem (pyresults, i, item);
}
if (notify->data)
retobj = PyEval_CallFunction (notify->func, "(OOO)",
notify->self,
pyresults,
notify->data);
else
retobj = PyObject_CallFunction (notify->func, "(OO)",
notify->self,
pyresults);
if (retobj == NULL) {
PyErr_Print();
PyErr_Clear();
}
Py_XDECREF (retobj);
Py_DECREF (pyresults);
async_notify_free (notify);
pyg_unblock_threads ();
}
static PyObject *
pygvfs_async_get_file_info (PyObject *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "urilist", "callback", "options", "priority",
"data", NULL };
PyObject *py_urilist;
GList *urilist = NULL;
GnomeVFSFileInfoOptions options = GNOME_VFS_FILE_INFO_DEFAULT;
PyObject *callback;
PyObject *data = NULL;
int priority = GNOME_VFS_PRIORITY_DEFAULT;
int size, i;
PyObject *pyself;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OO|iiO:gnome.vfs.async.get_file_info",
kwlist, &py_urilist, &callback, &options,
&priority, &data))
return NULL;
/* XXXX: unblock threads here */
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
if (PyString_Check(py_urilist)) {
urilist = g_list_append (urilist,
gnome_vfs_uri_new(PyString_AsString
(py_urilist)));
}
else if (PyObject_TypeCheck(py_urilist, &PyGnomeVFSURI_Type)) {
urilist = g_list_append (urilist,
gnome_vfs_uri_ref
(pygnome_vfs_uri_get (py_urilist)));
} else if (PySequence_Check(py_urilist)) {
size = PySequence_Size(py_urilist);
for (i = 0; i < size; ++i) {
PyObject *item = PySequence_GetItem(py_urilist, i);
GnomeVFSURI *uri = NULL;
if (PyObject_TypeCheck(item, &PyGnomeVFSURI_Type))
uri = gnome_vfs_uri_ref(pygnome_vfs_uri_get(item));
else if (PyString_Check(item)) {
uri = gnome_vfs_uri_new(PyString_AsString(item)); }
else {
PyErr_SetString(PyExc_TypeError, "all items in sequence must be of string type or gnome.vfs.URI");
return NULL;
}
urilist = g_list_append(urilist, uri);
Py_DECREF (item);
}
}
else {
PyErr_SetString(PyExc_TypeError, "'urilist' must be either a string, gnome.vfs.URI or a sequence of those");
return NULL;
}
pyself = pygnome_vfs_async_handle_new (NULL);
gnome_vfs_async_get_file_info(&((PyGnomeVFSAsyncHandle*)pyself)->fd,
urilist,
options,
priority,
(GnomeVFSAsyncGetFileInfoCallback)get_info_marshal,
async_notify_new (callback, pyself, data,
ASYNC_NOTIFY_G_INFO));
while (urilist) {
gnome_vfs_uri_unref ((GnomeVFSURI*)urilist->data);
urilist = urilist->next;
}
g_list_free (urilist);
return pyself;
}
static PyObject *
pygvhandle_is_open (PyGnomeVFSAsyncHandle *self)
{
return PyInt_FromLong (self->fd != NULL);
}
static PyObject *
pygvhandle_cancel (PyGnomeVFSAsyncHandle *self)
{
if (self->fd) {
gnome_vfs_async_cancel (self->fd);
self->fd = NULL;
}
Py_INCREF (Py_None);
return Py_None;
}
static void
load_dir_marshal (GnomeVFSAsyncHandle *handle,
GnomeVFSResult result,
GList *list,
guint length,
PyGVFSAsyncNotify *notify)
{
PyObject *retobj;
PyObject *pyresults; /* a list of gnome.vfs.FileInfo */
gint i;
gboolean error_happened;
PyObject *exception;
pyg_block_threads ();
exception = fetch_exception (result, &error_happened);
if (error_happened &&
notify->origin == ASYNC_NOTIFY_LOAD_DIRECTORY)
notify->self->fd = NULL;
pyresults = PyList_New (length);
for (i=0; i<length; i++, list = list->next) {
GnomeVFSFileInfo *info = list->data;
gnome_vfs_file_info_ref (info);
PyList_SetItem (pyresults, i, pygnome_vfs_file_info_new (info));
}
if (notify->data)
retobj = PyEval_CallFunction (notify->func, "(OOOO)",
notify->self,
pyresults,
exception,
notify->data);
else
retobj = PyObject_CallFunction (notify->func, "(OOO)",
notify->self,
pyresults,
exception);
if (retobj == NULL) {
PyErr_Print();
PyErr_Clear();
}
Py_XDECREF (retobj);
Py_DECREF (pyresults);
Py_DECREF (exception);
/* Supposedly we don't get called after errors? */
if (error_happened)
async_notify_free (notify);
pyg_unblock_threads ();
}
static PyObject*
pygvfs_async_load_directory (PyObject *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "uri", "callback",
"options",
"items_per_notification",
"priority",
"data", NULL };
PyObject *uri;
PyObject *callback;
GnomeVFSFileInfoOptions options = GNOME_VFS_FILE_INFO_DEFAULT;
guint items_per_notification = 20; /* Some default to keep the
order of the parameters as in
the C API */
int priority = GNOME_VFS_PRIORITY_DEFAULT;
PyObject *data = NULL;
PyObject *pyself;
GnomeVFSURI *c_uri;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OO|iIiO:gnome.vfs.async.load_directory",
kwlist, &uri, &callback,
&options,
&items_per_notification,
&priority, &data))
return NULL;
/* XXXX: unblock threads here */
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
c_uri = object_to_uri (uri);
if (c_uri == NULL)
return NULL;
pyself = pygnome_vfs_async_handle_new (NULL);
gnome_vfs_async_load_directory_uri(&((PyGnomeVFSAsyncHandle*)pyself)->fd,
c_uri,
options,
items_per_notification,
priority,
(GnomeVFSAsyncDirectoryLoadCallback)load_dir_marshal,
async_notify_new (callback, pyself, data,
ASYNC_NOTIFY_LOAD_DIRECTORY));
gnome_vfs_uri_unref (c_uri);
return pyself;
}
static PyObject*
pygvfs_async_create (PyObject *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "uri", "callback",
"open_mode",
"exclusive",
"perm",
"priority",
"data", NULL };
PyObject *uri;
PyObject *callback;
GnomeVFSOpenMode open_mode = GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_WRITE;
gboolean exclusive = FALSE;
guint perm = 0666;
int priority = GNOME_VFS_PRIORITY_DEFAULT;
PyObject *data = NULL;
PyObject *pyself;
GnomeVFSURI *c_uri;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OO|iiiiO:gnome.vfs.async.create",
kwlist, &uri, &callback,
&open_mode, &exclusive,
&perm, &priority, &data))
return NULL;
/* XXXX: unblock threads here */
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
c_uri = object_to_uri (uri);
if (c_uri == NULL)
return NULL;
pyself = pygnome_vfs_async_handle_new (NULL);
gnome_vfs_async_create_uri(&((PyGnomeVFSAsyncHandle*)pyself)->fd,
c_uri,
open_mode,
exclusive,
perm,
priority,
(GnomeVFSAsyncOpenCallback)callback_marshal,
async_notify_new (callback, pyself, data,
ASYNC_NOTIFY_CREATE));
gnome_vfs_uri_unref (c_uri);
return pyself;
}
static PyObject*
pygvfs_async_create_symbolic_link (PyObject *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "uri", "reference", "callback",
"priority",
"data", NULL };
PyObject *uri;
PyObject *reference;
PyObject *callback;
int priority = GNOME_VFS_PRIORITY_DEFAULT;
PyObject *data = NULL;
PyObject *pyself;
GnomeVFSURI *c_uri, *c_reference;
gchar *reference_buffer;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"OOO|iO:gnome.vfs.async.create_symbolic_link",
kwlist, &uri, &reference, &callback,
&priority, &data))
return NULL;
/* XXXX: unblock threads here */
if (!PyCallable_Check(callback)) {
PyErr_SetString(PyExc_TypeError, "'callback' argument not callable");
return NULL;
}
c_uri = object_to_uri (uri);
if (c_uri == NULL)
return NULL;
c_reference = object_to_uri (reference);
if (c_reference == NULL) {
gnome_vfs_uri_unref (c_uri);
return NULL;
}
/* hmmm... */
reference_buffer = gnome_vfs_uri_to_string (c_reference,
GNOME_VFS_URI_HIDE_NONE);
pyself = pygnome_vfs_async_handle_new (NULL);
gnome_vfs_async_create_symbolic_link(&((PyGnomeVFSAsyncHandle*)pyself)->fd,
c_uri,
reference_buffer,
priority,
(GnomeVFSAsyncOpenCallback)callback_marshal,
async_notify_new (callback, pyself, data,
ASYNC_NOTIFY_CREATE_SYMLINK));
g_free (reference_buffer);
gnome_vfs_uri_unref (c_uri);
gnome_vfs_uri_unref (c_reference);
return pyself;
}
static PyObject *
pygvfs_async_get_job_limit (PyObject *self)
{
return PyInt_FromLong (gnome_vfs_async_get_job_limit ());
}
static PyObject*
pygvfs_async_set_job_limit (PyObject *self,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "limit", NULL };
int limit;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
"i:gnome.vfs.async.set_job_limit",
kwlist, &limit))
return NULL;
gnome_vfs_async_set_job_limit (limit);
Py_INCREF (Py_None);
return Py_None;
}
static PyMethodDef pygnomevfs_async_functions[] = {
{ "open", (PyCFunction)pygvfs_async_open, METH_VARARGS|METH_KEYWORDS },
{ "get_file_info", (PyCFunction)pygvfs_async_get_file_info,
METH_VARARGS|METH_KEYWORDS },
{ "load_directory", (PyCFunction)pygvfs_async_load_directory,
METH_VARARGS|METH_KEYWORDS },
{ "create", (PyCFunction)pygvfs_async_create,
METH_VARARGS|METH_KEYWORDS },
{ "create_symbolic_link",
(PyCFunction)pygvfs_async_create_symbolic_link,
METH_VARARGS|METH_KEYWORDS },
{ "get_job_limit", (PyCFunction)pygvfs_async_get_job_limit,
METH_NOARGS },
{ "set_job_limit", (PyCFunction)pygvfs_async_set_job_limit,
METH_VARARGS|METH_KEYWORDS },
{ NULL, NULL, 0}
};
PyObject *
pygvfs_async_module_init (void)
{
PyObject *m;
PyObject *d;
PyGnomeVFSAsyncHandle_Type.ob_type = &PyType_Type;
if (PyType_Ready(&PyGnomeVFSAsyncHandle_Type) < 0)
return NULL;
m = Py_InitModule("gnome.vfs.async", pygnomevfs_async_functions);
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "Handle",
(PyObject *)&PyGnomeVFSAsyncHandle_Type);
return m;
}
static PyMethodDef pygvhandle_methods[] = {
{ "close", (PyCFunction)pygvhandle_close,
METH_VARARGS|METH_KEYWORDS },
{ "read", (PyCFunction)pygvhandle_read, METH_VARARGS|METH_KEYWORDS },
{ "write", (PyCFunction)pygvhandle_write, METH_VARARGS|METH_KEYWORDS },
{ "is_open", (PyCFunction)pygvhandle_is_open, METH_NOARGS },
{ "cancel", (PyCFunction)pygvhandle_cancel, METH_NOARGS },
{ NULL, NULL, 0 }
};
PyTypeObject PyGnomeVFSAsyncHandle_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"gnome.vfs.async.Handle", /* tp_name */
sizeof(PyGnomeVFSAsyncHandle), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)pygvhandle_dealloc, /* tp_dealloc */
(printfunc)0, /* tp_print */
(getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(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_BASETYPE, /* tp_flags */
NULL, /* Documentation string */
(traverseproc)0, /* tp_traverse */
(inquiry)0, /* tp_clear */
(richcmpfunc)0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)0, /* tp_iter */
(iternextfunc)0, /* tp_iternext */
pygvhandle_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
(PyTypeObject *)0, /* tp_base */
(PyObject *)0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pygvhandle_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
(inquiry)0, /* tp_is_gc */
(PyObject *)0, /* tp_bases */
};
_______________________________________________
pygtk mailing list [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/