Python catalog to support python widgets at runtime

Juan Pablo Ugarte <[email protected]>
Newsgroups gmane.comp.gnome.glade.devel
Message-ID <[email protected]>
Hello people.
As you probably know the BINDINGS branch have been inactive for a long
time.
Coming up with a framework to support multiples languages in glade and
actually implementing the full gladeui API for such languages is a big
job.
That said, it does not mean we cant have python widget at runtime!

The idea is simple, i have ported the old branch code into a regular
glade plugin.

So all you have to do is add gladepython as your catalog library
and set the init function to glade_python_init()
glade_python_init() will run a python interpreter and import your python library
using the catalog name.

btw , the patch is against trunk, but it should work in stable

enjoy

Juan Pablo

_______________________________________________
Glade-devel maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/glade-devel
pythonplugin.py (text/x-python, 160 B)
import gobject
import gtk

class MyBox(gtk.HBox):
        __gtype_name__ = 'MyBox'
        
        def __init__(self):
                gtk.HBox.__init__(self)
pythonplugin.xml (application/xml, 444 B)
<?xml version="1.0" encoding="UTF-8"?>
<glade-catalog name="pythonplugin" library="gladepython" domain="glade-3" depends="gtk+">
  <init-function>glade_python_init</init-function>
  <glade-widget-classes>
    <glade-widget-class title="MyBox" name="MyBox" generic-name="mybox"/>
  </glade-widget-classes>
	
  <glade-widget-group name="python" title="Python">
    <glade-widget-class-ref name="MyBox"/>
  </glade-widget-group>
</glade-catalog>
gladepython.patch (text/x-patch, 11 KB)
Index: m4/python.m4
===================================================================
--- m4/python.m4	(revision 1832)
+++ m4/python.m4	(working copy)
@@ -1,7 +1,7 @@
 ## this one is commonly used with AM_PATH_PYTHONDIR ...
 dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
 dnl Check if a module containing a given symbol is visible to python.
-AC_DEFUN([AM_CHECK_PYMOD],
+AC_DEFUN(AM_CHECK_PYMOD,
 [AC_REQUIRE([AM_PATH_PYTHON])
 py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
 AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
@@ -60,65 +60,29 @@
 $2])
 CPPFLAGS="$save_CPPFLAGS"
 ])
-## this one is commonly used with AM_PATH_PYTHONDIR ...
-dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
-dnl Check if a module containing a given symbol is visible to python.
-AC_DEFUN([AM_CHECK_PYMOD],
-[AC_REQUIRE([AM_PATH_PYTHON])
-py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
-AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
-AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
-ifelse([$2],[], [prog="
-import sys
-try:
-        import $1
-except ImportError:
-        sys.exit(1)
-except:
-        sys.exit(0)
-sys.exit(0)"], [prog="
-import $1
-$1.$2"])
-if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
-  then
-    eval "py_cv_mod_$py_mod_var=yes"
-  else
-    eval "py_cv_mod_$py_mod_var=no"
-  fi
-])
-py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
-if test "x$py_val" != xno; then
-  AC_MSG_RESULT(yes)
-  ifelse([$3], [],, [$3
-])dnl
-else
-  AC_MSG_RESULT(no)
-  ifelse([$4], [],, [$4
-])dnl
-fi
-])
 
-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"`
+dnl a macro to check for ability to embed python
+dnl  AM_CHECK_PYTHON_LIBS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_LIBS
+AC_DEFUN([AM_CHECK_PYTHON_LIBS],
+[AC_REQUIRE([AM_CHECK_PYTHON_HEADERS])
+AC_MSG_CHECKING(for libraries required to embed python)
+dnl deduce PYTHON_LIBS
 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}"
+if test "x$PYTHON_LIBS" == x; then
+	PYTHON_LIBS="-L${py_prefix}/lib -lpython${PYTHON_VERSION}"
 fi
-AC_SUBST(PYTHON_INCLUDES)
+if test "x$PYTHON_LIB_LOC" == x; then
+	PYTHON_LIB_LOC="${py_prefix}/lib" 
+fi
+AC_SUBST(PYTHON_LIBS)
+AC_SUBST(PYTHON_LIB_LOC)
 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"
+save_LIBS="$LIBS"
+LIBS="$LIBS $PYTHON_LIBS"
+AC_TRY_LINK_FUNC(Py_Initialize, dnl
+         [LIBS="$save_LIBS"; AC_MSG_RESULT(yes); $1], dnl
+         [LIBS="$save_LIBS"; AC_MSG_RESULT(no); $2])
+
 ])
+
Index: plugins/python/Makefile.am
===================================================================
--- plugins/python/Makefile.am	(revision 0)
+++ plugins/python/Makefile.am	(revision 0)
@@ -0,0 +1,28 @@
+## Process this file with automake to produce Makefile.in
+
+libgladeui = $(top_builddir)/gladeui/libgladeui-1.la
+
+
+# libgladepython
+
+gladepython_LTLIBRARIES = libgladepython.la
+gladepythondir = $(pkglibdir)/modules
+
+libgladepython_la_SOURCES = glade-python.c
+libgladepython_la_CPPFLAGS = $(AM_CPPFLAGS)
+libgladepython_la_CFLAGS = \
+        -DG_LOG_DOMAIN=\"GladeUI-PYTHON\" \
+	-I$(top_srcdir)                  \
+	-I$(top_builddir)                \
+	$(PYTHON_INCLUDES)      \
+	$(PYGTK_CFLAGS)            \
+	$(GTK_CFLAGS)                    \
+	$(PLUGINS_WARN_CFLAGS)           \
+	$(AM_CPPFLAGS)
+libgladepython_la_LDFLAGS = -module -avoid-version $(PYTHON_LIBS) $(AM_LDFLAGS)
+libgladepython_la_LIBADD = $(libgladeui) $(PYTHON_LIBS)
+
+if PLATFORM_WIN32
+libgladepython_la_LDFLAGS += -no-undefined
+endif
+
Index: plugins/python/glade-python.c
===================================================================
--- plugins/python/glade-python.c	(revision 0)
+++ plugins/python/glade-python.c	(revision 0)
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2008 Juan Pablo Ugarte.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *   Juan Pablo Ugarte <[email protected]>
+ */
+
+#include <config.h>
+
+#include <gladeui/glade.h>
+
+#include <Python.h>
+#include <pygobject.h>
+
+static void
+python_init (void)
+{
+	char *argv[1];
+	
+	if (Py_IsInitialized ()) return;
+
+	Py_InitializeEx (0);
+
+	argv[0] = g_get_prgname ();
+	
+	PySys_SetArgv (1, argv);
+}
+
+static void
+glade_python_init_pygtk_check (gint req_major, gint req_minor, gint req_micro)
+{
+	PyObject *gobject, *mdict, *version;
+	int found_major, found_minor, found_micro;
+	
+	init_pygobject();
+	
+	gobject = PyImport_ImportModule("gobject");
+	mdict = PyModule_GetDict(gobject);
+        version = PyDict_GetItemString(mdict, "pygtk_version");
+	if (!version)
+	{
+		PyErr_SetString(PyExc_ImportError, "PyGObject version too old");
+		return;
+	}
+	if (!PyArg_ParseTuple(version, "iii", &found_major, &found_minor, &found_micro))
+		return;
+	if (req_major != found_major || req_minor >  found_minor ||
+	    (req_minor == found_minor && req_micro > found_micro))
+	{
+		PyErr_Format(PyExc_ImportError, 
+                     "PyGObject version mismatch, %d.%d.%d is required, "
+                     "found %d.%d.%d.", req_major, req_minor, req_micro,
+                     found_major, found_minor, found_micro);
+		return;
+	}
+}
+
+static void
+glade_python_setup ()
+{
+	gchar *command;
+	
+    	Py_SetProgramName (PACKAGE_NAME);
+	
+	/* Initialize the Python interpreter */
+	python_init ();
+	
+	/* Check and init pygobject >= 2.12.0 */
+	PyErr_Clear ();	
+	glade_python_init_pygtk_check (PYGTK_REQUIRED_MAJOR, PYGTK_REQUIRED_MINOR, PYGTK_REQUIRED_MICRO);
+	if (PyErr_Occurred ())
+	{
+		PyObject *ptype, *pvalue, *ptraceback;
+		PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+		g_warning ("Unable to load pygobject module >= %d.%d.%d, "
+			   "please make sure it is in python's path (sys.path). "
+			   "(use PYTHONPATH env variable to specify non default paths)\n%s",
+			   PYGTK_REQUIRED_MAJOR, PYGTK_REQUIRED_MINOR, PYGTK_REQUIRED_MICRO,
+			   PyString_AsString (pvalue));
+		PyErr_Clear ();
+		Py_Finalize ();
+		return;
+	}
+	
+	pyg_disable_warning_redirections ();
+
+	/* Set path */
+	command = g_strdup_printf ("import sys; sys.path+=['.', '%s', '%s'];\n",
+				   g_getenv (GLADE_ENV_CATALOG_PATH),
+				   glade_app_get_modules_dir ());
+	PyRun_SimpleString (command);
+	g_free (command);
+}
+
+
+void
+glade_python_init (const gchar *name)
+{
+	static gboolean init = TRUE;
+	gchar *import_sentence;
+	
+	if (init)
+	{
+		glade_python_setup ();
+		init = FALSE;
+	}
+	
+	/* Yeah, we use the catalog name as the library */
+	import_sentence = g_strdup_printf ("import %s;", name);
+	PyRun_SimpleString (import_sentence);
+	g_free (import_sentence);
+}
Index: plugins/gnome/glade-gnome.c
===================================================================
--- plugins/gnome/glade-gnome.c	(revision 1832)
+++ plugins/gnome/glade-gnome.c	(working copy)
@@ -41,7 +41,7 @@
 
 /* Catalog init function */
 void
-glade_gnomeui_init (void)
+glade_gnomeui_init (const gchar *name)
 {
 	gchar *argv[2] = {"glade-3", NULL};
 	GtkStockItem items [] = {
Index: plugins/Makefile.am
===================================================================
--- plugins/Makefile.am	(revision 1832)
+++ plugins/Makefile.am	(working copy)
@@ -5,3 +5,7 @@
 if BUILD_GNOME
 SUBDIRS += gnome
 endif
+
+if BUILD_PYTHON
+SUBDIRS += python
+endif
Index: configure.ac
===================================================================
--- configure.ac	(revision 1832)
+++ configure.ac	(working copy)
@@ -145,6 +145,33 @@
 
 AM_CONDITIONAL(BUILD_GNOME, test x"$have_gnome" = "xyes")
 
+dnl ================================================================
+dnl Python for optional python dev libs
+dnl ================================================================
+AC_ARG_ENABLE(python,
+    AS_HELP_STRING([--disable-python], [disable python catalog]),
+    check_python=$enableval, check_python=yes)
+
+if test x"$check_python" = x"yes"; then
+  PYGTK_REQUIRED_MAJOR=2
+  PYGTK_REQUIRED_MINOR=10
+  PYGTK_REQUIRED_MICRO=0
+  AM_CHECK_PYTHON_HEADERS(, [AC_MSG_ERROR(could not find Python headers)])
+  AM_CHECK_PYTHON_LIBS(, [AC_MSG_ERROR(could not find Python lib)])
+  PKG_CHECK_MODULES(PYGTK, [pygtk-2.0 >= 2.10.0], [have_python=yes],[have_python=no])
+
+  AC_DEFINE_UNQUOTED(PYGTK_REQUIRED_MAJOR, $PYGTK_REQUIRED_MAJOR, Pygtk mayor version required)
+  AC_DEFINE_UNQUOTED(PYGTK_REQUIRED_MINOR, $PYGTK_REQUIRED_MINOR, Pygtk minor version required)
+  AC_DEFINE_UNQUOTED(PYGTK_REQUIRED_MICRO, $PYGTK_REQUIRED_MICRO, Pygtk micro version required)
+
+  AC_SUBST(PYGTK_LIBS)
+  AC_SUBST(PYGTK_CFLAGS)
+else
+  have_python=no
+fi
+
+AM_CONDITIONAL(BUILD_PYTHON, test x"$have_python" = "xyes")
+
 # ==================================================================
 # Glade User Manual (requires gnome-doc-utils)
 # ==================================================================
@@ -218,6 +245,7 @@
 plugins/gnome/icons/Makefile
 plugins/gnome/icons/16x16/Makefile
 plugins/gnome/icons/22x22/Makefile
+plugins/python/Makefile
 po/Makefile.in
 doc/Makefile
 doc/version.xml
@@ -234,4 +262,5 @@
 	Compiler:		 ${CC}
 	GTK+ UNIX Print Widgets: ${have_unix_print}
 	GNOME UI Widgets:	 ${have_gnome}
+	PYTHON Widgets support:	 ${have_python}
 "
Index: gladeui/glade-catalog.c
===================================================================
--- gladeui/glade-catalog.c	(revision 1832)
+++ gladeui/glade-catalog.c	(working copy)
@@ -33,7 +33,7 @@
 #include <glib.h>
 #include <glib/gi18n-lib.h>
 
-typedef void   (*GladeCatalogInitFunc) (void);
+typedef void   (*GladeCatalogInitFunc) (const gchar *name);
 
 struct _GladeCatalog
 {
@@ -535,7 +535,7 @@
 	{
 		catalog = l->data;
 		if (catalog->init_function)
-			catalog->init_function ();
+			catalog->init_function (catalog->name);
 	}
 	
 	for (l = catalogs; l; l = l->next)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.