From 59e8488b49d360992d8df5ca0664ba742411c933 Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Sat, 26 Jul 2008 09:11:08 +0000 Subject: Move option over from gobject to glib. 2008-07-26 Johan Dahlin * 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 --- ChangeLog | 26 ++++ glib/Makefile.am | 29 ++-- glib/glibmodule.c | 33 ++++- glib/option.py | 347 +++++++++++++++++++++++++++++++++++++++++++ glib/pyglib.c | 99 ++++++++++++- glib/pyglib.h | 6 +- glib/pygoptioncontext.c | 325 ++++++++++++++++++++++++++++++++++++++++ glib/pygoptioncontext.h | 37 +++++ glib/pygoptiongroup.c | 305 ++++++++++++++++++++++++++++++++++++++ glib/pygoptiongroup.h | 40 +++++ gobject/Makefile.am | 3 - gobject/__init__.py | 12 +- gobject/gobjectmodule.c | 30 +--- gobject/option.py | 349 ------------------------------------------- gobject/pygobject-private.h | 24 +-- gobject/pygoptioncontext.c | 336 ----------------------------------------- gobject/pygoptiongroup.c | 353 -------------------------------------------- 17 files changed, 1243 insertions(+), 1111 deletions(-) create mode 100644 glib/option.py create mode 100644 glib/pygoptioncontext.c create mode 100644 glib/pygoptioncontext.h create mode 100644 glib/pygoptiongroup.c create mode 100644 glib/pygoptiongroup.h delete mode 100644 gobject/option.py delete mode 100644 gobject/pygoptioncontext.c delete mode 100644 gobject/pygoptiongroup.c diff --git a/ChangeLog b/ChangeLog index 86c04f9..5e01796 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2008-07-26 Johan Dahlin + + * 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. + 2008-07-26 Johan Dahlin * tests/common.py: 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 @@ -339,6 +349,92 @@ pyglib_main_context_new(GMainContext *context) return (PyObject *)self; } +/** + * 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 +#endif + +#include +#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__", + ¶meter_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 +#endif + +#include +#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__ */ + + diff --git a/gobject/Makefile.am b/gobject/Makefile.am index 4a58f3a..44c3741 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -10,7 +10,6 @@ pkgpyexecdir = $(pyexecdir)/gtk-2.0 pygobjectdir = $(pkgpyexecdir)/gobject pygobject_PYTHON = \ __init__.py \ - option.py \ propertyhelper.py pygobject_LTLIBRARIES = _gobject.la nodist_pygobject_PYTHON = constants.py @@ -54,8 +53,6 @@ _gobject_la_SOURCES = \ pygparamspec.c \ pygpointer.c \ pygtype.c \ - pygoptioncontext.c \ - pygoptiongroup.c _gobject_la_DEPENDENCIES = constants.py if HAVE_LIBFFI diff --git a/gobject/__init__.py b/gobject/__init__.py index 04b9a31..cf8be3f 100644 --- a/gobject/__init__.py +++ b/gobject/__init__.py @@ -20,6 +20,7 @@ # USA # this can go when things are a little further along + try: import ltihooks ltihooks # pyflakes @@ -27,13 +28,15 @@ try: except ImportError: pass +import sys + from glib import spawn_async, idle_add, timeout_add, timeout_add_seconds, \ io_add_watch, source_remove, child_watch_add, markup_escape_text, \ get_current_time, filename_display_name, filename_display_basename, \ filename_from_utf8, get_application_name, set_application_name, \ get_prgname, set_prgname, main_depth, Pid, GError, glib_version, \ MainLoop, MainContext, main_context_default, IOChannel, Source, Idle, \ - Timeout, PollFD + Timeout, PollFD, OptionGroup, OptionContext, option from glib import SPAWN_LEAVE_DESCRIPTORS_OPEN, SPAWN_DO_NOT_REAP_CHILD, \ SPAWN_SEARCH_PATH, SPAWN_STDOUT_TO_DEV_NULL, SPAWN_STDERR_TO_DEV_NULL, \ SPAWN_CHILD_INHERITS_STDIN, SPAWN_FILE_AND_ARGV_ZERO, PRIORITY_HIGH, \ @@ -42,7 +45,11 @@ from glib import SPAWN_LEAVE_DESCRIPTORS_OPEN, SPAWN_DO_NOT_REAP_CHILD, \ IO_STATUS_ERROR, IO_STATUS_NORMAL, IO_STATUS_EOF, IO_STATUS_AGAIN, \ IO_FLAG_APPEND, IO_FLAG_NONBLOCK, IO_FLAG_IS_READABLE, \ IO_FLAG_IS_WRITEABLE, IO_FLAG_IS_SEEKABLE, IO_FLAG_MASK, \ - IO_FLAG_GET_MASK, IO_FLAG_SET_MASK + IO_FLAG_GET_MASK, IO_FLAG_SET_MASK, OPTION_FLAG_HIDDEN, \ + OPTION_FLAG_IN_MAIN, OPTION_FLAG_REVERSE, OPTION_FLAG_NO_ARG, \ + OPTION_FLAG_FILENAME, OPTION_FLAG_OPTIONAL_ARG, OPTION_FLAG_NOALIAS, \ + OPTION_ERROR_UNKNOWN_OPTION, OPTION_ERROR_BAD_VALUE, \ + OPTION_ERROR_FAILED, OPTION_REMAINING, OPTION_ERROR from gobject.constants import * from _gobject import * @@ -50,6 +57,7 @@ _PyGObject_API = _gobject._PyGObject_API from propertyhelper import property +sys.modules['gobject.option'] = option class GObjectMeta(type): "Metaclass for automatically registering GObject classes" diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index 81b8892..201381a 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -2656,7 +2656,7 @@ struct _PyGObject_Functions pygobject_api_functions = { pyg_type_register_custom_callback, pyg_gerror_exception_check, - pyg_option_group_new + pyglib_option_group_new }; @@ -2753,9 +2753,6 @@ init_gobject(void) PyType_Ready(&PyGObjectWeakRef_Type); PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type); - REGISTER_TYPE(d, PyGOptionContext_Type, "OptionContext"); - REGISTER_TYPE(d, PyGOptionGroup_Type, "OptionGroup"); - /* pygobject version */ tuple = Py_BuildValue ("(iii)", PYGOBJECT_MAJOR_VERSION, @@ -2795,31 +2792,6 @@ init_gobject(void) PyModule_AddIntConstant(m, "PARAM_LAX_VALIDATION", G_PARAM_LAX_VALIDATION); PyModule_AddIntConstant(m, "PARAM_READWRITE", G_PARAM_READWRITE); - 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)); - /* The rest of the types are set in __init__.py */ PyModule_AddObject(m, "TYPE_INVALID", pyg_type_wrapper_new(G_TYPE_INVALID)); PyModule_AddObject(m, "TYPE_GSTRING", pyg_type_wrapper_new(G_TYPE_GSTRING)); diff --git a/gobject/option.py b/gobject/option.py deleted file mode 100644 index eee58d1..0000000 --- a/gobject/option.py +++ /dev/null @@ -1,349 +0,0 @@ -# -*- Mode: Python -*- -# pygobject - Python bindings for the GObject library -# Copyright (C) 2006 Johannes Hoelzl -# -# gobject/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 gobject. -""" - -import sys -import optparse -from optparse import OptParseError, OptionError, OptionValueError, \ - BadOptionError, OptionConflictError - -from glib import GError - -import _gobject as gobject - -__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 = '--' + gobject.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 |= gobject.OPTION_FLAG_HIDDEN - - if self.in_main: - self.flags |= gobject.OPTION_FLAG_IN_MAIN - - if self.takes_value(): - if self.optional_arg: - flags |= gobject.OPTION_FLAG_OPTIONAL_ARG - else: - flags |= gobject.OPTION_FLAG_NO_ARG - - if self.type == 'filename': - flags |= gobject.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 = GError(str(error)) - gerror.domain = gobject.OPTION_ERROR - gerror.code = gobject.OPTION_ERROR_BAD_VALUE - gerror.message = str(error) - raise gerror - - group = gobject.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 gobject.OptionGroup, which is returned by gtk_get_option_group(). - - Only gobject.option.OptionGroup and gobject.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 = gobject.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, gobject.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 = gobject.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], gobject.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 GError, error: - if error.domain != gobject.OPTION_ERROR: - raise - if error.code == gobject.OPTION_ERROR_BAD_VALUE: - raise OptionValueError(error.message) - elif error.code == gobject.OPTION_ERROR_UNKNOWN_OPTION: - raise BadOptionError(error.message) - elif error.code == gobject.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/gobject/pygobject-private.h b/gobject/pygobject-private.h index 19582d9..34a7e97 100644 --- a/gobject/pygobject-private.h +++ b/gobject/pygobject-private.h @@ -222,29 +222,7 @@ extern PyObject * pyg_enum_from_gtype (GType gtype, extern PyTypeObject PyGParamSpec_Type; PyObject * pyg_param_spec_new (GParamSpec *pspec); -/* pygoption.c */ -extern PyTypeObject PyGOptionContext_Type; -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; - -typedef struct { - PyObject_HEAD - PyGOptionGroup *main_group; - GOptionContext *context; -} PyGOptionContext; - -PyObject * pyg_option_context_new (GOptionContext * context); -PyObject * pyg_option_group_new (GOptionGroup * group); -GOptionGroup *pyg_option_group_transfer_group(PyGOptionGroup *self); - +/* pygtype.c */ extern GHashTable *custom_type_registration; void pyg_type_register_custom_callback(const gchar *type_name, PyGTypeRegistrationFunction callback, diff --git a/gobject/pygoptioncontext.c b/gobject/pygoptioncontext.c deleted file mode 100644 index 177b171..0000000 --- a/gobject/pygoptioncontext.c +++ /dev/null @@ -1,336 +0,0 @@ -/* -*- 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 -#endif - -#include "pygobject-private.h" - -static int -pyg_option_context_init(PyGOptionContext *self, - PyObject *args, - PyObject *kwargs) -{ - char *parameter_string; - if (!PyArg_ParseTuple(args, "s:gobject.GOptionContext.__init__", - ¶meter_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; - pyg_begin_allow_threads; - result = g_option_context_parse(self->context, &argv_length_int, &argv_content, - &error); - pyg_end_allow_threads; - argv_length = argv_length_int; - - if (!result) - { - g_strfreev(argv_content); - g_strfreev(original); - pyg_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 = pyg_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 = pyg_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, -}; - -/** - * pyg_option_context_new: - * @context: a GOptionContext - * - * Returns: A new GOptionContext wrapper. - */ -PyObject * -pyg_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; -} diff --git a/gobject/pygoptiongroup.c b/gobject/pygoptiongroup.c deleted file mode 100644 index 770a497..0000000 --- a/gobject/pygoptiongroup.c +++ /dev/null @@ -1,353 +0,0 @@ -/* -*- 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 -#endif - -#include -#include "pygobject-private.h" -#include "pygobject.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 = pyg_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, -}; - -/** - * 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 * -pyg_option_group_transfer_group(PyGOptionGroup *self) -{ - 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; -} - -/** - * pyg_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 * -pyg_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; -} -- cgit