Thursday, January 01, 2009

Python: Builds of PyWebkitGtk and Webkit-Glib-Gtk

I saw this on python-announce, and all I can say is "What the heck?" I think this means you can write a Python application and have it compile down to an Ajax application or a desktop application, but I could be wrong:
webkit-glib-gtk provides gobject bindings to webkit's DOM model. pywebkitgtk provides python bindings to the gobject bindings of webkit's DOM model.

files are available for download at: https://sourceforge.net/project/showfiles.php?group_id=236659&package_id=290457&release_id=650548

separate pre-built .debs for AMD64 and i386 Debian are included, for pywebkitgtk and webkit-gtk with gobject bindings to the DOM model. if you have seen OLPC/SUGAR's "hulahop", or if you have used Gecko / XUL DOM bindings, or KDE's KHTMLPart DOM bindings, you will appreciate the value of webkit-glib-gtk. pywebkitgtk with glib/gobject bindings basically brings pywebkitgtk on a par with hulahop.

if you find the thought of pywebkitgtk with glib bindings, and/or hulahop to be "all too much", then do consider looking at pyjd (the other download from the same location, above). pyjd - aka pyjamas-desktop - is a level "above" pywebkitgtk-glib, and is on a par with pykde, pyqt4, pygtk2, python-wxWidgets and other desktop-based widget sets. (side-note: the advantage of pyjd is that if you write an app which conforms to the pyjamas UI widget set API, you can compile the same python app source code to javascript and run it directly in all major web browsers: see http://pyjs.org, which is a python-to-javascript compiler).

code-stability-wise, pywebkitgtk and webkit-glib-gtk should be considered "experimental" (not least because this is a release from a svn build!). that having been said, pyjamas-desktop is declared "production" because pywebkitgtk with DOM bindings, thanks to webkit-glib-gtk, provides absolutely everything that pyjamas-desktop needs (and if webkit-glib-gtk becomes a moving target, the DOM.py abstraction layer in pyjamas-desktop will take care of it. if it becomes a _severe_ moving target, pyjamas-desktop will drop webkit and provide a python-hulahop / XUL-Geck port instead. or as well. whatevrrrr :).

gobject-interface-wise, the webkit gobject DOM bindings that have been added _can_ be considered to be "stable", as long as the underlying webkit library IDL files are "stable" (additions to Console.idl were made in the past couple of months, for example, and HTML5 is making advances as well). that having been said, _some_ functionality proved intransigent during the initial main development phase of the webkit gobject DOM bindings, such as RGBColour conversion of CSS Style Properties, and so were *temporarily* left out. given that pyjamas-desktop is considered "production", that should give a pretty clear indication of the importance of those rare bits of DOM model bindings features that were left out. SVG Canvas bindings, however, have NOT been included, as that would have added a further 120 gobjects to the list.

instructions for anyone brave enough to install webkit-glib-gtk from source, themselves, on macosx: http://github.com/lkcl/webkit/wikis/installing-webkit-glib-on-macosx there is an (experimental) Portfile in the macosx 10.4 glib tarball, as well.

please note that the MacOSX build is NOT a "native" webkit build: it is a GTK / X11 build (known as a "gtk port", in webkit developer terminology). the reason for providing the MacOSX webkit-glib-gtk build, along with a MacOSX port of pywebkitgtk is because the "native" webkit build - which includes ObjectiveC bindings and thus can automatically get python bindings - has very subtly different functionality. whilst the native ObjectiveC bindings are more fully compliant with the W3C standards, providing javascript-like functionality where absolutely necessary, the webkit-glib-gtk build's gobject bindings are going specifically for direct correspondance with the functionality provided by the webkit javascript bindings, falling back to alternatives where it is absolutely not possible to achieve that goal.

the actual differences, however, are extremely small, percentage-wise. out of around 300 objects, providing around 1,500 functions, and tens of thousands of properties, there are approximately 20 functions that are different, and only four properties that are different.

examples of the differences in the bindings APIs offered by ObjectiveC and webkit-glib-gtk Gobject bindings include:

* the provision of the function "toString", which is known as a javascriptism that is not in the W3C standard. _not_ providing this function, which is a de-facto standard, is considered to be inconvenient, especially as both Gecko's language bindings _and_ PyKDE's PyKHTMLPart bindings provide toString() functions. The ObjectiveC bindings, in sticking to the W3C standard, religiously, do not offer "toString". the reason for including toString in the webkit-glib-gtk bindings should be fairly obvious: it is unreasonable to expect developers who will be used to the de-facto existence of toString in javascript to find that it's ... disappeared for no good reason, thus forcing them to make unnecessary coding workarounds, duplicating the exact same functionality that *already* exists in the webkit library!

* hspace and vspace of HTMLAppletElement, and width and height of HTMLEmbedElement, are often (mistakenly) set to "NNNpx", "100%" and other values, in javascript, contrary to the W3C standards for HTMLAppletElement and HTMLEmbedElement, respectively. to make life easier for webkit applications (such as Safari, the iPhone browser and other important webkit applications), an exception was made to allow - and cater for or ignore, as appropriate, values in these non-standard formats. Whilst the ObjectiveC bindings stick to the W3C standards, and only allow hspace, vspace, width and height to be set to integer values, the webkit-glib-gtk bindings take advantage of the underlying webkit functions that perform the conversion, and are thus more tolerant - with the proviso of course that it's perfectly possible for users to shoot themselves in the foot by trying to set vspace="10em". such foot-shooting will be silently ignored - just as it is if you tried to do the same thing with javascript.

* XMLHTTPRequest.send accepts a DOMString on the webkit-glib-gtk bindings, whereas what should actually be passed in is a Webkit Document object. various attempts were made to create appropriate TextDocument and XMLDocument objects: unfortunately they failed miserably. fortunately, earlier versions of Webkit provided a version of XMLHTTPRequest.send which accepts a DOMString argument, and this version was reactivated for the webkit-glib-gtk bindings. the ObjectiveC and all other bindings successfully pass in a Webkit Document object. this issue will at some point need to be addressed, however it's pretty low priority: using a DOMString works just as well.

* Document.getSelection is considered to be a javascript-ism, and is not made available to the ObjectiveC bindings. the function has been added to the webkit-glib-gtk bindings just in case anyone feels like using it.

anyone wishing to use the glib/gobject DOM model directly, in c, is well advised to look at the example modified WebKitTools/GtkLauncher/main.c which can be found here: http://lkcl.net/pyjamas-desktop/main.c this modified example is not "gobject-perfect" - there are a couple of areas where an experienced gobject programmer will spot ref-count losses that have yet to be addressed, however the code does some really quite sophisticated messing-about of the DOM model, and provides genuinely useful code snippets. developers may be intrigued to know that some of the code-snippets, such as get_absolute_top(), are direct ports from pyjamas-desktop of the DOM.py getAbsoluteTop() function, which was in turn itself a direct port from the javascript code inside pyjamas DOM.py of the same function name. the technique, and the examples, will help other developers wishing to write applications, by first writing or sourcing an example written in javascript, and then following the same conversion techniques as can be seen by comparing DOM.py getAbsoluteTop() with the example main.c get_absolute_top().

anyone wishing to provide bindings to other languages, such as ruby, perl or java: the pygtk-codegen-2.0 application pretty much made mincemeat of webkit.defs (available on request, or look at code.google.com/p/pywebkitgtk issue #13 - i may update the patch soon enough) and absolutely _no_ funny business - overrides of _any_ kind - were required! the only "funny business" that's in pywebkitgtk overrides is to do with gtk, not the webkit gobject bindings. 300 objects, 1500 functions and tens of thousands of properties all get added with a vanilla .defs file. unbelievable. so this spells "good news" for the garbage-collecting languages (e.g. ruby, perl, possibly java): if your language-of-choice's gobject-auto-generator is as good as python-gobject's auto-generator, you should be up-and-running within literally a couple of hours. oh - but first: i would advise you to look at pywebkitgtk's "demobrowser.py" for guidance on how to create a webkit gtk app (using your language of choice) first, followed by looking at pyjamas-desktop's "pyjd.py" for further hints on how to bind to the DOM model functions [pyjd.py is based on demobrowser.py].

c++ is a different matter. webkitgtkmm will _not_ be gaining DOM bindings based on webkit.defs. after discussions with jonathon jongsma, we came to the conclusion that it would be far better to write a _separate_ set of bindings (gobjectmm) actually in webkit, due to subtle information being available that is lost by the time you get to webkit-gobject c-bindings. anyone anticipating to write or have webkitgtkmm "up-and-running", providing gtk / gobject bindings to webkit's DOM model, should expect to take between three and four weeks in writing a CodeGeneratorGobjectMM.pl, using the other WebKit CodeGenerators as guides.

that's all, for now. bugs should be reported to the respective bugtrackers of the appropriate projects - http://code.google.com/p/pyjamas, http://code.google.com/p/pywebkitgtk and http://bugs.webkit.org should do the trick.

4 comments:

jonathan Saggau said...

It means you can load content into a web view and bind directly to its Document Object Model. This means you could (say) write your data model and logic in python and use a web page to display it. Or... you could mess around with some other web content directly in your app.

JerryS said...

It means exactly what JJ wrote, that you can write an app in Python, and run it as either 1) a web based, server driven application, powered by Javascript, or 2) a desktop app with built in browser-like web access, based on Webkit ( the engine under apple's Safari, and Google's Chrome ), or alternatively, based on hulahop (the engine under OLPC's Sugar environment, which uses Mozilla Gecko for rendering ).

Here are some more links:

Pyjamas home = http://code.google.com/p/pyjamas/

Pyjamas Desktop Home = http://pyjd.org/

BTW, the patches to add the glib, gobject bindings have been submitted to the Webkit Open Source project, so that Python developers can easily use the Webkit engine. However, they have been "under review" for some time now. Maybe if enough Pythonistas mention that we're patiently waiting to start building Webkit apps, the review process will be completed sooner?

It's painless to register, here:

https://trac.webkit.org/auth/register/

Then you can edit the wiki, and add your $.02.

Jerry S.

Shannon -jj Behrens said...

Thanks for the comment, Jerry.

Anonymous said...

http://ppibburr.heliohost.org/doc/index.html

ruby glib webkit bindings :D