Re: Python bindings -- I'm stepping back from them

Malcolm Tredinnick <[email protected]> Thu, 13 Mar 2003 19:55:37 +1100
Newsgroups gmane.comp.gnome.apps.mr-project.devel
Message-ID <[email protected]>
--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Mar 13, 2003 at 01:53:53AM +0100, Mikael Hallendal wrote:
[...]
> We are not finished though and I really think that having your bindings
> (are they finished?) will help even if there are conflicts. For example
> we have mostly done the really easy parts yet and the more complex
> functions still needs doing. I for one have not much knowledge in
> wrapping C libraries in Python and wouldn't mind glancing on your code
> (or be able to just copy them in).
> 
> You think it would be possible to send your stuff to the list?

I have sorted out a fair bit of my stuff and attached it to this mail.
That might save you some time. I'm not going to commit it directly,
because I still don't know where you are up to.

There are still a couple of problems here. In particular, I am not sure
why mrp_interval_new is not being wrapped, even though I have provided
data for it. I wanted to make MrpInterval a proper type, but I cannot
currently create one (the idea is to make the tp_init slot in
PyMrpInterval_Type be a pointer to _wrap_mrp_interval_new). The Interval
type is probably a bit incomplete at the moment, because this
constructor issue was driving me up the wall. I think I'm doing
something really dumb, but I cannot see it right at the moment.

Also, I think there are a couple of FIXMEs in the code where I got bored
and left something for later.

During this work, I came across a couple of points that need to be
considered:

	- Calling mrproject.Application() more than once should _not_
	  segfault. The solution may be to have a check in
	  mrp_application_new() (in libmrproject) and just return if the
	  application has already been initialised.

	- I suspect that mrp_application_get_all_file_readers() and
	  mrp_application_get_all_file_writers() should be private
	  functions. They return lists of MrpFileReader and
	  MrpFileWriter structures, respectively, but these structures
	  are not declared in any public header file. Since no functions
	  take such lists as input, the return values of these two
	  functions seems to be completely useless outside of
	  libmrproject.

	- There problably should be non-varargs versions of
	  mrp_object_set and mrp_object_get. This is a problem common to
	  most non-C language bindings: everywhere you have a varargs
	  function, you also have something like mrp_object_setv that
	  takes a list for the bindings to use. We need to wrap these
	  functions eventually, because otherwise there is no convenient
	  way to access custom parameters of MrpObject instances.

Cheers,
Malcolm

-- 
I've got a mind like a... a... what's that thing called?

--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="python.patch"

Index: mrproject.override
===================================================================
RCS file: /cvs/gnome/libmrproject/python/mrproject.override,v
retrieving revision 1.3
diff -u -r1.3 mrproject.override
--- mrproject.override	12 Mar 2003 22:08:15 -0000	1.3
+++ mrproject.override	13 Mar 2003 08:40:42 -0000
@@ -6,6 +6,181 @@
 #include "pygobject.h"
 #include <mrproject/mrproject.h>
 #include <mrproject/mrp-storage-module.h>
+
+/* ------------- MrpDay ------------- */
+
+typedef struct {
+	PyObject_HEAD
+	MrpDay *day;
+} PyMrpDay;
+
+staticforward PyTypeObject PyMrpDay_Type;
+
+static PyObject *
+pymrp_day_new (MrpDay *day)
+{
+	PyMrpDay *self;
+	
+	self = (PyMrpDay *) PyObject_NEW (PyMrpDay, &PyMrpDay_Type);
+	if (self == NULL) {
+		return NULL;
+	}
+	self->day = day;
+	
+	return (PyObject *) self;
+}
+
+static void
+pymrp_day_dealloc (PyMrpDay *self)
+{
+    g_free (self->day);
+    PyObject_DEL(self);
+}
+
+static PyTypeObject PyMrpDay_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,					/* ob_size */
+    "mrproject.Day",			/* tp_name */
+    sizeof(PyMrpDay),			/* tp_basicsize */
+    0,					/* tp_itemsize */
+    /* methods */
+    (destructor)pymrp_day_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,			/* 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 */
+    0,					/* 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)0,			/* tp_init */
+    (allocfunc)0,			/* tp_alloc */
+    (newfunc)0,				/* tp_new */
+    0,					/* tp_free */
+    (inquiry)0,				/* tp_is_gc */
+    (PyObject *)0,			/* tp_bases */
+};
+
+/* ------------- MrpInterval ------------- */
+
+typedef struct {
+	PyObject_HEAD
+	MrpInterval *interval;
+} PyMrpInterval;
+
+staticforward PyTypeObject PyMrpInterval_Type;
+
+static PyObject *
+pymrp_interval_new (MrpInterval *interval)
+{
+	PyMrpInterval *self;
+	
+	self = (PyMrpInterval *) PyObject_NEW (PyMrpInterval,
+					       &PyMrpInterval_Type);
+	if (self == NULL) {
+		return NULL;
+	}
+	self->interval = interval;
+	
+	return (PyObject *) self;
+}
+
+static void
+pymrp_interval_dealloc (PyMrpInterval *self)
+{
+    g_free (self->interval);
+    PyObject_DEL(self);
+}
+
+static PyObject *
+pymrp_interval_copy (PyMrpInterval *self)
+{
+	return pymrp_interval_new ( mrp_interval_copy (self->interval));
+}
+
+
+static PyMethodDef pymrp_interval_methods[] = {
+	{ "copy", (PyCFunction) pymrp_interval_copy, METH_NOARGS },
+	{ NULL, NULL, 0 }
+};
+
+static PyTypeObject PyMrpInterval_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,					/* ob_size */
+    "mrproject.Interval",		/* tp_name */
+    sizeof(PyMrpInterval),		/* tp_basicsize */
+    0,					/* tp_itemsize */
+    /* methods */
+    (destructor)pymrp_interval_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,			/* 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 */
+    pymrp_interval_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)0,			/* tp_init */
+    (allocfunc)0,			/* tp_alloc */
+    (newfunc)0,				/* tp_new */
+    0,					/* tp_free */
+    (inquiry)0,				/* tp_is_gc */
+    (PyObject *)0,			/* tp_bases */
+};
+%%
+init
+    PyMrpDay_Type.tp_alloc = PyType_GenericAlloc;
+    PyMrpDay_Type.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&PyMrpDay_Type) < 0)
+        return;
+    PyMrpInterval_Type.tp_alloc = PyType_GenericAlloc;
+    PyMrpInterval_Type.tp_new = PyType_GenericNew;
+    if (PyType_Ready(&PyMrpInterval_Type) < 0)
+        return;
 %%
 modulename mrproject
 %%
@@ -15,10 +190,17 @@
   *_get_type
   *_valist
   mrp_string_list_* 
+%%
+ignore
   mrp_object_set
   mrp_object_get
   mrp_calendar_set_days
   mrp_calendar_set_default_days 
+  mrp_error_quark
+  mrp_time_from_tm
+  mrp_param_spec_time
+  mrp_interval_ref
+  mrp_interval_unref
 %%
 override mrp_task_get_assignments noargs
 static PyObject *
@@ -124,4 +306,229 @@
 	Py_DECREF(obj);
     }
     return py_list;
+}
+%%
+override mrp_day_add kwargs
+static PyObject *
+_wrap_mrp_day_add (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = {"project", "name", "description", NULL};
+	PyGObject   *project;
+	gchar       *name, *description;
+	MrpDay      *day;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!ss:mrp_day_add",
+					  kwlist, &PyMrpProject_Type, &project,
+					  &name, &description)) {
+		return NULL;
+	}
+
+	day = mrp_day_add (MRP_PROJECT (project->obj), name, description);
+	return pymrp_day_new (day);
+}
+%%
+override mrp_day_get_all kwargs
+static PyObject *
+_wrap_mrp_day_get_all (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = {"project", NULL};
+	PyGObject   *project;
+	GList       *days, *l;
+	PyObject    *tuple;
+	gint        i;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!:mrp_day_get_all",
+					  kwlist, &PyMrpProject_Type,
+					  &project)) {
+		return NULL;
+	}
+
+	days = mrp_day_get_all (MRP_PROJECT (project->obj));
+	tuple = PyTuple_New (g_list_length (days));
+	for (l = days, i = 0; l; l = l->next, ++i) {
+		PyTuple_SET_ITEM (tuple, i, pymrp_day_new (l->data));
+	}
+	return tuple;
+}
+%%
+override mrp_day_remove kwargs
+static PyObject *
+_wrap_mrp_day_remove (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = {"project", "day", NULL};
+	PyGObject   *project;
+	PyMrpDay    *day;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O!O!:mrp_day_remove",
+					  kwlist, &PyMrpProject_Type, &project,
+					  &PyMrpDay_Type, &day)) {
+		return NULL;
+	}
+	mrp_day_remove (MRP_PROJECT (project->obj), day->day);
+	Py_INCREF (Py_None);
+	return Py_None;
+}
+%%
+override mrp_day_get_work noargs
+static PyObject *
+_wrap_mrp_day_get_work (PyObject *self)
+{
+	return pymrp_day_new (mrp_day_get_work ());
+}
+%%
+override mrp_day_get_nonwork noargs
+static PyObject *
+_wrap_mrp_day_get_nonwork (PyObject *self)
+{
+	return pymrp_day_new (mrp_day_get_nonwork ());
+}
+%%
+override mrp_day_get_use_base noargs
+static PyObject *
+_wrap_mrp_day_get_use_base (PyObject *self)
+{
+	return pymrp_day_new (mrp_day_get_use_base ());
+}
+%%
+override mrp_resource_compare
+static PyObject *
+_wrap_mrp_resource_compare (PyObject *self, PyObject *args)
+{
+	PyGObject *lhs, *rhs;
+
+	if (!PyArg_ParseTuple (args, "O!O!:mrp_resource_compare",
+			       &PyMrpResource_Type, &lhs,
+			       &PyMrpResource_Type, &rhs)) {
+		return NULL;
+	}
+	return PyInt_FromLong (mrp_resource_compare (lhs->obj, rhs->obj));
+}
+%%
+override mrp_task_compare
+static PyObject *
+_wrap_mrp_task_compare (PyObject *self, PyObject *args)
+{
+	PyGObject *lhs, *rhs;
+
+	if (!PyArg_ParseTuple (args, "O!O!:mrp_task_compare",
+			       &PyMrpTask_Type, &lhs, &PyMrpTask_Type, &rhs)) {
+		return NULL;
+	}
+	return PyInt_FromLong (mrp_task_compare (lhs->obj, rhs->obj));
+}
+%%
+override mrp_interval_new kwargs
+static PyObject *
+_wrap_mrp_interval_new (PyMrpInterval *self, PyObject *args, PyObject *kwargs)
+{
+	/* FIXME: Why doesn't this method get created????? */
+	static char *kwlist[] = {"start", "end", NULL};
+	glong       start, end;
+	PyObject    *interval;
+
+	if (!PyArg_ParseTupleKeywords (args, kwargs, "ll:mrp_interval_new",
+					  kwlist, &start, &end)) {
+		return NULL;
+	}
+
+	interval = (PyMrpInterval *) PyObject_NEW (PyMrpInterval,
+						   &PyMrpInterval_Type);
+	interval->interval = mrp_interval_new (start, end);
+	return interval;
+}
+%%
+override mrp_calendar_day_set_intervals kwargs
+static PyObject *
+_wrap_mrp_calendar_day_set_intervals (PyGObject *self,
+				      PyObject  *args,
+				      PyObject  *kwargs)
+{
+	static char   *kwlist[] = {"day", "intervals", NULL};
+	PyMrpDay      *day;
+	PyObject      *intervals;
+/*
+	PyMrpInterval *interval;
+	GList         *l;
+	gint          i;
+*/
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+					  "O!O:mrp_calendar_day_set_intervals",
+					  kwlist, &PyMrpDay_Type, &day,
+					  &intervals)) {
+		return NULL;
+	}
+	if (!PySequence_Check (intervals)) {
+		PyErr_SetString(PyExc_TypeError, "intervals argument must be a "
+				"sequence");
+		Py_DECREF (day);
+		Py_DECREF (intervals);
+		return NULL;
+	}
+
+	/* FIXME -- implement! */
+	
+	Py_INCREF (Py_None);
+	return Py_None;
+}
+%%
+override mrp_calendar_day_get_total_work kwargs
+static PyObject *
+_wrap_mrp_calendar_day_get_total_work (PyGObject *self,
+                                       PyObject  *args,
+				       PyObject  *kwargs)
+{
+	static char *kwlist[] = {"day", NULL};
+	PyMrpDay    *day;
+	gint        work;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+				          "O!:mrp_calendar_day_get_total_work",
+				          kwlist, &PyMrpDay_Type, &day)) {
+		return NULL;
+	}
+	work = mrp_calendar_day_get_total_work (MRP_CALENDAR (self->obj),
+						day->day);
+	return PyInt_FromLong (work);
+}
+%%
+override mrp_calendar_get_day kwargs
+static PyObject *
+_wrap_mrp_calendar_get_day (PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = {"date", "check_ancestors", NULL};
+	glong       date;
+	PyObject    *check;
+	gboolean    check_ancestors;
+	MrpDay      *day;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+				          "lO:mrp_calendar_get_day",
+				          kwlist, &date, &check)) {
+		return NULL;
+	}
+	check_ancestors = PyObject_IsTrue (check);
+	day = mrp_calendar_get_day (MRP_CALENDAR (self->obj), date,
+				    check_ancestors);
+	return pymrp_day_new (day);
+}
+%%
+override mrp_calendar_get_default_day kwargs
+static PyObject *
+_wrap_mrp_calendar_get_default_day (PyGObject *self,
+				    PyObject  *args,
+				    PyObject  *kwargs)
+{
+	static char *kwlist[] = {"week_day", NULL};
+	gint        week_day;
+	MrpDay      *day;
+
+	if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+				          "i:mrp_calendar_get_default_day",
+				          kwlist, &week_day)) {
+		return NULL;
+	}
+
+	day = mrp_calendar_get_default_day (MRP_CALENDAR (self->obj), week_day);
+	return pymrp_day_new (day);
 }

--envbJBWh7q8WU6mo
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

_______________________________________________
Mrproject-devel mailing list
[email protected]
http://lists.codefactory.se/cgi-bin/mailman/listinfo/mrproject-devel

--envbJBWh7q8WU6mo--