[Planner Dev] Python binding (and test case nr 1)



Hi,

I've reenabled the Python binding and added it as script language (see
the action menu). Default is autodetection but you can enable/disable
it.
Richard/Mikael, is it ok to commit ?

Regards,
Xavier Ordoquy.
? planner-python.patch
? python/planner-arg-types.py
? python/planner.c
? src/libpython_plugin_la-planner-python-plugin.loT
cvs server: Diffing .
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/Makefile.am,v
retrieving revision 1.8
diff -u -B -p -r1.8 Makefile.am
--- Makefile.am	14 Jan 2004 20:56:43 -0000	1.8
+++ Makefile.am	26 Apr 2004 15:04:31 -0000
@@ -2,6 +2,10 @@ if HAVE_DOTNET
 dotnet_DIR = dotnet
 endif
 
+if HAVE_PYTHON
+python_DIR = python
+endif
+
 SUBDIRS = \
 	po 				\
 	libplanner			\
@@ -9,6 +13,7 @@ SUBDIRS = \
 	src				\
 	data				\
 	docs				\
+	$(python_DIR)			\
 	$(dotnet_DIR)
 
 EXTRA_DIST = \
Index: acinclude.m4
===================================================================
RCS file: /cvs/gnome/planner/acinclude.m4,v
retrieving revision 1.1.1.1
diff -u -B -p -r1.1.1.1 acinclude.m4
--- acinclude.m4	1 Dec 2003 17:36:19 -0000	1.1.1.1
+++ acinclude.m4	26 Apr 2004 15:04:31 -0000
@@ -59,3 +59,43 @@ AC_DEFUN([PLANNER_COMPILE_WARNINGS],[
     AC_SUBST(WARN_CFLAGS)
 ])
 
+dnl a macro to check for ability to create python extensions
+dnl  AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_INCLUDES
+AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
+[AC_REQUIRE([AM_PATH_PYTHON])
+AC_MSG_CHECKING(for headers required to compile python extensions)
+dnl deduce PYTHON_INCLUDES
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+if test "$py_prefix" != "$py_exec_prefix"; then
+  PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
+fi
+AC_SUBST(PYTHON_INCLUDES)
+dnl check if the headers exist:
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
+AC_TRY_CPP([#include <Python.h>],dnl
+[AC_MSG_RESULT(found)
+$1],dnl
+[AC_MSG_RESULT(not found)
+$2])
+CPPFLAGS="$save_CPPFLAGS"
+
+	# Check for Python library path
+        AC_MSG_CHECKING([for Python library path])
+        python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+        for i in "$python_path/lib/python$PYTHON_VERSION/config/" "$python_path/lib/python$PYTHON_VERSION/" "$python_path/lib/python/config/" "$python_path/lib/python/" "$python_path/" ; do
+                python_path=`find $i -type f -name libpython$PYTHON_VERSION.* -print | sed "1q"`
+                if test -n "$python_path" ; then
+                        break
+                fi
+        done
+        python_path=`echo $python_path | sed "s,/libpython.*$,,"`
+        AC_MSG_RESULT([$python_path])
+        if test -z "$python_path" ; then
+                AC_MSG_ERROR([cannot find Python library path])
+        fi
+        AC_SUBST([PYTHON_LDFLAGS],["-L$python_path -lpython$PYTHON_VERSION"])
+])
Index: configure.in
===================================================================
RCS file: /cvs/gnome/planner/configure.in,v
retrieving revision 1.24
diff -u -B -p -r1.24 configure.in
--- configure.in	15 Apr 2004 18:27:12 -0000	1.24
+++ configure.in	26 Apr 2004 15:04:31 -0000
@@ -193,30 +193,31 @@ dnl ------------------------------------
 dnl  --------------
 dnl | Python setup |--------------------------------------------
 dnl  --------------
-
 AC_ARG_ENABLE(python, [  --enable-python        build python bindings [default=auto]], enable_python="$enableval", enable_python=auto)
 
-#AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, have_python=no)
-#AM_PATH_PYTHON([2.2])
-#AM_CHECK_PYTHON_HEADERS(,have_python=no)
-#PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= $PYGTK_REQUIRED, have_python=yes, have_python=no)
-#AC_SUBST(PYGTK_CFLAGS)
-
-#if test x$have_python = xno; then
-#   AC_MSG_WARN([Python development libraries not found])
-#fi
-
-#if test x$enable_python = xyes; then
-#   if test x$have_python = xno; then
-#      AC_MSG_ERROR([Python explicitly required, and Python development libraries not found])
-#   fi
-#fi
-
-#if test x$enable_python = xno; then
-#   have_python=no
-#fi
+if test "x$enable_python" != "xno"; then
+    dnl check for python
+    have_python=yes
+    AM_PATH_PYTHON([2.2])
+    AM_CHECK_PYTHON_HEADERS(,have_python=no)
+    AC_SUBST(PYGTK_CFLAGS)
+
+    dnl check for pygtk
+    if test "x$have_python" = "xyes"; then
+      PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= $PYGTK_REQUIRED, have_python=yes, have_python=no)
+    fi
+    if test "x$have_python" = "xyes"; then
+      AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no)
+      if test "x$PYGTK_CODEGEN" = xno; then
+        AC_MSG_ERROR(could not find pygtk-codegen-2.0 script)
+        have_python=no
+      fi
+    fi
+else
+    have_python=no
+fi
 
-#AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes)
+AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes)
 
 dnl  --------------
 dnl | dotnet setup |--------------------------------------------
@@ -274,6 +275,7 @@ data/ui/Makefile
 data/dtd/Makefile
 data/stylesheets/Makefile
 data/mime/Makefile
+python/Makefile
 dotnet/Makefile
 dotnet/libplanner/Makefile
 dotnet/samples/Makefile
@@ -288,7 +290,7 @@ AC_OUTPUT
 echo
 echo "Planner prefix    : $prefix"
 echo "Build API docs    : $enable_gtk_doc"
-#echo "Python bindings   : $have_python"
+echo "Python bindings   : $have_python"
 echo "Dotnet bindings   : $have_dotnet"
 echo "GDA support       : $use_gda"
 echo "Time table view   : $enable_timetable"
cvs server: Diffing data
cvs server: Diffing data/dtd
cvs server: Diffing data/glade
cvs server: Diffing data/images
cvs server: Diffing data/mime
cvs server: Diffing data/stylesheets
cvs server: Diffing data/ui
Index: data/ui/Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/data/ui/Makefile.am,v
retrieving revision 1.2
diff -u -B -p -r1.2 Makefile.am
--- data/ui/Makefile.am	12 Dec 2003 19:25:50 -0000	1.2
+++ data/ui/Makefile.am	26 Apr 2004 15:04:32 -0000
@@ -4,6 +4,10 @@ if BUILD_TIMETABLE
 timetable_view_ui = time-table-view.ui
 endif
 
+if HAVE_PYTHON
+python_script_ui = python-plugin.ui
+endif
+
 ui_DATA = \
 	gantt-view.ui		\
 	task-view.ui		\
@@ -13,6 +17,7 @@ ui_DATA = \
 	resource-view.ui	\
 	sql-plugin.ui		\
 	task-view.ui		\
+	$(python_script_ui)	\
 	$(timetable_view_ui)
 
 EXTRA_DIST = $(ui_DATA)
cvs server: data/ui/python-plugin.ui is a new entry, no comparison available
cvs server: Diffing docs
cvs server: Diffing docs/libplanner
cvs server: Diffing docs/libplanner/tmpl
cvs server: Diffing docs/sql
cvs server: Diffing docs/user-guide
cvs server: Diffing docs/user-guide/C
cvs server: Diffing docs/user-guide/C/figures
cvs server: Diffing docs/user-guide/es
cvs server: Diffing docs/user-guide/es/figures
cvs server: Diffing dotnet
cvs server: Diffing dotnet/libplanner
cvs server: Diffing dotnet/samples
cvs server: Diffing dotnet/sources
cvs server: Diffing examples
cvs server: Diffing examples/user-guide
cvs server: Diffing libegg
cvs server: Diffing libegg/recent-files
cvs server: Diffing libplanner
cvs server: Diffing po
cvs server: Diffing python
Index: python/Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/python/Makefile.am,v
retrieving revision 1.1.1.1
diff -u -B -p -r1.1.1.1 Makefile.am
--- python/Makefile.am	1 Dec 2003 17:36:20 -0000	1.1.1.1
+++ python/Makefile.am	26 Apr 2004 15:04:32 -0000
@@ -7,13 +7,15 @@ INCLUDES = 				\
 	$(LIBPLANNER_CFLAGS)		\
 	$(NULL)
 
-CFLAGS += -Wno-missing-declarations -Wno-missing-prototypes
+pkgpythondir = $(pythondir)/gtk-2.0
+pkgpyexecdir = $(pyexecdir)/gtk-2.0
 
-pyexec_LTLIBRARIES = plannermodule.la
-plannermodule_la_LDFLAGS = -module -avoid-version -export-symbols-regex initplanner
-plannermodule_la_LIBADD = $(LIBPLANNER_LIBS) ../planner/libplanner.la
-plannermodule_la_SOURCES = plannermodule.c
-nodist_plannermodule_la_SOURCES = planner.c
+pkgpyexec_LTLIBRARIES = planner.la
+planner_la_CFLAGS = -Wno-missing-declarations -Wno-missing-prototypes
+planner_la_LDFLAGS = -module -avoid-version -export-symbols-regex initplanner
+planner_la_LIBADD = $(LIBPLANNER_LIBS) $(top_builddir)/libplanner/libplanner-1.la
+planner_la_SOURCES = plannermodule.c
+nodist_planner_la_SOURCES = planner.c
 
 planner.c: planner.defs planner.override
 
Index: python/planner.defs
===================================================================
RCS file: /cvs/gnome/planner/python/planner.defs,v
retrieving revision 1.1.1.1
diff -u -B -p -r1.1.1.1 planner.defs
--- python/planner.defs	1 Dec 2003 17:36:21 -0000	1.1.1.1
+++ python/planner.defs	26 Apr 2004 15:04:33 -0000
@@ -661,8 +661,8 @@
   (c-name "mrp_project_insert_task")
   (return-type "none")
   (parameters
-    '("MrpTask*" "parent")
-    '("gint" "position")
+    '("MrpTask*" "parent" (null-ok)(default "NULL"))
+    '("gint" "position" (default "0"))
     '("MrpTask*" "task")
   )
 )
cvs server: python/test.py is a new entry, no comparison available
cvs server: Diffing src
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/src/Makefile.am,v
retrieving revision 1.10
diff -u -B -p -r1.10 Makefile.am
--- src/Makefile.am	15 Mar 2004 21:02:29 -0000	1.10
+++ src/Makefile.am	26 Apr 2004 15:04:33 -0000
@@ -15,6 +15,10 @@ INCLUDES = \
 	-DMRP_PLUGINDIR=\""$(libdir)/planner/plugins"\"		\
 	$(GNOMEUI_UNSTABLE)
 
+if HAVE_PYTHON
+INCLUDES += $(PYTHON_INCLUDES)
+endif
+
 bin_PROGRAMS = planner 
 
 planner_SOURCES = \
@@ -193,9 +197,18 @@ libsql_plugin_la_CFLAGS = $(GDA_CFLAGS) 
 libsql_plugin_la_LDFLAGS = -avoid-version -module
 endif
 
+if HAVE_PYTHON
+python_plugin = libpython-plugin.la
+libpython_plugin_la_SOURCES = planner-python-plugin.c
+libpython_plugin_la_LDFLAGS = -avoid-version -module
+libpython_plugin_la_LIBADD  = $(PYTHON_LDFLAGS)
+# libpython_plugin_la_CFLAGS =
+endif
+
 plugin_LTLIBRARIES = \
 	libhtml-plugin.la		\
-	$(sql_plugin)
+	$(sql_plugin)			\
+	$(python_plugin)
 
 libhtml_plugin_la_SOURCES = planner-html-plugin.c
 libhtml_plugin_la_LDFLAGS = -avoid-version -module
cvs server: src/planner-python-plugin.c is a new entry, no comparison available
cvs server: Diffing tests
cvs server: Diffing tests/python
<Root>
  <commands>	
    <cmd name="Python script" _label="Execute a Python scipt" pixtype="stock" pixname="Execute"/>
  </commands>
  <menu>
    <submenu    name="Actions">
      <placeholder name="View specific actions placeholder">
        <menuitem name="Python script" verb="" accel=""/>
        <separator/>
      </placeholder>
    </submenu>
  </menu>
</Root>
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2004 Xavier Ordoquy <xordoquy wanadoo fr>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <Python.h>

#include <config.h>
#include <glib.h> 
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <bonobo/bonobo-ui-component.h>
#include <bonobo/bonobo-ui-util.h>
#include <glade/glade.h>
#include <gtk/gtkradiobutton.h>
#include <gtk/gtkmessagedialog.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkfilesel.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-file-entry.h>
#include "planner-window.h"
#include "planner-plugin.h"

#include "/opt/gnome26/include/pygtk-2.0/pygobject.h"

struct _PlannerPluginPriv {
	PlannerWindow *main_window;
	GtkWidget     *dialog;
};

static void python_plugin_execute             (BonoboUIComponent *component,
					       gpointer           user_data,
					       const gchar       *cname);

void        plugin_init                       (PlannerPlugin     *plugin,
					       PlannerWindow     *main_window);
void        plugin_exit                       (PlannerPlugin     *plugin);


static BonoboUIVerb verbs[] = {
	BONOBO_UI_VERB ("Python script", python_plugin_execute),
	BONOBO_UI_VERB_END
};




static gboolean
window_file_is_dir (const gchar *file)
{
	struct stat sb;

	if ((stat (file, &sb) == 0) && S_ISDIR (sb.st_mode)) {
		return TRUE;
	}

	return FALSE;
}

/*
static gchar *
get_last_dir (PlannerWindow *window)
{
	PlannerWindowPriv *priv;
	GConfClient      *gconf_client;
	gchar            *last_dir;
	
	priv = window->priv;
	
	gconf_client = planner_application_get_gconf_client (priv->application);
	
	last_dir = gconf_client_get_string (gconf_client,
					    GCONF_PATH "/general/last_dir",
					    NULL);
	
	if (last_dir == NULL) {
		last_dir = g_strdup (g_get_home_dir ());
	}
	
	if (last_dir[strlen (last_dir)] != G_DIR_SEPARATOR) {
		gchar *tmp;
		
		tmp = g_strconcat (last_dir, G_DIR_SEPARATOR_S, NULL);
		g_free (last_dir);
		last_dir = tmp;
	}

	return last_dir;
}
*/

static void
python_plugin_execute (BonoboUIComponent *component,
		       gpointer           user_data,
		       const gchar       *cname)
{
	PlannerWindow     *window;
	PlannerPluginPriv *priv;

	GtkWidget        *file_sel;
	gint              response;
	const gchar      *filename = NULL;
	gchar            *last_dir;

	priv = PLANNER_PLUGIN (user_data)->priv;
	window = priv->main_window;

	file_sel = gtk_file_selection_new (_("Open a file"));

	/* last_dir = get_last_dir (window); */
	last_dir = g_strdup (g_get_home_dir ());
	gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_sel), last_dir);
	g_free (last_dir);

	gtk_window_set_modal (GTK_WINDOW (file_sel), TRUE);

	gtk_widget_show (file_sel);

	response = gtk_dialog_run (GTK_DIALOG (file_sel));

	if (response == GTK_RESPONSE_OK) {
		filename = gtk_file_selection_get_filename (
			GTK_FILE_SELECTION (file_sel));
		if (window_file_is_dir (filename)) {
			filename = NULL;
		}
	}
	
	gtk_widget_destroy (file_sel);

	if (filename != NULL) {
		FILE *fp;
		PyObject *pModule, *pName;
		/* PyObject *pDict, *pMain; */

		fp = fopen(filename,"r");
		Py_Initialize();

		/* Import pygtk */
		PyRun_SimpleString("import pygtk\n"
				"pygtk.require('2.0')\n"
				"import gtk\n");

		/* Import planner */
		pName = PyString_FromString("planner");
		pModule = PyImport_Import(pName);
		Py_DECREF(pName);
		/*
		pDict = PyImport_GetModuleDict();
		pMain = PyDict_GetItemString(pDict,"__main__");
		pDict = PyModule_GetDict(pMain);
		PyDict_SetItemString(pDict,"planner",pModule);
		*/

		if (pModule != NULL) {
			PyObject   *py_widget;
			PyObject   *pDict, *pMain;
			MrpProject *project;

			pDict = PyImport_GetModuleDict();
			pMain = PyDict_GetItemString(pDict,"__main__");
			pDict = PyModule_GetDict(pMain);

			project = planner_window_get_project(window);
			py_widget = pygobject_new((GObject *)project);
			PyDict_SetItemString(pDict, "project", py_widget);
			Py_DECREF(py_widget);

			PyRun_SimpleFile(fp,filename);
		}
		Py_Finalize();
		fclose(fp);
	}
}

G_MODULE_EXPORT void 
plugin_init (PlannerPlugin *plugin, PlannerWindow *main_window)
{
	PlannerPluginPriv *priv;
	BonoboUIContainer *ui_container;
	BonoboUIComponent *ui_component;
	
	priv = g_new0 (PlannerPluginPriv, 1);
	plugin->priv = priv;
	priv->main_window = main_window;
	
	ui_container = planner_window_get_ui_container (main_window);
	ui_component = bonobo_ui_component_new_default ();
	
	bonobo_ui_component_set_container (ui_component, 
					   BONOBO_OBJREF (ui_container),
					   NULL);
	bonobo_ui_component_freeze (ui_component, NULL);
	bonobo_ui_component_add_verb_list_with_data (ui_component, 
						     verbs,
						     plugin);
	bonobo_ui_util_set_ui (ui_component,
			       DATADIR,
			       "/planner/ui/python-plugin.ui",
			       "pythonplugin",
			       NULL);
	
	bonobo_ui_component_thaw (ui_component, NULL);
}

G_MODULE_EXPORT void 
plugin_exit (PlannerPlugin *plugin) 
{
	/*g_message ("Test exit");*/
}
import pygtk
pygtk.require('2.0')
import gtk
import planner

#if project.is_empty():
#	print 'The project is empty.'
#else:
#	print 'The project is not empty.'

#
# Test case nr 1
#

t1 = planner.Task()
t1.set_name('T1')
t1.set_property('work', 8*60*60)
project.insert_task(task=t1)

r1 = planner.Resource()
r1.set_name('R1')
project.add_resource(r1)
r1.set_custom_property('cost',125.0)
r1.assign(t1,100)

if t1.get_cost() == 125*8:
	print 'Test1 .... OK'
else:
	print 'Test1 .... FAILED'

#
# Test case nr 2
#




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]