[pygtk] Bug 163645 – Support GOption
Johannes Hölzl
johannes.hoelzl at gmx.de
Sat Apr 15 06:27:19 WST 2006
Hi,
I'm new to this list so I hope this is the correct behaviour :-)
To finish the first GnomeGoal [1] for gnome-python i wrote a wrapper for
GOptionGroup and GOptionContext which can be found under [2].
This wrapper simply maps the GOptionEntry structure to a 7-tuple. Mostly
this is a 1-1 mapping, there is only a difference for the arg_data
member. Either arg is G_OPTION_ARG_CALLBACK, then the add_entries()
function expects a callable, which gets called with the option_name,
option_value and GOptionGroup. Otherwise arg must be a PyString. In this
case the option value can (after the command-line parsing) accessed by
__getitem__(). So the entry
group.add_entries([
("file", "f", 0, gobject.OPTION_ARG_FILENAME, "file-name",
"A filename", "FILE")
])
can later accessed by group['file-name'].
IMPLEMENTATION
The values are internally saved in (GHashTable*)
PyGOptionGroup.arg_name_value_map. (Is the preferred way in pygtk to use
GLib data structures or the corresponding Python structures?) The
GHashTables PyGOptionGroup.arg_name_callback_map maps the option names
(the long and the short ones) to the callback function.
MEMORY MANAGEMENT
To avoid memory leaks, double frees etc. the PyGOptionGroup has only
access to its GOptionGroup when it was created with
pyg_option_group_init(). So we can set the destroy notify callback which
cleans the callbacks, the callback arguments and the hash tables
arg_name_callback_map and arg_name_value_map. When the PyGOptionGroup is
created with pyg_option_group_new(GOptionGroup*), it can only be used to
add the group with GOptionContext.add_group() to a context. For
set_parse_group() etc. we don't get a notify when the GOptionGroup is
destroyed.
While the GOptionGroup lives, it holds a reference to the PyGOptionGroup
(the userdata for the destroy notifier), so the PyGOptionGroup can only
be destroyed when the GOptionContext is freed, for this in
pyg_option_group_transfer_group() it INCREFs the PyGOptionGroup and
DECREFs it in pyg_option_group_destroy(), which also frees the callbacks
and callback arguements.
I tried to detect wrong usage as much as possible. Is this is the
correct behaviour in pygtk, or is it simply to much work to be done
right? (at least in my code it seams to look ugly)
ALTERNATIVES
Instead of being a mapping, it would probably be better if every
GOptionGroup has a dictionary, for example group.values, which can be
set to an arbitrary mapping object (but defaults to an ordinary PyDict).
And every GOptionEntry is an callback entry, which sets the value in the
dictionary when the callback is called. One problem is, that in the
error case the PyDict isn't changed back like it is done now by
g_option_context_parse().
So we could write:
class TestModule(object):
pass
test = TestModule()
ctxt = gobject.GOptionContext("Test")
group = gobject.GOptionGroup("The Test Controller", "...", "...")
ctxt.add_group(group)
group.values = test.__dict__
group.add_entries([
("file", "f", gobject.OPTION_FLAG_FILENAME,
"A filename", "FILE")
])
ctxt.parse([sys.argv[0], "-f", "example.txt"])
assert test.file == "example.txt"
mfg,
Johannes Hölzl
[1] http://live.gnome.org/GnomeGoals/PoptGOption
[2] http://bugzilla.gnome.org/show_bug.cgi?id=163645
More information about the pygtk
mailing list