[gnome-python] Bug 507174 – Convert from popt to GOption



commit d62b041db415ff2e072bc55b064f6c3e7696f7af
Author: Tristan Hill <stan saticed me uk>
Date:   Sun Apr 26 12:22:22 2009 +0100

    Bug 507174 â?? Convert from popt to GOption
---
 Makefile.am              |    3 +-
 configure.ac             |    4 +
 examples/popt/goption.py |   36 +++++++
 gnome/gnome.override     |  239 +++++++++++++++++++++++++++++-----------------
 wscript                  |    2 +
 5 files changed, 197 insertions(+), 87 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index a49edad..55649f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -64,7 +64,8 @@ EXTRA_DIST = \
   examples/vfs/pygvfsmethod/README \
   examples/vfs/pygvfsmethod/pyfs.conf \
   examples/vfs/pygvfsmethod/pyfs.py \
-  examples/popt/popt.py
+  examples/popt/popt.py \
+  examples/popt/goption.py
 
 
 $(srcdir)/ChangeLog:
diff --git a/configure.ac b/configure.ac
index 5a02895..62e9ca4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,6 +24,7 @@ m4_define(gconf_required_version,             2.11.1)
 m4_define(bonobo_activation_required_version, 2.8.0)
 m4_define(libbonobo_required_version,         2.8.0)
 m4_define(libbonoboui_required_version,       2.8.0)
+m4_define(pyobject_required_version,          2.15.0)
 
 AC_INIT(gnome-python, gnome_python_version,
         [http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-python])
@@ -69,6 +70,9 @@ AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers or library)
 dnl make the python compiler used globally
 CC="$PYTHON_CC"
 
+dnl check for pygobject
+PKG_CHECK_MODULES(PYGOBJECT, pygobject-2.0 >= pygobject_required_version)
+
 dnl check for pygtk
 PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= pygtk_required_version)
 AC_SUBST(PYGTK_CFLAGS)
diff --git a/examples/popt/goption.py b/examples/popt/goption.py
new file mode 100644
index 0000000..6541ebb
--- /dev/null
+++ b/examples/popt/goption.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+"""
+http://live.gnome.org/GnomeGoals/PoptGOption
+
+Since GNOME 2.10, GLib provides GOption, a commandline option parser.
+The help output of your program will be much nicer :-) And it will enable us to
+slowly get rid of popt (even if libgnome will still have to depend on it for
+compatibility reasons). 
+
+"""
+
+import sys
+
+import glib
+import gnome
+
+def callback(name, value, group):
+    if name == "--example":
+        print "example got %s" % value
+    elif name in ("-o", "--option"):
+        print "option"
+    else:
+        print "remaining:", value
+
+group = glib.OptionGroup(None, None, None, callback)
+group.add_entries([("example", "\0", 0, "An example option",
+                    "option"),
+                   ("option", "o", glib.OPTION_FLAG_NO_ARG, "An option",
+                    None),
+                   (glib.OPTION_REMAINING, "\0", 0, "", None),
+                  ])
+context = glib.OptionContext("argument")
+context.set_main_group(group)
+
+prog = gnome.init("myprog", "1.0", argv=sys.argv, option_context=context)
diff --git a/gnome/gnome.override b/gnome/gnome.override
index 0a67618..ba7c42d 100644
--- a/gnome/gnome.override
+++ b/gnome/gnome.override
@@ -278,6 +278,117 @@ popt_build_table(PyObject *table)
     return NULL;
 }
 
+static PyTypeObject *
+get_option_context_type()
+{
+    PyObject *module;
+    PyTypeObject *type;
+    if ((module = PyImport_ImportModule("glib")) != NULL) {
+        type = (PyTypeObject *)PyObject_GetAttrString(module, "OptionContext");
+        Py_DECREF(module);
+        if (type == NULL) {
+            PyErr_SetString(PyExc_ImportError,
+                            "cannot import OptionContext from glib");
+            return NULL;
+        } else
+            return type;
+    } else {
+        PyErr_SetString(PyExc_ImportError, "could not import glib");
+        return NULL;
+    }
+}
+
+static int
+build_gnome_init_params(PyObject *py_properties,
+                        struct poptOption *popt_table, int flags,
+                        PyObject *option_context,
+                        PyObject **py_properties_items, Py_ssize_t *nparams,
+                        GParameter **params_ptr)
+{
+    Py_ssize_t py_properties_len = -1;
+    PyObject *items = NULL;
+    if (py_properties) {
+        *py_properties_items = items = PyMapping_Items(py_properties);
+        if (!items)
+            return 0;
+        *nparams = py_properties_len = PyList_GET_SIZE(items);
+    } else
+        *nparams = 0;
+    if (popt_table)
+        *nparams += 2;
+    if (option_context)
+        *nparams += 1;
+
+    GParameter *params = NULL;
+    if (*nparams) {
+        params = g_new0(GParameter, *nparams);
+        if (!params) {
+            PyErr_NoMemory();
+            return 0;
+        }
+    }
+    Py_ssize_t i = 0;
+    if (py_properties) {
+        PyObject *item, *key, *val;
+        GType type;
+        for (; i < py_properties_len; ++i) {
+            item = PyList_GET_ITEM(items, i);
+            key = PyTuple_GET_ITEM(item, 0);
+            val = PyTuple_GET_ITEM(item, 1);
+            type = pyg_type_from_object((PyObject *) val->ob_type);
+            if (type == 0)
+                goto error;
+            params[i].name = PyString_AsString(key);
+            g_value_init(&params[i].value, type);
+            if (pyg_value_from_pyobject(&params[i].value, val))
+                goto error;
+            continue;
+            error:
+            {
+                int j;
+                for (j = 0; j < i; ++j)
+                    g_value_unset(&params[j].value);
+                g_free(params);
+                Py_DECREF(items);
+                return 0;
+            }
+        }
+    }
+    if (popt_table) {
+        params[i].name = GNOME_PARAM_POPT_TABLE;
+        g_value_init(&params[i].value, G_TYPE_POINTER);
+        g_value_set_pointer(&params[i].value, popt_table);
+        i++;
+        params[i].name = GNOME_PARAM_POPT_FLAGS;
+        g_value_init(&params[i].value, G_TYPE_INT);
+        g_value_set_int(&params[i].value, flags);
+    }
+    if (option_context) {
+        params[i].name = GNOME_PARAM_GOPTION_CONTEXT;
+        g_value_init(&params[i].value, G_TYPE_POINTER);
+        PyObject* context = PyObject_CallMethod(option_context, "_get_context", NULL);
+        g_value_set_pointer(&params[0].value, PyCObject_AsVoidPtr(context));
+        Py_DECREF(context);
+    }
+
+    *params_ptr = params;
+    return 1;
+}
+
+static void
+free_gnome_init_params(PyObject *py_properties_items, Py_ssize_t nparams,
+                       GParameter *params)
+{
+    Py_XDECREF(py_properties_items);
+    if (nparams)
+    {
+        Py_ssize_t i;
+        for (i = 0; i < nparams; ++i)
+            g_value_unset(&params[i].value);
+        g_free(params);
+    }
+}
+
 static PyObject *
 _wrap_gnome_program_init(PyObject *self, 
                          PyObject *args, 
@@ -285,13 +396,13 @@ _wrap_gnome_program_init(PyObject *self,
 {
     static char *kwlist[] = { "app_id", "app_version", "module_info", 
                               "argv", "popt_table", "popt_flags",
-                              "properties", NULL };
+                              "option_context", "properties", NULL };
     gchar *app_id;
     gchar *app_version;
     PyObject *av = NULL;
     int argc;
     char **argv, **leftover_args;
-    int i, len;
+    int i;
     GnomeModuleInfo *moduleinfo;
     GnomeProgram *program;
     struct sigaction sa;
@@ -301,22 +412,32 @@ _wrap_gnome_program_init(PyObject *self,
     PyObject *m = NULL;
     PyObject *argdict, *py_leftover_args;
     PyObject *tmpobj;
+    PyObject *option_context = NULL;
     PyObject *py_properties = NULL;
     PyObject *py_properties_items = NULL;
     GParameter *params;
-    int nparams;
+    Py_ssize_t nparams;
     poptContext ctx = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, 
-                                     "ss|OO!O!iO!:gnome.program_init", kwlist, 
-                                     &app_id, &app_version, &m, 
-                                     &PyList_Type, &av, 
-                                     &PyList_Type, &table, 
+    PyTypeObject *py_goption_context_type = get_option_context_type();
+    if (!py_goption_context_type) {
+        return NULL;
+    }
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "ss|OO!O!iO!O!:gnome.program_init",
+                                     kwlist,
+                                     &app_id, &app_version, &m,
+                                     &PyList_Type, &av,
+                                     &PyList_Type, &table,
                                      &flags,
+                                     py_goption_context_type, &option_context,
                                      &PyDict_Type, &py_properties)) {
         return NULL;
     }
 
+    Py_DECREF(py_goption_context_type);
+
     if (m == NULL) {
         moduleinfo = (GnomeModuleInfo *) libgnome_module_info_get();
     } else {
@@ -329,92 +450,40 @@ _wrap_gnome_program_init(PyObject *self,
         }
     }
 
-    if (table != NULL) {
-        popt_table = popt_build_table(table);
-        if (popt_table == NULL)
-            return NULL;
-    }
-
     if (av == NULL) {
           /* ... use argc and argv from sys */
         av = PySys_GetObject("argv");
     }
+    argc = PyList_Size(av);
+    argv = g_new(char *, argc);
+    if (!argv)
+        return PyErr_NoMemory();
+    for (i = 0; i < argc; i++)
+        argv[i] = PyString_AsString(PyList_GetItem(av, i));
 
-    if (py_properties)
-    {
-        PyObject *items, *item, *key, *val;
-        py_properties_items = items = PyMapping_Items(py_properties);
-        if (!items)
+    if (table != NULL) {
+        popt_table = popt_build_table(table);
+        if (!popt_table)
             return NULL;
-        len = PyList_GET_SIZE(items);
-        nparams = popt_table? len + 2 : len;
-        params = g_new0(GParameter, nparams);
-        for (i = 0; i < len; ++i) {
-            GType type;
-            item = PyList_GET_ITEM(items, i);
-            key = PyTuple_GET_ITEM(item, 0);
-            val = PyTuple_GET_ITEM(item, 1);
-            type = pyg_type_from_object((PyObject *) val->ob_type);
-            if (type == 0)
-                goto error;
-            params[i].name = PyString_AsString(key);
-            g_value_init(&params[i].value, type);
-            if (pyg_value_from_pyobject(&params[i].value, val))
-                goto error;
-            continue;
-            error:
-            {
-                int j;
-                for (j = 0; j < i; ++j)
-                    g_value_unset(&params[j].value);
-                g_free(params);
-                Py_DECREF(items);
-                if (popt_table)
-                    popt_destroy_table(popt_table);
-                return NULL;
-            }
-        }
-    } else {
-        if (popt_table) {
-            nparams = 2;
-            params = g_new0(GParameter, nparams);
-            i = 0;
-        } else {
-            nparams = 0;
-            params = NULL;
-            i = 0;
-        }
     }
 
-    if (popt_table) {
-        params[i].name = GNOME_PARAM_POPT_TABLE;
-        g_value_init(&params[i].value, G_TYPE_POINTER);
-        g_value_set_pointer(&params[i].value, popt_table);
-        i++;
-        params[i].name = GNOME_PARAM_POPT_FLAGS;
-        g_value_init(&params[i].value, G_TYPE_INT);
-        g_value_set_int(&params[i].value, flags);
+    if (!build_gnome_init_params(py_properties, popt_table, flags,
+                                 option_context,
+                                 &py_properties_items, &nparams, &params)) {
+        if (popt_table)
+            popt_destroy_table(popt_table);
+        return NULL;
     }
 
-    argc = PyList_Size(av);
-    argv = g_new(char *, argc);
-    for (i = 0; i < argc; i++)
-        argv[i] = PyString_AsString(PyList_GetItem(av, i));
-
     memset(&sa, 0, sizeof(sa));
     sigaction(SIGCHLD, NULL, &sa);
 
-
-      /* --- */
     program = gnome_program_init_paramv(GNOME_TYPE_PROGRAM,
-                                        app_id, app_version, 
+                                        app_id, app_version,
                                         moduleinfo,  argc, argv,
-                                        nparams, params);
+                                        (guint) nparams, params);
 
-    Py_XDECREF(py_properties_items);
-    for (i = 0; i < nparams; ++i)
-        g_value_unset(&params[i].value);
-    g_free(params);
+    free_gnome_init_params(py_properties_items, nparams, params);
 
     if (!program) {
         PyErr_SetString(PyExc_RuntimeError,
@@ -431,12 +500,11 @@ _wrap_gnome_program_init(PyObject *self,
     setlocale(LC_NUMERIC, "C");
 #endif
 
-    if (popt_table)
-    {
+    if (popt_table) {
           /* get argdict, store in object for later use */
         argdict = (PyObject *) popt_table[0].descrip;
         Py_INCREF(argdict);
-        g_object_set_data_full(G_OBJECT(program), 
+        g_object_set_data_full(G_OBJECT(program),
                                "gnome-python-popt-argdict",
                                argdict, __py_object_free);
 
@@ -445,8 +513,7 @@ _wrap_gnome_program_init(PyObject *self,
         leftover_args = (char **) poptGetArgs(ctx);
         py_leftover_args = PyList_New(0);
         if (!py_leftover_args) {
-            PyErr_NoMemory();
-            return NULL;
+            return PyErr_NoMemory();
         }
         if (leftover_args) {
             for (i = 0; leftover_args[i]; i++) {
@@ -463,7 +530,7 @@ _wrap_gnome_program_init(PyObject *self,
                 Py_DECREF(tmpobj);
             }
         }
-        g_object_set_data_full(G_OBJECT(program), 
+        g_object_set_data_full(G_OBJECT(program),
                                "gnome-python-popt-leftover-args",
                                py_leftover_args, __py_object_free);
 
@@ -473,11 +540,11 @@ _wrap_gnome_program_init(PyObject *self,
 #if (defined(HAVE_PRCTL) && defined(PR_SET_NAME)) || defined(HAVE_SETPROCTITLE)
     if (argv && argv[0]) {
 #if defined(HAVE_PRCTL) && defined(PR_SET_NAME)
-	if (prctl(PR_SET_NAME, (unsigned long) argv[0], 0, 0, 0)) {
+    if (prctl(PR_SET_NAME, (unsigned long) argv[0], 0, 0, 0)) {
             g_warning("prctl() failed");
         }
 #elif defined(HAVE_SETPROCTITLE)
-	setproctitle("-%s", argv[0]);
+    setproctitle("-%s", argv[0]);
 #endif
     }
 #endif
diff --git a/wscript b/wscript
index 26cfccf..c1a0baa 100644
--- a/wscript
+++ b/wscript
@@ -81,6 +81,8 @@ def configure(conf):
     conf.pkg_check_modules('PYGTK', 'pygtk-2.0 >= %s' % ('.'.join([str(x) for x in pygtk_version]),))
     conf.env['PYGTK_DEFSDIR'] = conf.pkg_check_module_variable('pygtk-2.0', 'defsdir')
 
+    conf.pkg_check_modules('PYGOBJECT', 'pygobject-2.0 >= 2.17.0', mandatory=True)
+
     if not conf.find_program('pygobject-codegen-2.0', var='CODEGEN'):
         if not conf.find_program('pygtk-codegen-2.0', var='CODEGEN'):
             Params.fatal("Could not find pygobject/pygtk codegen")



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