App Developer Week -- PyGTK is dead, long live PyGI! Using gobject-introspection in Python -- pitti -- Tue, Apr 12th, 2011
1 [17:01] <dpm> Check out http://ubuntu-news.org/2011/04/12/off-to-a-great-start-ubuntu-app-developer-week-day-1/ if you missed any of the sessions yesterday 2 [17:01] <ClassBot> Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. 3 [17:02] <dpm> Next up is Martin Pitt, one of the persons who know Ubuntu and its technologies inside out 4 [17:02] <dpm> He's going to be talking about porting your old PyGTK applications to the new PyGI framework, 5 [17:02] <dpm> so that they can make use of all the awesomeness of introspection. 6 [17:02] <dpm> Let's hand him the mike... 7 [17:03] * pitti clears throat 8 [17:03] <pitti> Hello everyone! I am Martin Pitt from the Canonical Ubuntu Desktop Team. 9 [17:03] <pitti> Python is a very important and popular language in Ubuntu, we have a lot of applications written in Python for GTK and Qt/KDE. Most prominent examples are our installer Ubiquity, Software Center, our driver installer "Jockey", and our bug/crash reporting system "Apport" (shameless plug!). 10 [17:03] <pitti> By way of Quickly we also encourage application developers to use Python and GTK, as these allow you to write GUI applications both conveniently, fast, and still rather robust. 11 [17:03] <pitti> So far the package of choice for that has been PyGTK, a manually maintained Python binding for GTK, ATK, Pango, Glade, and a few other things. However, a few months ago, with the advent of GTK3, PyGTK was declared dead, so it's time to bring the banner of the great new world of its successor -- gobject-introspection -- to the world! 12 [17:04] <pitti> Tomeu Vizoso already explained what gobject-introspection (commonly abbreviated "GI") is, why we need it, and how library developers can use it to provide a machine readable and complete API/ABI description. So I'll just do a very brief summary here. 13 [17:04] <pitti> I'll concentrate on the app developer side, i. e. how to use GI typelibs in Python. 14 [17:04] <pitti> Porting existing PyGTK2 code is a topic that will keep many of us busy in the next months, so I'll explain the process and common pitfalls with that. 15 [17:04] <pitti> Finally I'll give some pointers to documentation, and will be available for some Q&A. 16 [17:05] <pitti> Everyone ready to dive in? Please let me know (here or in #-chat) when I become too fast. If I am being totally unclear, please yell and I'll handle that immediately. If you just have a followup question, let's handle these at the end.
Quick recap: What is GI?
1 [17:05] <pitti> So far a lot of energy was spent to write so-called "bindings", i. e. glue code which exposes an existing API such as GTK for a target language: PyGTK, libnotify-cil, or Vala's .vapi files. 2 [17:05] <pitti> This both leads to a combinatorial explosion (libraries times languages), as well as many bindings which don't exist at all, or being of low quality. In addition it is also an almost insurmountable barrier for introducing new languages, as they would need a lot of bindings before they become useful. 3 [17:05] <pitti> GI is a set of tools to generate a machine parseable and complete API/ABI description of a library, and a library (libgirepository) which can then be used by a language compiler/interpreter to automatically provide a binding for this library. 4 [17:06] <pitti> With GI you can then use every library which ships a typelib in every language which has GI support. 5 [17:06] <pitti> GI ABI/API descriptions come in two forms: 6 [17:06] <pitti> * An XML file, called the "GIR" (GI repository). These are mainly interesting for developers if they need to look up a particular detail of e. g. a method argument or an enum value. These are not actually used at runtime (as XML would be too costly to interpret every time), and thus they are shipped in the library's -dev package in Ubuntu and Debian. For example, libgtk2.0-dev ships 7 [17:06] <pitti> /usr/share/gir-1.0/Gdk-2.0.gir. 8 [17:07] <pitti> * A compiled binary form for efficient access, called the "typelib". These are the files that language bindings actually use. Ubuntu/Debian ship them in separate packages named gir<GI_ABI_version>-<libraryname>-<library_ABI_version>, for example, gir1.2-gtk-2.0 ships /usr/lib/girepository-1.0/Gdk-2.0.typelib. 9 [17:07] <pitti> (Yes, it's confusing that the gir1.2-* package does _not_ actually ship the .gir file; don't ask me why they were named "gir-", not "typelib-").
How does it work in Python?
1 [17:07] <pitti> pygobject is the piece of software which provides Python access to GI (amongst other things, like providing the glib and GObject bindings). 2 [17:08] <pitti> The package name in Ubuntu/Debian is "python-gobject", and it should already be installed on all but the most manually trimmed down installations. 3 [17:08] <pitti> Initial GI support was added to pygobject in version 2.19.0 (August 2009), but the entire GI/pygobject/annotations stack really only stabilized in the last couple of months, so that in practice you will need at least pygobject 2.28 and the corresponding latest upstream releases of GTK and other libraries you want to use. 4 [17:08] <pitti> This means that you can only really use this with distros which are less than about three months old. For Debian/Ubuntu this means you'll need to use the current development versions, i. e. Ubuntu Natty (beta-1) or Debian experimental (most of this wasn't uploaded to unstable yet after the squeeze release). 5 [17:09] <pitti> pygobject provides a "gi.repository" module namespace which generates virtual Python modules from installed typelibs on the fly. 6 [17:09] <pitti> For example, if you install gir1.2-gtk-2.0 (it's already installed by default in Ubuntu Natty), you can do: 7 [17:09] <pitti> $ python -c 'from gi.repository import Gtk; print Gtk' 8 [17:09] <pitti> <gi.module.DynamicModule 'Gtk' from '/usr/lib/girepository-1.0/Gtk-2.0.typelib'> 9 [17:10] <pitti> and use it just like any other Python module. 10 [17:10] <pitti> I bet that this first example comes as an absolutely unexpected surprise to you: 11 [17:10] <pitti> $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' 12 [17:10] * pitti gives everyone a minute to try this 13 [17:11] <pitti> Let's look at the corresponding C declaration:
1 GtkWidget* gtk_message_dialog_new (GtkWindow *parent, GtkDialogFlags flags, GtkMessageType type, GtkButtonsType buttons, const gchar *message_format, ...);
1 [17:12] <pitti> and the C call:
1 [17:12] <pitti> So what do we see here? 2 [17:12] <pitti> (1) The C API by and large remains valid in Python (and other languages using the GI bindings), in particular the structure, order, and data types of arguments. 3 [17:13] <pitti> There are a few exceptions which are mostly due to the different way Python works, and in some cases to make it easier to write code in Python. I'll speak about details below. But this means that you can (and should) use the normal API documentation for the C API of the library. devhelp is your friend! 4 [17:13] <pitti> (2) As Python is a proper object oriented language, pygobject (and in fact the GI typelib already) expose a GObject API as proper classes, objects, methods, and attributes. 5 [17:13] <pitti> I. e. in Python you write
1 [17:13] <pitti> instead of the C gobject syntax
1 [17:14] <pitti> The class names in the typelib (and thus in Python) are derived from the actual class names stated in the C library (like "GtkButton"), except that the common namespace prefix ("Gtk" here) is stripped, as it becomes the name of the module. 2 [17:14] <pitti> (3) Global constants would be a heavy namespace clutter in Python, and thus pygobject exposes them in a namespaced fashion as well. 3 [17:14] <pitti> I. e. if the MessageDialog constructor expects a constant of type "GtkMessageType", then by above namespace split this becomes a Python class "Gtk.MessageType" with the individual constants as attributes, e. g. Gtk.MessageType.INFO. 4 [17:15] <pitti> (This is actually something that pygtk gets quite wrong, the constant names are quite arbitrary there) 5 [17:15] <pitti> (4) Data types are converted in a rather obvious fashion. E. g. when the C API expects an int* array pointer, you can supply a normal Python array [0, 1, 2]. A Python string "foo" will match a gchar*, Pythons None matches NULL, etc. 6 [17:16] <pitti> So the GObject API actually translates quite naturally into a real OO language like Python, and after some time of getting used to above transformation rules, you should have no trouble translating the C API documentation into their Python equivalents. 7 [17:16] <pitti> When in doubt, you can always look for the precise names, data types, etc. in the .gir instead, which shows the API broken by class, method, enum, etc, with the exact names and namespaces as they are exposed in Python. 8 [17:16] <pitti> s I mentioned above, this is in no way restricted to GTK, GNOME, or UI. For example, if you handle any kind of hardware and hotplugging, you almost certainly want to query udev, which provides a nice glib integration (with signals) through the gudev library. 9 [17:17] <pitti> This example lists all block devices (i. e. hard drives, USB sticks, etc.): 10 [17:17] <pitti> (You need to install the gir1.2-gudev-1.0 package for this) 11 [17:17] <pitti> $ python 12 [17:17] <pitti> >>> from gi.repository import GUdev 13 [17:17] <pitti> >>> c = GUdev.Client() 14 [17:18] <pitti> >>> for dev in c.query_by_subsystem("block"): 15 [17:18] <pitti> ... print dev.get_device_file() 16 [17:18] <pitti> ... 17 [17:18] <pitti> /dev/sda 18 [17:18] <pitti> /dev/sda1 19 [17:18] <pitti> /dev/sda2 20 [17:18] <pitti> [...] 21 [17:18] <pitti> See http://www.kernel.org/pub/linux/utils/kernel/hotplug/gudev/GUdevClient.html#g-udev-client-query-by-subsystem for the corresponding C API. 22 [17:19] <pitti> GI is not even restricted to GObject, you can annotate any non-OO function based API with it. E. g. there is already a /usr/share/gir-1.0/xlib-2.0.gir (although it's horribly incomplete). These will behave as normal functions in Python (or other languages) as well.
Other API differences
1 [17:20] <pitti> I said above in (1) that the structure of method arguments is by and large the same in C and in GI/Python. There are some notable exceptions which you must be aware of.
1 [17:21] <pitti> * Use the standard GObject constructor and pass in the initial property values as named arguments:
1 Gtk.Button(label="foo", use_underline=True)
1 [17:22] <pitti> The second is actually the recommended one, as it makes the meaning of the arguments more explicit, and also underlines the GObject best practice that a constructor should do nothing more than to initialize properties. But otherwise it's pretty much a matter of taste which one you use.
1 [17:23] <pitti> Unlike C, higher level languages know how long an array is, while in the C API you need to specify that explicitly, either by terminating them with NULL or explicitly giving the length of the array in a separate argument. 2 [17:23] <pitti> Which one is used is already specified in the annotations and thus in the typelib, so Python can automatically provide the right format without the developer needing to append an extra "None" or a separate len(my_array) argument. 3 [17:23] <pitti> For example, in C you have
1 gtk_icon_theme_set_search_path (GtkIconTheme *icon_theme, const gchar *path, gint n_elements)
1 [17:24] <pitti> In Python you can just call this as
1 my_icon_theme.set_search_path(['/foo', '/bar'])
1 [17:24] <pitti> and don't need to worry about the array size.
1 [17:24] <pitti> C functions can't return more than one argument, so they often use pointers which the function then fills out. Conversely, Python doesn't know about pointers, but can easily return more than one value as a tuple. 2 [17:25] <pitti> The annotations already describe which arguments are "out" arguments, so in Python they become part of the return tuple: first one is the "real" return value, and then all out arguments in the same order as they appear in the declaration. For example:
1 GdkWindow* gdk_window_get_pointer (GdkWindow *window, gint *x, gint *y, GdkModifierType *mask)
1 [17:25] <pitti> In Python you would call this like
1 (ptr_window, x, y, mask) = mywindow.get_pointer()
1 [17:26] <pitti> Some GLib/GTK functions take a callback method and an extra "user_data" argument that is passed to the callback. 2 [17:26] <pitti> In C they often also take a "GDestroyNotify" function which is run once all callbacks are done, in order to free the memory of user_data. 3 [17:26] <pitti> As Python has automatic memory management, pygobject will take care of all this by itself, so you simply don't specify the GDestroyNotify argument. 4 [17:26] <pitti> For example:
1 void gtk_enumerate_printers (GtkPrinterFunc func, gpointer user_data, GDestroyNotify destroy, gboolean wait)
1 [17:27] <pitti> In Python you call this as
1 Gtk.enumerate_printers(my_callback, my_user_data, True)
1 [17:28] <pitti> When you work with PyGI for a longer time, you'll inevitably stumble over a method that simply doesn't exist in the bindings. These usually are marked with introspectable="0" in the GIR. 2 [17:28] <pitti> In the best case this is because there are some missing annotations in the library which don't have a safe default, so GI disables these to prevent crashes. They usually come along with a corresponding warning message from g-ir-scanner, and it's usually quite easy to fix these. 3 [17:28] <pitti> So please do file upstream bugs against the relevant library when you find these 4 [17:28] <pitti> Another common case are functions which take a variable number of arguments, such as gtk_cell_area_add_with_properties(). 5 [17:29] <pitti> Varargs cannot be handled safely by libgirepository. In these cases there are often alternatives available (such as gtk_cell_area_cell_set_property()). For other cases libraries now often have a ..._v() counterpart which takes a list instead of variable arguments.
1 [17:29] <pitti> A specialty of pygobject is the possibility of replacing functions, methods, or classes of the introspected library with custom code, called "overrides". 2 [17:30] <pitti> As the goal is to stay very close to the original API, they should be used and written sparsely, though. 3 [17:30] <pitti> One major use case is to provide replacements for unintrospectable methods. For example, Gtk.Menu.popup() is not introspectable in GTK, but the GTK override implements this method in terms of Gtk.Menu.popup_for_device(), so in this case the override actually helps to get closer to the original API again. 4 [17:30] <pitti> Another important case is automatic data type conversion, most prominently to allow passing unicode objects to methods which expect an UTF-8 encoded gchar*. This also actually helps to prevent workarounds in application code and maintain a clean API. 5 [17:31] <pitti> Thirdly, overrides are useful if they help to massively ease development. For example it is quite laborious to do GDBus calls or GVariant constructions with the native Gio/GLib API. 6 [17:31] <pitti> pygobject offers convenience overrides to make these a lot simpler and more Pythonic, but of course without actually breaking the original API. 7 [17:32] <pitti> Overrides are shipped in /usr/share/pyshared/gi/overrides/, and should be quite easy to understand. 8 [17:32] <pitti> e. g. in /usr/share/pyshared/gi/overrides/Gtk.py you see the "def popup()" method for Menu that I mentioned above 9 [17:32] <pitti> In general you should not even be required to know about it, as most of them really just fix stuff to work as expected. 10 [17:33] <pitti> But for the GDBus/GVariant cases it is useful to know them, as you can safe yourself a ton of extra work
Migrating pygtk2 code
1 [17:33] <pitti> A big task that we in Ubuntu already started in the Natty cycle, and which will continue to keep us and all other PyGTK app developers busy for a while is to port PyGTK2 applications to GTK3 and PyGI. 2 [17:33] <pitti> Note that this is really two migrations in one step, but is recommended as GTK2 still has a lot of breakage with PyGI, although I did a fair amount of work to backport fixes from GTK3 (the six applications that we ported in Natty run with PyGI and GTK2, after all). 3 [17:34] <pitti> The GTK2 â†’ GTK3 specifics are documented at http://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html and I don't want to cover them here. 4 [17:34] <pitti> If we compare the PyGTK vs. PyGI code for a "Hello" message box, we see that it's actually very similar in structure: 5 [17:34] <pitti> $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' 6 [17:34] <pitti> (^ pygi) 7 [17:34] <pitti> $ python -c 'import gtk; gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "Hello World").run()' 8 [17:34] <pitti> (^ pygtk) 9 [17:35] <pitti> So PyGTK also already did the representation of the C functions as proper classes and methods, thus if you port from PyGTK instead of from C, it'll be a lot easier.
Step 1: The Great Renaming
1 [17:35] <pitti> The biggest part in terms of volume of code changed is basically just a renaming exercise. 2 [17:35] <pitti> E. g. "gtk.*" now becomes "Gtk.*", and "gtk.MESSAGE_INFO" becomes "Gtk.MessageType.INFO". 3 [17:35] <pitti> Likewise, the imports need to be updated: "import gtk" becomes "from gi.repository import Gtk". 4 [17:35] <pitti> Fortunately this is is a mechanical task which can be automated. The pygobject git tree has a script "pygi-conver.sh" which is a long list of perl -pe 's/old/new/' string replacements. You can get it from http://git.gnome.org/browse/pygobject/tree/pygi-convert.sh. 5 [17:36] <pitti> It's really blunt, but surprisingly effective, and for small applications chances are that it will already produce something which actually runs. 6 [17:36] <pitti> Note that this script is in no way finished, and should be considered a collaborative effort amongst porters. So if you have something which should be added there, please don't hesitate to open a bug or ping me or someone else on IRC (see below). We pygobject devs will be happy to improve the script. 7 [17:36] <pitti> When you just run pygi-convert.sh in your project tree, it will work on all *.py files. 8 [17:36] <pitti> If you have other Python code there which is named differently (such as bin/myprogram), you should run it once more with all these file names as argument.
Step 2: Wash, rinse, repeat
1 [17:37] <pitti> Once the mechanical renamings are out of the way, the tedious and laborious part starts. As Python does not have a concept of "compile-time check" and can't even check that called methods exist or that you pass the right number of parameters, you now have to enter a loop of "start your program", "click around until it breaks", "fix it", "goto 1". 2 [17:37] <pitti> The necessary changes here are really hard to generalize, as they highly depend on what your program actually does, and this will also involve the GTK 2 â†’ 3 parts. 3 [17:37] <pitti> One thing that comes up a lot are pack_start()/pack_end() calls. 4 [17:38] <pitti> In PyGTK they have default values for "expand", "start", and "padding", but as GTK does not have them, you won't have them in PyGI either. 5 [17:38] <pitti> There even was a patch once for providing an override for them, but it was rejected as it would cement the API incompatibility. 6 [17:38] <pitti> ted as it would cement the API incompatibility. 7 [17:38] <pitti> One thing you need to be aware of is that you can't do a migration halfway: If you try to import both "gtk" and "gi.repository.Gtk" hell will break lose and you'll get nothing but program hangs and crashes, as you are trying to work with the same library in two different ways. 8 [17:39] <pitti> You can mix static and GI bindings of _different_ libraries, such as using dbus-python and GTI-GI. 9 [17:39] <pitti> erm, Gtk-GI, sorry
Step 3: Packaging changes
1 [17:39] <pitti> After you have your code running with PyGI and committed it to your branch and released it, you need to update the dependencies of your distro package for PyGI. 2 [17:39] <pitti> This section will be Debian/Ubuntu specific due to the involved package names, sorry. It is not be fundamentally different on other distros, though. 3 [17:40] <pitti> You should grep your code for "gi.repository" and collect a list of all imported typelibs, and then translate them into the appropriate package name. 4 [17:40] <pitti> For example, if you import "Gtk, Notify, Gudev" you need to add package dependencies to gir1.2-gtk-3.0, gir1.2-notify-0.7, and gir1.2-gudev-1.0. 5 [17:40] <pitti> At the same time you should drop the old static bindings, like python-gtk2, python-notify, etc. 6 [17:40] <pitti> Finally you should also bump the version of the python-gobject dependency to (>= 2.28) to ensure that you run with a reasonably bug free PyGI.
RTFM & Links
1 [17:41] <pitti> I'd like to give a list of useful links for this topic here. 2 [17:41] <pitti> This has a good general overview about GI's architecture, annotations, etc: 3 [17:41] <pitti> https://live.gnome.org/GObjectIntrospection 4 [17:41] <pitti> The interview with Jon Palmieri and Tomeu Vizoso is also an interesting read about its state: 5 [17:41] <pitti> http://www.gnomejournal.org/article/118/pygtk-gobject-and-gnome-3 6 [17:41] <pitti> The GI/PyGI developers hang out on IRC here: 7 [17:42] <pitti> #introspection / #python on irc.gnome.org 8 [17:42] <pitti> pygobject's git tree has a very comprehensive demo showing off pretty much all available GTK widgets in PyGI: 9 [17:42] <pitti> http://git.gnome.org/browse/pygobject/tree/demos/gtk-demo 10 [17:42] <pitti> Description of the Python overrides for much easier GVariant and GDBus support 11 [17:42] <pitti> http://www.piware.de/2011/01/na-zdravi-pygi/ 12 [17:42] <pitti> Examples of previously done pygtk â†’ pyGI ports: 13 [17:42] <pitti> Apport: http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/1801 14 [17:42] <pitti> Jockey: http://bazaar.launchpad.net/~jockey-hackers/jockey/trunk/revision/679 15 [17:42] <pitti> gtimelog: http://bazaar.launchpad.net/~pitti/gtimelog/pygi/revision/181 16 [17:42] <pitti> system-config-printer (work in progress): http://git.fedorahosted.org/git/?p=system-config-printer.git;a=shortlog;h=refs/heads/pygi 17 [17:42] <pitti> The gtimelog one is interesting because it makes the code work with *both* PyGTK and PyGI, whichever is available. 18 [17:43] <pitti> finally, I plan to turn this talk into a proper wiki page below https://live.gnome.org/GObjectIntrospection, so that it's more useful for posterity
Q & A
1 [17:43] <pitti> Thanks everyone for your attention! I'm happy to answer questions now. 2 [17:44] <ClassBot> toabctl asked: why is it git1.2 but girepository-1.0? 3 [17:44] <pitti> 1.0 is the ABI version of libgirepository, i. e. the client side library for gjs, pygojbect, etc. to create bindings 4 [17:45] <pitti> 1.2 is the binary format version for the .typelibs 5 [17:45] <ClassBot> toabctl asked: what about structs like eg GDate/GDateTime? 6 [17:45] <pitti> these actually do get exported 7 [17:46] <pitti> have a look at /usr/share/gir-1.0/GLib-2.0.gir 8 [17:46] <pitti> <record name="DateTime" c:type="GDateTime" ... 9 [17:46] <pitti> <record name="Date" c:type="GDate"> 10 [17:46] <pitti> <field name="julian_days" writable="1" bits="32"> 11 [17:46] <pitti> <type name="guint" c:type="guint"/> 12 [17:46] <pitti> </field> 13 [17:46] <pitti> etc. 14 [17:46] <pitti> so as long as they are relatively simple, they do work 15 [17:47] <ClassBot> JanC asked: does GI support named parameters & default values, so that in Python method/function calls we can leave some parameters out? 16 [17:48] <pitti> not right now 17 [17:48] <pitti> I hear that there is a plan to support default values which are specified in the C code/annotations themselves 18 [17:48] <pitti> but otherwise you'll need an override for cases where it makes sens 19 [17:48] <pitti> e 20 [17:49] <ClassBot> rr0hit asked: the hello world example in pygi gives me error: TypeError: __init__() takes at most 5 arguments (6 given) . What am I doing wrong 21 [17:49] <pitti> rr0hit: I suppose you are using Ubuntu 10.10? 22 [17:49] <pitti> as I said above, I'm afraid this is all pretty new, and you need 11.04 beta 23 [17:49] <ClassBot> crazedpsyc asked: why did pygtk not work out well? wxpython seems just fine, and it is a C wrapper as well. 24 [17:50] <pitti> well, it did work well for years 25 [17:50] <pitti> but as I said, someone would need to maintain it, and port it to GTK3, and keep that up to date, etc. 26 [17:50] <pitti> and provide missing bindings for all other GNOMEish libraries (which were often missing) 27 [17:51] <ClassBot> chadadavis asked: If other distros are not using the latest GI yet, is Ubuntu planning to maintain their own GI-ported version of all these apps? 28 [17:51] <pitti> no, that would be quite crazy 29 [17:51] <ClassBot> There are 10 minutes remaining in the current session. 30 [17:51] <pitti> so far we just ported a lot of our Ubuntu specific stuff 31 [17:51] <pitti> and I ported gtimelog, but proposed that upstream first 32 [17:52] <pitti> so likewise, if we port upstream software, we do that upstream 33 [17:52] <pitti> e. g. GNOME will certainly appreciate these patches, it's a GNOME goal to port their pygtk stack, etc. 34 [17:52] <pitti> not sure if that answered chadadavis question? 35 [17:52] <ClassBot> toabctl asked: how can i create a instance of GDate/GDatetime with python? and how to map these types to the python types(datetime.date/datetime.datetime) ? 36 [17:53] <pitti> $ python -c 'from gi.repository import GLib; GLib.Date()' 37 [17:53] <pitti> etc. 38 [17:53] <pitti> (not really tested much) 39 [17:53] <pitti> but that's the idea 40 [17:54] <pitti> note that structs have always been a bit fiddly, as often GI doesn't have enough type information about members 41 [17:54] <pitti> so this only works for simple structs 42 [17:54] <pitti> the more complex ones should be turned into proper GObjects (that was necessary and done in GTK3 in some cases) 43 [17:54] <pitti> the most common case is probably the Events struct, which works good enough 44 [17:55] <ClassBot> zinga60 asked: can I use Python introspection like dir() for the dynamically created modules? 45 [17:55] <pitti> not right now, I'm afraid 46 [17:55] <pitti> it is possible in principle, the typelib has all necessary information 47 [17:55] <pitti> but it doesn't work right now 48 [17:55] <ClassBot> zinga60 asked: so as a beginner with gtk, etc. (without the need of porting from pygtk to pygi) I should use the official C API docs (to look up function signatures, etc.) and the gir-xml files to see the corresponding Python name spaces? 49 [17:56] <pitti> usually the C API docs (libgtk-3-doc etc.) should suffice 50 [17:56] <pitti> with the appropriate transformation rules that I mentioned above 51 [17:56] <ClassBot> There are 5 minutes remaining in the current session. 52 [17:56] <pitti> so usually you should be able to easily derive the according Python call 53 [17:56] <pitti> if not, you can look in the gir, but I seldomly found that necessary myself 54 [17:56] <pitti> out of questions :) 55 [17:56] <pitti> so, thanks everyone! 56 [17:57] <pitti> I hang out in #ubuntu-desktop, #ubuntu-devel, and also #python/#introspection on the GNOME IRC, so feel free to ask me there later 57 [17:58] <pitti> dpm: clearing the floor then 58 [17:58] <pitti> for manish_ 59 [17:59] <dpm> thanks a lot for a great session pitti! 60 [17:59] <dpm> excellent participation as well