summaryrefslogtreecommitdiffstats
path: root/glib
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2008-07-26 09:11:08 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-07-26 09:11:08 +0000
commit59e8488b49d360992d8df5ca0664ba742411c933 (patch)
treeefd6663aea4774cc469617a3477996fc7960f396 /glib
parent7079b546e06dd77b61cd1ba4692a077a85b9e033 (diff)
downloadpygobject-59e8488b49d360992d8df5ca0664ba742411c933.tar.gz
pygobject-59e8488b49d360992d8df5ca0664ba742411c933.tar.xz
pygobject-59e8488b49d360992d8df5ca0664ba742411c933.zip
Move option over from gobject to glib.
2008-07-26 Johan Dahlin <johan@gnome.org> * glib/Makefile.am: * glib/glibmodule.c (pyglib_register_constants), (init_glib): * glib/option.py: * glib/pyglib.c (pyglib_init), (pyglib_option_group_transfer_group), (pyglib_option_group_new), (pyglib_option_context_new): * glib/pyglib.h: * glib/pygoptioncontext.c (pyg_option_context_parse), (pyg_option_context_set_main_group), (pyg_option_context_add_group), (pyglib_option_context_register_types): * glib/pygoptioncontext.h: * glib/pygoptiongroup.c (arg_func), (pyglib_option_group_register_types): * glib/pygoptiongroup.h: * gobject/Makefile.am: * gobject/__init__.py: * gobject/gobjectmodule.c (init_gobject): * gobject/option.py: * gobject/pygobject-private.h: * gobject/pygoptioncontext.c: * gobject/pygoptiongroup.c: Move option over from gobject to glib. svn path=/trunk/; revision=860
Diffstat (limited to 'glib')
-rw-r--r--glib/Makefile.am29
-rw-r--r--glib/glibmodule.c33
-rw-r--r--glib/option.py347
-rw-r--r--glib/pyglib.c99
-rw-r--r--glib/pyglib.h6
-rw-r--r--glib/pygoptioncontext.c325
-rw-r--r--glib/pygoptioncontext.h37
-rw-r--r--glib/pygoptiongroup.c305
-rw-r--r--glib/pygoptiongroup.h40
9 files changed, 1205 insertions, 16 deletions
diff --git a/glib/Makefile.am b/glib/Makefile.am
index c2cbf47..e5be61f 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -10,7 +10,8 @@ pkgpyexecdir = $(pyexecdir)/gtk-2.0
pyglibdir = $(pkgpyexecdir)/glib
pyglib_PYTHON = \
- __init__.py
+ __init__.py \
+ option.py
pyglib_LTLIBRARIES = _glib.la
common_ldflags = -module -avoid-version
@@ -28,17 +29,21 @@ libpyglib_2_0_la_SOURCES = \
_glib_la_CFLAGS = $(GLIB_CFLAGS)
_glib_la_LDFLAGS = $(common_ldflags) -export-symbols-regex init_glib
_glib_la_LIBADD = $(GLIB_LIBS) libpyglib-2.0.la
-_glib_la_SOURCES = \
- glibmodule.c \
- pygiochannel.c \
- pygiochannel.h \
- pygmaincontext.c \
- pygmaincontext.h \
- pygmainloop.c \
- pygmainloop.h \
- pygsource.c \
- pygsource.h \
- pygspawn.c \
+_glib_la_SOURCES = \
+ glibmodule.c \
+ pygiochannel.c \
+ pygiochannel.h \
+ pygoptioncontext.c \
+ pygoptioncontext.h \
+ pygoptiongroup.c \
+ pygoptiongroup.h \
+ pygmaincontext.c \
+ pygmaincontext.h \
+ pygmainloop.c \
+ pygmainloop.h \
+ pygsource.c \
+ pygsource.h \
+ pygspawn.c \
pygspawn.h
if PLATFORM_WIN32
diff --git a/glib/glibmodule.c b/glib/glibmodule.c
index b4a5b09..dc7afca 100644
--- a/glib/glibmodule.c
+++ b/glib/glibmodule.c
@@ -32,6 +32,8 @@
#include "pygiochannel.h"
#include "pygmaincontext.h"
#include "pygmainloop.h"
+#include "pygoptioncontext.h"
+#include "pygoptiongroup.h"
#include "pygsource.h"
#include "pygspawn.h"
@@ -679,8 +681,35 @@ pyglib_register_constants(PyObject *m)
G_IO_FLAG_GET_MASK);
PyModule_AddIntConstant(m, "IO_FLAG_SET_MASK",
G_IO_FLAG_SET_MASK);
-
+
+ PyModule_AddIntConstant(m, "OPTION_FLAG_HIDDEN",
+ G_OPTION_FLAG_HIDDEN);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_IN_MAIN",
+ G_OPTION_FLAG_IN_MAIN);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_REVERSE",
+ G_OPTION_FLAG_REVERSE);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_NO_ARG",
+ G_OPTION_FLAG_NO_ARG);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_FILENAME",
+ G_OPTION_FLAG_FILENAME);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_OPTIONAL_ARG",
+ G_OPTION_FLAG_OPTIONAL_ARG);
+ PyModule_AddIntConstant(m, "OPTION_FLAG_NOALIAS",
+ G_OPTION_FLAG_NOALIAS);
+
+ PyModule_AddIntConstant(m, "OPTION_ERROR_UNKNOWN_OPTION",
+ G_OPTION_ERROR_UNKNOWN_OPTION);
+ PyModule_AddIntConstant(m, "OPTION_ERROR_BAD_VALUE",
+ G_OPTION_ERROR_BAD_VALUE);
+ PyModule_AddIntConstant(m, "OPTION_ERROR_FAILED",
+ G_OPTION_ERROR_FAILED);
+
+ PyModule_AddStringConstant(m, "OPTION_REMAINING",
+ G_OPTION_REMAINING);
+ PyModule_AddStringConstant(m, "OPTION_ERROR",
+ (char*) g_quark_to_string(G_OPTION_ERROR));
}
+
DL_EXPORT(void)
init_glib(void)
{
@@ -698,4 +727,6 @@ init_glib(void)
pyglib_maincontext_register_types(d);
pyglib_source_register_types(d);
pyglib_spawn_register_types(d);
+ pyglib_option_context_register_types(d);
+ pyglib_option_group_register_types(d);
}
diff --git a/glib/option.py b/glib/option.py
new file mode 100644
index 0000000..034b7b3
--- /dev/null
+++ b/glib/option.py
@@ -0,0 +1,347 @@
+# -*- Mode: Python -*-
+# pygobject - Python bindings for the GObject library
+# Copyright (C) 2006 Johannes Hoelzl
+#
+# glib/option.py: GOption command line parser
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+"""GOption command line parser
+
+Extends optparse to use the GOptionGroup, GOptionEntry and GOptionContext
+objects. So it is possible to use the gtk, gnome_program and gstreamer command
+line groups and contexts.
+
+Use this interface instead of the raw wrappers of GOptionContext and
+GOptionGroup in glib.
+"""
+
+import sys
+import optparse
+from optparse import OptParseError, OptionError, OptionValueError, \
+ BadOptionError, OptionConflictError
+
+import _glib
+
+__all__ = [
+ "OptParseError",
+ "OptionError",
+ "OptionValueError",
+ "BadOptionError",
+ "OptionConflictError"
+ "Option",
+ "OptionGroup",
+ "OptionParser",
+ "make_option",
+]
+
+class Option(optparse.Option):
+ """Represents a command line option
+
+ To use the extended possibilities of the GOption API Option
+ (and make_option) are extended with new types and attributes.
+
+ Types:
+ filename The supplied arguments are read as filename, GOption
+ parses this type in with the GLib filename encoding.
+
+ Attributes:
+ optional_arg This does not need a arguement, but it can be supplied.
+ hidden The help list does not show this option
+ in_main This option apears in the main group, this should only
+ be used for backwards compatibility.
+
+ Use Option.REMAINING as option name to get all positional arguments.
+
+ NOTE: Every argument to an option is passed as utf-8 coded string, the only
+ exception are options which use the 'filename' type, its arguments
+ are passed as strings in the GLib filename encoding.
+
+ For further help, see optparse.Option.
+ """
+ TYPES = optparse.Option.TYPES + (
+ 'filename',
+ )
+
+ ATTRS = optparse.Option.ATTRS + [
+ 'hidden',
+ 'in_main',
+ 'optional_arg',
+ ]
+
+ REMAINING = '--' + _glib.OPTION_REMAINING
+
+ def __init__(self, *args, **kwargs):
+ optparse.Option.__init__(self, *args, **kwargs)
+ if not self._long_opts:
+ raise ValueError("%s at least one long option name.")
+
+ if len(self._long_opts) < len(self._short_opts):
+ raise ValueError(
+ "%s at least more long option names than short option names.")
+
+ if not self.help:
+ raise ValueError("%s needs a help message.", self._long_opts[0])
+
+
+ def _set_opt_string(self, opts):
+ if self.REMAINING in opts:
+ self._long_opts.append(self.REMAINING)
+ optparse.Option._set_opt_string(self, opts)
+ if len(self._short_opts) > len(self._long_opts):
+ raise OptionError("goption.Option needs more long option names "
+ "than short option names")
+
+ def _to_goptionentries(self):
+ flags = 0
+
+ if self.hidden:
+ self.flags |= _glib.OPTION_FLAG_HIDDEN
+
+ if self.in_main:
+ self.flags |= _glib.OPTION_FLAG_IN_MAIN
+
+ if self.takes_value():
+ if self.optional_arg:
+ flags |= _glib.OPTION_FLAG_OPTIONAL_ARG
+ else:
+ flags |= _glib.OPTION_FLAG_NO_ARG
+
+ if self.type == 'filename':
+ flags |= _glib.OPTION_FLAG_FILENAME
+
+ for (long_name, short_name) in zip(self._long_opts, self._short_opts):
+ yield (long_name[2:], short_name[1], flags, self.help, self.metavar)
+
+ for long_name in self._long_opts[len(self._short_opts):]:
+ yield (long_name[2:], '\0', flags, self.help, self.metavar)
+
+class OptionGroup(optparse.OptionGroup):
+ """A group of command line options.
+
+ Arguements:
+ name: The groups name, used to create the
+ --help-{name} option
+ description: Shown as title of the groups help view
+ help_description: Shown as help to the --help-{name} option
+ option_list: The options used in this group, must be option.Option()
+ defaults: A dicitionary of default values
+ translation_domain: Sets the translation domain for gettext().
+
+ NOTE: This OptionGroup does not exactly map the optparse.OptionGroup
+ interface. There is no parser object to supply, but it is possible
+ to set default values and option_lists. Also the default values and
+ values are not shared with the OptionParser.
+
+ To pass a OptionGroup into a function which expects a GOptionGroup (e.g.
+ gnome_program_init() ). OptionGroup.get_option_group() can be used.
+
+ For further help, see optparse.OptionGroup.
+ """
+ def __init__(self, name, description, help_description="",
+ option_list=None, defaults=None,
+ translation_domain=None):
+ optparse.OptionContainer.__init__(self, Option, 'error', description)
+ self.name = name
+ self.parser = None
+ self.help_description = help_description
+ if defaults:
+ self.defaults = defaults
+
+ self.values = None
+
+ self.translation_domain = translation_domain
+
+ if option_list:
+ for option in option_list:
+ self.add_option(option)
+
+ def _create_option_list(self):
+ self.option_list = []
+ self._create_option_mappings()
+
+ def _to_goptiongroup(self, parser):
+ def callback(option_name, option_value, group):
+ if option_name.startswith('--'):
+ opt = self._long_opt[option_name]
+ else:
+ opt = self._short_opt[option_name]
+
+ try:
+ opt.process(option_name, option_value, self.values, parser)
+ except OptionValueError, error:
+ gerror = _glib.GError(str(error))
+ gerror.domain = _glib.OPTION_ERROR
+ gerror.code = _glib.OPTION_ERROR_BAD_VALUE
+ gerror.message = str(error)
+ raise gerror
+
+ group = _glib.OptionGroup(self.name, self.description,
+ self.help_description, callback)
+ if self.translation_domain:
+ group.set_translation_domain(self.translation_domain)
+
+ entries = []
+ for option in self.option_list:
+ entries.extend(option._to_goptionentries())
+ group.add_entries(entries)
+
+ return group
+
+ def get_option_group(self, parser = None):
+ """ Returns the corresponding GOptionGroup object.
+
+ Can be used as parameter for gnome_program_init(), gtk_init().
+ """
+ self.set_values_to_defaults()
+ return self._to_goptiongroup(parser)
+
+ def set_values_to_defaults(self):
+ for option in self.option_list:
+ default = self.defaults.get(option.dest)
+ if isinstance(default, basestring):
+ opt_str = option.get_opt_string()
+ self.defaults[option.dest] = option.check_value(
+ opt_str, default)
+ self.values = optparse.Values(self.defaults)
+
+class OptionParser(optparse.OptionParser):
+ """Command line parser with GOption support.
+
+ NOTE: The OptionParser interface is not the exactly the same as the
+ optparse.OptionParser interface. Especially the usage parameter
+ is only used to show the metavar of the arguements.
+
+ Attribues:
+ help_enabled: The --help, --help-all and --help-{group}
+ options are enabled (default).
+ ignore_unknown_options: Do not throw a exception when a option is not
+ knwon, the option will be in the result list.
+
+ OptionParser.add_option_group() does not only accept OptionGroup instances
+ but also glib.OptionGroup, which is returned by gtk_get_option_group().
+
+ Only glib.option.OptionGroup and glib.option.Option instances should
+ be passed as groups and options.
+
+ For further help, see optparse.OptionParser.
+ """
+
+ def __init__(self, *args, **kwargs):
+ if 'option_class' not in kwargs:
+ kwargs['option_class'] = Option
+ self.help_enabled = kwargs.pop('help_enabled', True)
+ self.ignore_unknown_options = kwargs.pop('ignore_unknown_options',
+ False)
+ optparse.OptionParser.__init__(self, add_help_option=False,
+ *args, **kwargs)
+
+ def set_usage(self, usage):
+ if usage is None:
+ self.usage = ''
+ elif usage.startswith("%prog"):
+ self.usage = usage[len("%prog"):]
+ else:
+ self.usage = usage
+
+ def _to_goptioncontext(self, values):
+ if self.description:
+ parameter_string = self.usage + " - " + self.description
+ else:
+ parameter_string = self.usage
+ context = _glib.OptionContext(parameter_string)
+ context.set_help_enabled(self.help_enabled)
+ context.set_ignore_unknown_options(self.ignore_unknown_options)
+
+ for option_group in self.option_groups:
+ if isinstance(option_group, _glib.OptionGroup):
+ g_group = option_group
+ else:
+ g_group = option_group.get_option_group(self)
+ context.add_group(g_group)
+
+ def callback(option_name, option_value, group):
+ if option_name.startswith('--'):
+ opt = self._long_opt[option_name]
+ else:
+ opt = self._short_opt[option_name]
+ opt.process(option_name, option_value, values, self)
+
+ main_group = _glib.OptionGroup(None, None, None, callback)
+ main_entries = []
+ for option in self.option_list:
+ main_entries.extend(option._to_goptionentries())
+ main_group.add_entries(main_entries)
+ context.set_main_group(main_group)
+
+ return context
+
+ def add_option_group(self, *args, **kwargs):
+ if isinstance(args[0], basestring):
+ optparse.OptionParser.add_option_group(self,
+ OptionGroup(self, *args, **kwargs))
+ return
+ elif len(args) == 1 and not kwargs:
+ if isinstance(args[0], OptionGroup):
+ if not args[0].parser:
+ args[0].parser = self
+ if args[0].parser is not self:
+ raise ValueError("invalid OptionGroup (wrong parser)")
+ if isinstance(args[0], _glib.OptionGroup):
+ self.option_groups.append(args[0])
+ return
+ optparse.OptionParser.add_option_group(self, *args, **kwargs)
+
+ def _get_all_options(self):
+ options = self.option_list[:]
+ for group in self.option_groups:
+ if isinstance(group, optparse.OptionGroup):
+ options.extend(group.option_list)
+ return options
+
+ def _process_args(self, largs, rargs, values):
+ context = self._to_goptioncontext(values)
+
+ # _process_args() returns the remaining parameters in rargs.
+ # The prepended program name is used to all g_set_prgname()
+ # The program name is cut away so it doesn't appear in the result.
+ rargs[:] = context.parse([sys.argv[0]] + rargs)[1:]
+
+ def parse_args(self, args=None, values=None):
+ old_args = args or []
+ try:
+ options, args = optparse.OptionParser.parse_args(
+ self, args, values)
+ except _glib.GError, error:
+ if error.domain != _glib.OPTION_ERROR:
+ raise
+ if error.code == _glib.OPTION_ERROR_BAD_VALUE:
+ raise OptionValueError(error.message)
+ elif error.code == _glib.OPTION_ERROR_UNKNOWN_OPTION:
+ raise BadOptionError(error.message)
+ elif error.code == _glib.OPTION_ERROR_FAILED:
+ raise OptParseError(error.message)
+ else:
+ raise
+
+ for group in self.option_groups:
+ for key, value in group.values.__dict__.items():
+ options.ensure_value(key, value)
+
+ args = args[2:-len(old_args)]
+ return options, args
+
+make_option = Option
diff --git a/glib/pyglib.c b/glib/pyglib.c
index 6fbc5bb..f101ec1 100644
--- a/glib/pyglib.c
+++ b/glib/pyglib.c
@@ -28,6 +28,8 @@
#include "pyglib.h"
#include "pyglib-private.h"
#include "pygmaincontext.h"
+#include "pygoptioncontext.h"
+#include "pygoptiongroup.h"
static struct _PyGLib_Functions *_PyGLib_API;
static int pyglib_thread_state_tls_key;
@@ -35,6 +37,12 @@ static int pyglib_thread_state_tls_key;
static PyTypeObject *_PyGMainContext_Type;
#define PyGMainContext_Type (*_PyGMainContext_Type)
+static PyTypeObject *_PyGOptionGroup_Type;
+#define PyGOptionGroup_Type (*_PyGOptionGroup_Type)
+
+static PyTypeObject *_PyGOptionContext_Type;
+#define PyGOptionContext_Type (*_PyGOptionContext_Type)
+
void
pyglib_init(void)
{
@@ -69,6 +77,8 @@ pyglib_init(void)
}
_PyGMainContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "MainContext");
+ _PyGOptionGroup_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionGroup");
+ _PyGOptionContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionContext");
}
void
@@ -340,6 +350,92 @@ pyglib_main_context_new(GMainContext *context)
}
/**
+ * pyg_option_group_transfer_group:
+ * @group: a GOptionGroup wrapper
+ *
+ * This is used to transfer the GOptionGroup to a GOptionContext. After this
+ * is called, the calle must handle the release of the GOptionGroup.
+ *
+ * When #NULL is returned, the GOptionGroup was already transfered.
+ *
+ * Returns: Either #NULL or the wrapped GOptionGroup.
+ */
+GOptionGroup *
+pyglib_option_group_transfer_group(PyObject *obj)
+{
+ PyGOptionGroup *self = (PyGOptionGroup*)obj;
+
+ if (self->is_in_context)
+ return NULL;
+
+ self->is_in_context = TRUE;
+
+ /* Here we increase the reference count of the PyGOptionGroup, because now
+ * the GOptionContext holds an reference to us (it is the userdata passed
+ * to g_option_group_new().
+ *
+ * The GOptionGroup is freed with the GOptionContext.
+ *
+ * We set it here because if we would do this in the init method we would
+ * hold two references and the PyGOptionGroup would never be freed.
+ */
+ Py_INCREF(self);
+
+ return self->group;
+}
+
+/**
+ * pyglib_option_group_new:
+ * @group: a GOptionGroup
+ *
+ * The returned GOptionGroup can't be used to set any hooks, translation domains
+ * or add entries. It's only intend is, to use for GOptionContext.add_group().
+ *
+ * Returns: the GOptionGroup wrapper.
+ */
+PyObject *
+pyglib_option_group_new (GOptionGroup *group)
+{
+ PyGOptionGroup *self;
+
+ self = (PyGOptionGroup *)PyObject_NEW(PyGOptionGroup,
+ &PyGOptionGroup_Type);
+ if (self == NULL)
+ return NULL;
+
+ self->group = group;
+ self->other_owner = TRUE;
+ self->is_in_context = FALSE;
+
+ return (PyObject *)self;
+}
+
+/**
+ * pyglib_option_context_new:
+ * @context: a GOptionContext
+ *
+ * Returns: A new GOptionContext wrapper.
+ */
+PyObject *
+pyglib_option_context_new (GOptionContext *context)
+{
+ PyGOptionContext *self;
+
+ self = (PyGOptionContext *)PyObject_NEW(PyGOptionContext,
+ &PyGOptionContext_Type);
+ if (self == NULL)
+ return NULL;
+
+ self->context = context;
+ self->main_group = NULL;
+
+ return (PyObject *)self;
+}
+
+
+/****** Private *****/
+
+/**
* _pyglib_destroy_notify:
* @user_data: a PyObject pointer.
*
@@ -359,8 +455,6 @@ _pyglib_destroy_notify(gpointer user_data)
pyglib_gil_state_release(state);
}
-/****** Private *****/
-
gboolean
_pyglib_handler_marshal(gpointer user_data)
{
@@ -388,3 +482,4 @@ _pyglib_handler_marshal(gpointer user_data)
return res;
}
+
diff --git a/glib/pyglib.h b/glib/pyglib.h
index 4b28089..dcc8f8a 100644
--- a/glib/pyglib.h
+++ b/glib/pyglib.h
@@ -38,11 +38,14 @@ gboolean pyglib_enable_threads(void);
gboolean pyglib_error_check(GError **error);
gboolean pyglib_gerror_exception_check(GError **error);
gboolean pyglib_threads_enabled(void);
-PyObject *pyglib_main_context_new(GMainContext *context);
+PyObject * pyglib_main_context_new(GMainContext *context);
void pyglib_set_thread_block_funcs(PyGLibThreadBlockFunc block_threads_func,
PyGLibThreadBlockFunc unblock_threads_func);
void pyglib_block_threads(void);
void pyglib_unblock_threads(void);
+PyObject * pyglib_option_context_new(GOptionContext *context);
+PyObject * pyglib_option_group_new(GOptionGroup *group);
+GOptionGroup * pyglib_option_group_transfer_group(PyObject *self);
#define pyglib_begin_allow_threads \
G_STMT_START { \
@@ -55,6 +58,7 @@ void pyglib_unblock_threads(void);
PyEval_RestoreThread(_save); \
} G_STMT_END
+
G_END_DECLS
#endif /* __PYGLIB_H__ */
diff --git a/glib/pygoptioncontext.c b/glib/pygoptioncontext.c
new file mode 100644
index 0000000..2baf36d
--- /dev/null
+++ b/glib/pygoptioncontext.c
@@ -0,0 +1,325 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 2006 Johannes Hoelzl
+ *
+ * pygoptioncontext.c: GOptionContext wrapper
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pyglib.h>
+#include "pyglib-private.h"
+#include "pygoptioncontext.h"
+
+static int
+pyg_option_context_init(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ char *parameter_string;
+ if (!PyArg_ParseTuple(args, "s:gobject.GOptionContext.__init__",
+ &parameter_string))
+ return -1;
+
+ self->context = g_option_context_new(parameter_string);
+ return 0;
+}
+
+static void
+pyg_option_context_dealloc(PyGOptionContext *self)
+{
+ Py_CLEAR(self->main_group);
+
+ if (self->context != NULL)
+ {
+ GOptionContext *tmp = self->context;
+ self->context = NULL;
+ g_option_context_free(tmp);
+ }
+
+ PyObject_Del(self);
+}
+
+static PyObject *
+pyg_option_context_parse(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "argv", NULL };
+ PyObject *arg;
+ PyObject *new_argv, *argv;
+ Py_ssize_t argv_length, pos;
+ gint argv_length_int;
+ char **argv_content, **original;
+ GError *error = NULL;
+ gboolean result;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GOptionContext.parse",
+ kwlist, &argv))
+ return NULL;
+
+ if (!PyList_Check(argv))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionContext.parse expects a list of strings.");
+ return NULL;
+ }
+
+ argv_length = PyList_Size(argv);
+ if (argv_length == -1)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionContext.parse expects a list of strings.");
+ return NULL;
+ }
+
+ argv_content = g_new(char*, argv_length + 1);
+ argv_content[argv_length] = NULL;
+ for (pos = 0; pos < argv_length; pos++)
+ {
+ arg = PyList_GetItem(argv, pos);
+ argv_content[pos] = g_strdup(PyString_AsString(arg));
+ if (argv_content[pos] == NULL)
+ {
+ g_strfreev(argv_content);
+ return NULL;
+ }
+ }
+ original = g_strdupv(argv_content);
+
+ g_assert(argv_length <= G_MAXINT);
+ argv_length_int = argv_length;
+ pyglib_begin_allow_threads;
+ result = g_option_context_parse(self->context, &argv_length_int, &argv_content,
+ &error);
+ pyglib_end_allow_threads;
+ argv_length = argv_length_int;
+
+ if (!result)
+ {
+ g_strfreev(argv_content);
+ g_strfreev(original);
+ pyglib_error_check(&error);
+ return NULL;
+ }
+
+ new_argv = PyList_New(g_strv_length(argv_content));
+ for (pos = 0; pos < argv_length; pos++)
+ {
+ arg = PyString_FromString(argv_content[pos]);
+ PyList_SetItem(new_argv, pos, arg);
+ }
+
+ g_strfreev(original);
+ g_strfreev(argv_content);
+ return new_argv;
+}
+
+static PyObject *
+pyg_option_context_set_help_enabled(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "help_enable", NULL };
+ PyObject *help_enabled;
+ if (! PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:GOptionContext.set_help_enabled",
+ kwlist, &help_enabled))
+ return NULL;
+ g_option_context_set_help_enabled(self->context, PyObject_IsTrue(help_enabled));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+pyg_option_context_get_help_enabled(PyGOptionContext *self)
+{
+ return PyBool_FromLong(g_option_context_get_help_enabled(self->context));
+}
+
+static PyObject *
+pyg_option_context_set_ignore_unknown_options(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "ignore_unknown_options", NULL };
+ PyObject *ignore_unknown_options;
+ if (! PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:GOptionContext.set_ignore_unknown_options",
+ kwlist, &ignore_unknown_options))
+ return NULL;
+ g_option_context_set_ignore_unknown_options(self->context,
+ PyObject_IsTrue(ignore_unknown_options));
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+pyg_option_context_get_ignore_unknown_options(PyGOptionContext *self)
+{
+ return PyBool_FromLong(
+ g_option_context_get_ignore_unknown_options(self->context));
+}
+
+static PyObject *
+pyg_option_context_set_main_group(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "group", NULL };
+ GOptionGroup *g_group;
+ PyObject *group;
+
+ if (! PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:GOptionContext.set_main_group",
+ kwlist, &group))
+ return NULL;
+
+ if (PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionContext.set_main_group expects a GOptionGroup.");
+ return NULL;
+ }
+
+ g_group = pyglib_option_group_transfer_group((PyGOptionGroup*) group);
+ if (g_group == NULL)
+ {
+ PyErr_SetString(PyExc_RuntimeError, "Group is already in a OptionContext.");
+ return NULL;
+ }
+
+ g_option_context_set_main_group(self->context, g_group);
+ Py_INCREF(group);
+ self->main_group = (PyGOptionGroup*) group;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+pyg_option_context_get_main_group(PyGOptionContext *self)
+{
+ if (self->main_group == NULL)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ Py_INCREF(self->main_group);
+ return (PyObject*) self->main_group;
+}
+
+static PyObject *
+pyg_option_context_add_group(PyGOptionContext *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "group", NULL };
+ GOptionGroup *g_group;
+ PyObject *group;
+ if (! PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O:GOptionContext.add_group",
+ kwlist, &group))
+ return NULL;
+ if (PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionContext.add_group expects a GOptionGroup.");
+ return NULL;
+ }
+ g_group = pyglib_option_group_transfer_group((PyGOptionGroup*) group);
+ if (g_group == NULL)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Group is already in a OptionContext.");
+ return NULL;
+ }
+ Py_INCREF(group);
+ g_option_context_add_group(self->context, g_group);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static int
+pyg_option_context_compare(PyGOptionContext *self, PyGOptionContext *context)
+{
+ if (self->context == context->context) return 0;
+ if (self->context > context->context)
+ return 1;
+ return -1;
+}
+
+static PyMethodDef pyg_option_context_methods[] = {
+ { "parse", (PyCFunction)pyg_option_context_parse, METH_VARARGS | METH_KEYWORDS },
+ { "set_help_enabled", (PyCFunction)pyg_option_context_set_help_enabled, METH_VARARGS | METH_KEYWORDS },
+ { "get_help_enabled", (PyCFunction)pyg_option_context_get_help_enabled, METH_NOARGS },
+ { "set_ignore_unknown_options", (PyCFunction)pyg_option_context_set_ignore_unknown_options, METH_VARARGS | METH_KEYWORDS },
+ { "get_ignore_unknown_options", (PyCFunction)pyg_option_context_get_ignore_unknown_options, METH_NOARGS },
+ { "set_main_group", (PyCFunction)pyg_option_context_set_main_group, METH_VARARGS | METH_KEYWORDS },
+ { "get_main_group", (PyCFunction)pyg_option_context_get_main_group, METH_NOARGS },
+ { "add_group", (PyCFunction)pyg_option_context_add_group, METH_VARARGS | METH_KEYWORDS },
+ { NULL, NULL, 0 },
+};
+
+PyTypeObject PyGOptionContext_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.OptionContext",
+ sizeof(PyGOptionContext),
+ 0,
+ /* methods */
+ (destructor)pyg_option_context_dealloc,
+ (printfunc)0,
+ (getattrfunc)0,
+ (setattrfunc)0,
+ (cmpfunc)pyg_option_context_compare,
+ (reprfunc)0,
+ 0,
+ 0,
+ 0,
+ (hashfunc)0,
+ (ternaryfunc)0,
+ (reprfunc)0,
+ (getattrofunc)0,
+ (setattrofunc)0,
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ NULL,
+ (traverseproc)0,
+ (inquiry)0,
+ (richcmpfunc)0,
+ 0,
+ (getiterfunc)0,
+ (iternextfunc)0,
+ pyg_option_context_methods,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ (descrgetfunc)0,
+ (descrsetfunc)0,
+ 0,
+ (initproc)pyg_option_context_init,
+};
+
+void
+pyglib_option_context_register_types(PyObject *d)
+{
+ PYGLIB_REGISTER_TYPE(d, PyGOptionContext_Type, "OptionContext");
+}
diff --git a/glib/pygoptioncontext.h b/glib/pygoptioncontext.h
new file mode 100644
index 0000000..118d664
--- /dev/null
+++ b/glib/pygoptioncontext.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pyglib - Python bindings for GLib toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __PYG_OPTIONCONTEXT_H__
+#define __PYG_OPTIONCONTEXT_H__
+
+#include "pygoptiongroup.h"
+
+extern PyTypeObject PyGOptionContext_Type;
+
+typedef struct {
+ PyObject_HEAD
+ PyGOptionGroup *main_group;
+ GOptionContext *context;
+} PyGOptionContext;
+
+void pyglib_option_context_register_types(PyObject *d);
+
+#endif /* __PYG_OPTIONCONTEXT_H__ */
diff --git a/glib/pygoptiongroup.c b/glib/pygoptiongroup.c
new file mode 100644
index 0000000..cb1d62f
--- /dev/null
+++ b/glib/pygoptiongroup.c
@@ -0,0 +1,305 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pygtk- Python bindings for the GTK toolkit.
+ * Copyright (C) 2006 Johannes Hoelzl
+ *
+ * pygoptiongroup.c: GOptionContext and GOptionGroup wrapper
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <pyglib.h>
+#include "pyglib-private.h"
+#include "pygoptiongroup.h"
+
+static gboolean
+check_if_owned(PyGOptionGroup *self)
+{
+ if (self->other_owner)
+ {
+ PyErr_SetString(PyExc_ValueError, "The GOptionGroup was not created by "
+ "gobject.OptionGroup(), so operation is not possible.");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+destroy_g_group(PyGOptionGroup *self)
+{
+ PyGILState_STATE state;
+ state = pyglib_gil_state_ensure();
+
+ self->group = NULL;
+ Py_CLEAR(self->callback);
+ g_slist_foreach(self->strings, (GFunc) g_free, NULL);
+ g_slist_free(self->strings);
+ self->strings = NULL;
+
+ if (self->is_in_context)
+ {
+ Py_DECREF(self);
+ }
+
+ pyglib_gil_state_release(state);
+}
+
+static int
+pyg_option_group_init(PyGOptionGroup *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "name", "description", "help_description",
+ "callback", NULL };
+ char *name, *description, *help_description;
+ PyObject *callback;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zzzO:GOptionGroup.__init__",
+ kwlist, &name, &description,
+ &help_description, &callback))
+ return -1;
+
+ self->group = g_option_group_new(name, description, help_description,
+ self, (GDestroyNotify) destroy_g_group);
+ self->other_owner = FALSE;
+ self->is_in_context = FALSE;
+
+ Py_INCREF(callback);
+ self->callback = callback;
+
+ return 0;
+}
+
+static void
+pyg_option_group_dealloc(PyGOptionGroup *self)
+{
+ if (!self->other_owner && !self->is_in_context)
+ {
+ GOptionGroup *tmp = self->group;
+ self->group = NULL;
+ if (tmp)
+ g_option_group_free(tmp);
+ }
+
+ PyObject_Del(self);
+}
+
+static gboolean
+arg_func(const gchar *option_name,
+ const gchar *value,
+ PyGOptionGroup *self,
+ GError **error)
+{
+ PyObject *ret;
+ PyGILState_STATE state;
+ gboolean no_error;
+
+ state = pyglib_gil_state_ensure();
+
+ if (value == NULL)
+ {
+ ret = PyObject_CallFunction(self->callback, "sOO",
+ option_name, Py_None, self);
+ }
+ else
+ {
+ ret = PyObject_CallFunction(self->callback, "ssO",
+ option_name, value, self);
+ }
+
+ if (ret != NULL)
+ {
+ Py_DECREF(ret);
+ pyglib_gil_state_release(state);
+ return TRUE;
+ }
+ else
+ {
+ no_error = pyglib_gerror_exception_check(error) != -1;
+ pyglib_gil_state_release(state);
+ return no_error;
+ }
+}
+
+static PyObject *
+pyg_option_group_add_entries(PyGOptionGroup *self, PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "entries", NULL };
+ gssize entry_count, pos;
+ PyObject *entry_tuple, *list;
+ GOptionEntry *entries;
+
+ if (check_if_owned(self)) return NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GOptionGroup.add_entries",
+ kwlist, &list))
+ return NULL;
+
+ if (!PyList_Check(list))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionGroup.add_entries expected a list of entries");
+ return NULL;
+ }
+
+ entry_count = PyList_Size(list);
+ if (entry_count == -1)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "GOptionGroup.add_entries expected a list of entries");
+ return NULL;
+ }
+
+ entries = g_new0(GOptionEntry, entry_count + 1);
+ for (pos = 0; pos < entry_count; pos++)
+ {
+ gchar *long_name, *description, *arg_description;
+ entry_tuple = PyList_GetItem(list, pos);
+ if (!PyTuple_Check(entry_tuple))
+ {
+ PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries "
+ "expected a list of entries");
+ g_free(entries);
+ return NULL;
+ }
+ if (!PyArg_ParseTuple(entry_tuple, "scisz",
+ &long_name,
+ &(entries[pos].short_name),
+ &(entries[pos].flags),
+ &description,
+ &arg_description))
+ {
+ PyErr_SetString(PyExc_TypeError, "GOptionGroup.add_entries "
+ "expected a list of entries");
+ g_free(entries);
+ return NULL;
+ }
+ long_name = g_strdup(long_name);
+ self->strings = g_slist_prepend(self->strings, long_name);
+ entries[pos].long_name = long_name;
+
+ description = g_strdup(description);
+ self->strings = g_slist_prepend(self->strings, description);
+ entries[pos].description = description;
+
+ arg_description = g_strdup(arg_description);
+ self->strings = g_slist_prepend(self->strings, arg_description);
+ entries[pos].arg_description = arg_description;
+
+ entries[pos].arg = G_OPTION_ARG_CALLBACK;
+ entries[pos].arg_data = arg_func;
+ }
+
+ g_option_group_add_entries(self->group, entries);
+
+ g_free(entries);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static PyObject *
+pyg_option_group_set_translation_domain(PyGOptionGroup *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "domain", NULL };
+ char *domain;
+ if (check_if_owned(self)) return NULL;
+
+ if (self->group == NULL)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "The corresponding GOptionGroup was already freed, "
+ "probably through the release of GOptionContext");
+ return NULL;
+ }
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "z:GOptionGroup.set_translate_domain",
+ kwlist, &domain))
+ return NULL;
+ g_option_group_set_translation_domain(self->group, domain);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static int
+pyg_option_group_compare(PyGOptionGroup *self, PyGOptionGroup *group)
+{
+ if (self->group == group->group) return 0;
+ if (self->group > group->group)
+ return 1;
+ return -1;
+}
+
+static PyMethodDef pyg_option_group_methods[] = {
+ { "add_entries", (PyCFunction)pyg_option_group_add_entries, METH_VARARGS | METH_KEYWORDS },
+ { "set_translation_domain", (PyCFunction)pyg_option_group_set_translation_domain, METH_VARARGS | METH_KEYWORDS },
+ { NULL, NULL, 0 },
+};
+
+PyTypeObject PyGOptionGroup_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gobject.OptionGroup",
+ sizeof(PyGOptionGroup),
+ 0,
+ /* methods */
+ (destructor)pyg_option_group_dealloc,
+ (printfunc)0,
+ (getattrfunc)0,
+ (setattrfunc)0,
+ (cmpfunc)pyg_option_group_compare,
+ (reprfunc)0,
+ 0,
+ 0,
+ 0,
+ (hashfunc)0,
+ (ternaryfunc)0,
+ (reprfunc)0,
+ (getattrofunc)0,
+ (setattrofunc)0,
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ NULL,
+ (traverseproc)0,
+ (inquiry)0,
+ (richcmpfunc)0,
+ 0,
+ (getiterfunc)0,
+ (iternextfunc)0,
+ pyg_option_group_methods,
+ 0,
+ 0,
+ NULL,
+ NULL,
+ (descrgetfunc)0,
+ (descrsetfunc)0,
+ 0,
+ (initproc)pyg_option_group_init,
+};
+
+void
+pyglib_option_group_register_types(PyObject *d)
+{
+ PYGLIB_REGISTER_TYPE(d, PyGOptionGroup_Type, "OptionGroup");
+}
+
+
+
diff --git a/glib/pygoptiongroup.h b/glib/pygoptiongroup.h
new file mode 100644
index 0000000..bba8b94
--- /dev/null
+++ b/glib/pygoptiongroup.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * pyglib - Python bindings for GLib toolkit.
+ * Copyright (C) 1998-2003 James Henstridge
+ * 2004-2008 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __PYG_OPTIONGROUP_H__
+#define __PYG_OPTIONGROUP_H__
+
+extern PyTypeObject PyGOptionGroup_Type;
+
+typedef struct {
+ PyObject_HEAD
+ GOptionGroup *group;
+ gboolean other_owner, is_in_context;
+ PyObject *callback;
+ GSList *strings; /* all strings added with the entries, are freed on
+ GOptionGroup.destroy() */
+} PyGOptionGroup;
+
+void pyglib_option_group_register_types(PyObject *d);
+
+#endif /* __PYG_OPTIONGROUP_H__ */
+
+