Search Results: "nate"

7 May 2009

Biella Coleman: Make our words glisten



glisten vs hardened words, originally uploaded by the biella.
Now that I am (thankfully) done teaching until September, I have time to devour two small mountains of readings that I need to finish before I return to my manuscript, which I will be working on, I hope uber-productively, all summer long. One pile of readings deals with coding, open source, and the commons, such as Scott Rosenberg s Dreaming in Code and David Bollier s Viral Spiral. Another pile of reading edges toward the theoretical side of things, having to do with craft, pleasure, and humor, since it is pleasure in its many many many guises from from the calm feeling of self-satisfaction that underlies pride in one s craft, to the more sublime feeling of ecstatic bliss that powers many creative sprints. If one entertains pleasure, one must also entertain its darker side, for all of this feel good stuff is nonetheless often springs forth from a deep sea of passionate frustration. This seems to be the driving theme of Dreaming in Code and it is also what animates Ellen Ullman s fictional account of pure frustration, The Bug. I am quite fond of native expressions of geek frustration and recently was provided with an exquisite example a rant against the Adobe PSD format. The author of Xee, A light-weight, fast and convenient image viewer for Mac OS X explained his utter contempt for the Adobe PSD in the following way:
At this point, I d like to take a moment to speak to you about the Adobe PSD format. PSD is not a good format. PSD is not even a bad format. Calling it such would be an insult to other bad formats, such as PCX or JPEG. No, PSD is an abysmal format. Having worked on this code for several weeks now, my hate for PSD has grown to a raging fire that burns with the fierce passion of a million suns. If there are two different ways of doing something, PSD will do both, in different places. It will then make up three more ways no sane human would think of, and do those too. PSD makes inconsistency an art form. Why, for instance, did it suddenly decide that *these* particular chunks should be aligned to four bytes, and that this alignement should *not* be included in the size? Other chunks in other places are either unaligned, or aligned with the alignment included in the size. Here, though, it is not included. Were it within my power, I would gather every single copy of those specs, and launch them on a spaceship directly into the sun.
Even if this account represents unadulterated irritation, he leaves us, the reader, with nothing of the irritation, only pleasure. This aftermath of frustration is delivered through the vehicle of humor, which within the hacker context, is the cultural container that best captures the spirit of hacker pleasure or so I will be arguing. Like many humorous rants from the world of hacking (and please send me any others you know of), this text dances with liveliness; it exudes its own rhythm; it glistens to use Ronald Barthes apt phrasing from his short book The Pleasure of Text, which I just finished as part of my theoretical escape into the pleasure-dome. Although there are parts of his book which are to be frank, *really* *not* *pleasurable*, partly due to obscure references to High French Theory, which elide even an academic pair of eyes, the book generally pleases. And one of the most pleasing chunks is his definition of a stereotype:
The stereotype is the word repeated without any magic, any enthusiasm, as though it were natural, as though by some miracle this recurring words were adequate on each occasion for different reasons, as though to imitate could no longer be sensed as an imitation: an unconstrained word that claims consistency and is unaware of its own insistence
In contrast to the stereotype, a string of words that enchants does so by slipping off the page to hit you squarely in the heart or the gut. Unfortunately, while academic writing steers clear of stereotypes, often trying to present the detailed singularity of a phenomena (even when conditioned by social forces), it does not exactly glisten, though there are a handful of exceptions. I think we need more texts that glisten, even if only during sections or parts of our books and articles (much like the rant helped enliven the more staid technical document). In recent years, in large part due to the influence of free software, there has been an explosion, a move toward going open access. All of this is laudable and I fully embrace it (and have gotten into some small battles over it). But without an aesthetic politics that values pleasure in reading and writing we are doomed to obscurity anyway. A move toward making our knowledge public also required a move toward thinking about the literary aesthetics of pleasure.

Biella Coleman: Make our words glisten



glisten vs hardened words, originally uploaded by the biella.
Now that I am (thankfully) done teaching until September, I have time to devour two small mountains of readings that I need to finish before I return to my manuscript, which I will be working on, I hope uber-productively, all summer long. One pile of readings deals with coding, open source, and the commons, such as Scott Rosenberg s Dreaming in Code and David Bollier s Viral Spiral. Another pile of reading edges toward the theoretical side of things, having to do with craft, pleasure, and humor, since it is pleasure in its many many many guises from from the calm feeling of self-satisfaction that underlies pride in one s craft, to the more sublime feeling of ecstatic bliss that powers many creative sprints. If one entertains pleasure, one must also entertain its darker side, for all of this feel good stuff is nonetheless often springs forth from a deep sea of passionate frustration. This seems to be the driving theme of Dreaming in Code and it is also what animates Ellen Ullman s fictional account of pure frustration, The Bug. I am quite fond of native expressions of geek frustration and recently was provided with an exquisite example a rant against the Adobe PSD format. The author of Xee, A light-weight, fast and convenient image viewer for Mac OS X explained his utter contempt for the Adobe PSD in the following way:
At this point, I d like to take a moment to speak to you about the Adobe PSD format. PSD is not a good format. PSD is not even a bad format. Calling it such would be an insult to other bad formats, such as PCX or JPEG. No, PSD is an abysmal format. Having worked on this code for several weeks now, my hate for PSD has grown to a raging fire that burns with the fierce passion of a million suns. If there are two different ways of doing something, PSD will do both, in different places. It will then make up three more ways no sane human would think of, and do those too. PSD makes inconsistency an art form. Why, for instance, did it suddenly decide that *these* particular chunks should be aligned to four bytes, and that this alignement should *not* be included in the size? Other chunks in other places are either unaligned, or aligned with the alignment included in the size. Here, though, it is not included. Were it within my power, I would gather every single copy of those specs, and launch them on a spaceship directly into the sun.
Even if this account represents unadulterated irritation, he leaves us, the reader, with nothing of the irritation, only pleasure. This aftermath of frustration is delivered through the vehicle of humor, which within the hacker context, is the cultural container that best captures the spirit of hacker pleasure or so I will be arguing. Like many humorous rants from the world of hacking (and please send me any others you know of), this text dances with liveliness; it exudes its own rhythm; it glistens to use Ronald Barthes apt phrasing from his short book The Pleasure of Text, which I just finished as part of my theoretical escape into the pleasure-dome. Although there are parts of his book which are to be frank, *really* *not* *pleasurable*, partly due to obscure references to High French Theory, which elide even an academic pair of eyes, the book generally pleases. And one of the most pleasing chunks is his definition of a stereotype:
The stereotype is the word repeated without any magic, any enthusiasm, as though it were natural, as though by some miracle this recurring words were adequate on each occasion for different reasons, as though to imitate could no longer be sensed as an imitation: an unconstrained word that claims consistency and is unaware of its own insistence
In contrast to the stereotype, a string of words that enchants does so by slipping off the page to hit you squarely in the heart or the gut. Unfortunately, while academic writing steers clear of stereotypes, often trying to present the detailed singularity of a phenomena (even when conditioned by social forces), it does not exactly glisten, though there are a handful of exceptions. I think we need more texts that glisten, even if only during sections or parts of our books and articles (much like the rant helped enliven the more staid technical document). In recent years, in large part due to the influence of free software, there has been an explosion, a move toward going open access. All of this is laudable and I fully embrace it (and have gotten into some small battles over it). But without an aesthetic politics that values pleasure in reading and writing we are doomed to obscurity anyway. A move toward making our knowledge public also required a move toward thinking about the literary aesthetics of pleasure.

Pablo Lorenzzoni: Another small victory - don't relax just yet

Months (even years) of activism, over 140 thousand signatures, and finally another small victory: Brazilian Minister of Justice Mr. Tarso Genro sent a letter [pt-BR] stating that Sen. Azeredo s bill is dangerous, and that the Ministry is working in an alternative (among other things). We had already incited a public hearing that were very fruitful [pt-BR] and might have brought the Ministry to the issue. But don t relax just yet, folks! Right now, working in this alternative , are people with every kind of agenda It s safe to assume that some of them are from the same lobby that pushed Sen. Azeredo first version of the thing. So, yes, this was another victory, but nothing really changed The bill is still approved by the Senate and still has to be reviewed by the Chamber-of-Deputies, and the alternative that will be presented by the Ministry is still under construction. What we accomplished is nothing more than making the Minister aware of the issue So, keep the pressure over your representatives, send messages to the Ministry, stating how you feel about the issue! Let s show them what we want them to do After all, that s why we elected them, in the first place, isn t it? [Published also at Trezentos, in portuguese]

5 May 2009

Jan Hauke Rahm: Avelsieve 1.9.8

Today the SquirrelMail plugin avelsieve happened to be released with version 1.9.8. Thanks and kudos to Alexandros who after so long time still was in the mood to put things together. The new features promise to be amazing: a new user interface, much code rewriting, and an entirely new SPAM handling. Unfortunately after installing it my SquirrelMail installation went badly down somehow. While everything alse is delivered properly by apache2, SquirrelMail now runs into one timeout after another. I need to figure out what s actually going on there. The error.log is quiet so far Anyways, for all you people who are looking forward to see this new fancy and shiny version in sid, I have to ask for patience. I think the package is ready but before testing no uploading! Until then you can (if you re brave) test the package by installing it from http://downloads.jhr-online.de/avelsieve_1.9.8-1_all.deb And all you others just have a look at the changelog that s probably (hopefully) hitting sid in a few days:
  * New upstream release
     + A large part of the code has been rewritten.
     + A new-style SPAM rule has been implemented.
     + A new, global Whitelist rule has been implemented, for
       the SPAM rules to take advantage of.
     + New, "Custom Sieve Code" rule has been implemented; this allows users
       to enter directly Sieve code snippets as a rule. (experimental)
     + Miscellaneous code movement and restructuring.
     + UI: The "Add New Rule" buttons are now links, and are displayed
       both at the top and at the bottom of the rule table.
     + UI: Major rework in the UI of both the Rules Table and the Add New
       Rule / Edit Rule pages.
     + UI: If a vacation rule is active, then display a notice in the
       rules table page and upon logging in to Squirrelmail, that reminds
       the user.
     + UI: Vacation options have been aligned properly; text has been
       changed accordingly.
     + Sieve: Vacation Subject is now supported.
     + New functionality: "Insert New Rule Here"
     + New functionality: "Move Rule to Position" (requires Javascript)
     + Avelsieve now highly recommends the use of javascript_libs plugin
       for some visual effects / UI improvements.
     + UI: Added new icons and used different ones, to improve usability.
       Icons are provided by Mark James' famfamfam.com.
     + UI: Added new icon "theme" based also on famfamfam.com. This theme
       is the default from now on.
     + UI: Removed unnecessary text / clutter from rules table page.
     + UI: The notify action options have been aligned in a table.
     + Added an LDAP Sieve storage backend, compatible with Sun Messaging
       Server's Sieve features.
     + The DO_Sieve_* backends should have a separate retrieve() method
       for retrieving the raw Sieve script. Currently, only the Managesieve
       backend has it.

Martin-Éric Racine: Debian CUPS transition in progress

Since Lenny was the first Debian release to feature CUPS under its new package naming strategy, I started going through 'rdepends' results to see which packages in Squeeze still present dependencies for *cupsys* packages. Much to my amazement, there's quite many. If you are the maintainer of a package that still has those dependencies, please fix them ASAP. Alternately, if you're aware of any favorite package that does, please do not hesitate at filing a patch to help the maintainer update their debian/control. Comes June 2009, transitional CUPS packages will be removed from our debian/control.

Andrew Pollock: [tech] Analog cable's days numbered?

Apparently Comcast is planning on axing its analog cables at some undetermined point in the future. That will make my MythTV setup more complicated, and no doubt require a more expensive cable plan and yet more equipment. My setup is already a tad ridiculous.

4 May 2009

Manoj Srivastava: Manoj: Reflections on streetcars

Recently, I have made fairly major changes to kernel-package, and there were some reports that I had managed to mess up cross compilation. And, not having a cross-compilation tool chain handy, I had to depend on the kindness of strangers to address that issue. And, given that I am much less personable than Ms Vivien Leigh, this is not something I particularly look forward to repeating. At the onset, building a cross compiling tool chain seems a daunting task. This is not an activity one does frequently, and so one may be pardoned for being non-plussed by this. However, I have done this before, the most recent effort being creating one to compile rockbox binaries, so I had some idea where to start. Of course, since it is usually years between attempts to create cross-compiling tool chains, I generally forget how it is all done, and have to go hunting for details. Thank god for google. Well, I am not the only one in the same pickle, apparently, for there are gobs of articles and HOWTOs out there, including some pretty comprehensive (and intimidating) general tool sets to designed to create cross compilers in the most generic fashion possible. Using them was not really an option, since I would forget how to drive them in a few months, and have a miniature version of the current problem again. Also, you know, I don t feel comfortable using scripts that are too complex for me to understand I mean, without understanding, how can there be trust? Also, this time around, I could not decide whether to cross compile for arm-elf, as I did the last time, or for the newfangled armel target. A need for quickly changing the target for the cross compiler build mechanism would be nice. Manually building the tool chain makes a wrong decision here expensive, and I hate that. I am also getting fed up with having to root around on the internet every time I wanted to build a cross compiler. I came across a script by Uwe Hermann, which started me down the path of creating a script, with a help option, to store the instructions, without trying to be too general and thus getting overly complex. However, Uwe s script hard coded too many things like version numbers and upstream source locations, and I know I would rapidly find updating the script irritating. Using Debian source packages would fix both of these issues. I also wanted to use Debian sources as far as I could, to ensure that my cross compiler was as compatible as I could make it, though I did want to use newlib (I don t know why, except that I can, and the docs sound cool). And of course the script should have a help option and do proper command line parsing, so that editing the script would be unnecessary. Anyway, all this effort culminated in the following script: build cross toolchain, surprisingly compact. So I am now all set to try and cross compile a kernel the next time a kernel-package bug comes around. I thought that I would share this with the lazy web, while I was at it. Enjoy. The next thing, of course, is to get my script to create a qemu base image every week so I can move from user mode Linux to the much more nifty kvm, which is what all the cool kids use. And then I can even create an arm virtual machine to test my kernels with, something that user mode linux can t easily do.

Matthew Garrett: Thinkpad mixers

Older (up to the *60 series) Thinkpads have a slightly odd mixer setup. There's a mixer stage that sits between the software controllable mixer and the speakers. This is controlled by the firmware in response to the volume keys being hit and can't be prevented by the OS. This is unfortunate, since users are quite enthusiastic about seeing an on-screen display when they hit various keys and if we do the obvious thing and map the volume keys to KEY_VOLUMEUP and KEY_VOLUMEDOWN then they get the OSD but also get their software-controlled mixer changed at the same time as their firmware-controlled mixer. This causes boundless confusion.

Lorne Applebaum recently sent a patch that added an ALSA control to represent the Thinkpad mixer. This means that we can now read and control the Thinkpad-specific hardware without userspace needing any special knowledge. I've gone a little further and sent a followup patch that sends ALSA notifications on button presses. Lennart suggested that it would also be helpful to export dB values and wrote a nice app that measures them - that means that Pulseaudio will be able to set the mixer volume correctly by default.

The only missing part of the puzzle now is getting the OSD back. We still can't map the keys to KEY_VOLUMEUP and KEY_VOLUMEDOWN because that'll still result in two mixers being changed at once. We can't add new keys to indicate that it's a notification event rather than a command, since X can't deal with keycodes greater than 255 (actually 243, since it adds 8 to every kernel keycode for historical hilarity) and we've run out of space. We can't hook off the ALSA notifications because that'll result in the OSD popping up in response to someone dragging a slider in a volume control application. The easiest thing might be to add another ALSA notification that's only triggered if the notification was generated in the kernel and then have userspace listen for that.

Newer Thinkpads appear to have done away with this mixer setup entirely and just send standard volume events. This is a Good Thing.

In other news, I'm off on holiday to Australia for a couple of weeks so may be a bit slow in replying to things.

3 May 2009

Daniel Burrows: aptitude-gtk status, a visual tour

As some of you may know, Arthur Liu did the initial work on a GTK+ interface for aptitude last summer as part of the Google Summer of Code program. Since that program ended, I've been working to complete the GTK+ interface, along with some unrelated but similarly large changes to other parts of aptitude. It's been a while since I've written anything about aptitude-gtk, though, mostly because I set it aside for a few months to improve the dependency solver. While I'll probably be doing more work on the backend over the summer, I also hope to get the GTK+ interface to a point where I can feel comfortable including it in a stable release of aptitude. There are two things that I want to be in place for the GTK+ interface before I release it:
  1. The interface should be functionally complete, meaning that you should be able to do anything you can do in the other interfaces.
  2. The interface should be reasonably straightforward to use and nice to look at. This is a never-ending task, but there are some pieces of the current interface that are particularly ugly or awkward that I'd like to fix before release.
I've gone through the major areas of the current UI and marked them up with notes about things that I think need to be done. This isn't a definitive or exhaustive list, but it should give some idea of where aptitude is and where it's going.
Dashboard Tab annotated dashboard tab The first thing you see when you start aptitude is the dashboard. This is a display that gives you immediate access to some of the most common things you'll want to do: searching for a package, viewing the available upgrades, and upgrading as many packages as aptitude can figure out how to upgrade without removing anything. This is one of the most complete parts of the interface, but there are a few minor aesthetic things that I'd like to take care of. [UPDATE] Michael Johnson writes:
I agree with most of the notes on this screen. However, I'd like to see the Selected Package changelog stay. I often look more than one upgrade back. The summary doesn't show more than what's being upgraded. However, I do like the idea of package description tab. The search box should definately always be available. I found it annoying when I had to click back to a different tab to get it. One thing I definately miss from the console version of aptitude is the list of recommended and suggested packages. I don't let aptitude auto-install recommended packages, but I like to know what they are.

Packages tab annotated packages tab This is the view that's shown after you search for a package by name, keyword, or by other criteria. It's also fairly complete, but there are more things that could be added (mostly enhancements). Related to this is the dialog box for editing which columns are visible: annotated visible columns editor
Dependency solver tab annotated dependency solver tab The dependency solver got a lot of love in the 0.5.2.1 release, and it's now basically functional. There are some minor layout issues to be fixed, and if I have time I'd like to add more ways of controlling the resolver's behavior.
Package information tab annotated package information tab The package information page is probably the weakest part of the GTK+ aptitude interface; it wouldn't be too much of a stretch to say that this tab is holding back a stable release of aptitude-gtk. The big problem I have with it is that I feel that the information tab should open up with an overview of the status of the package. What version is installed, what's available, what archive is it in, who's the maintainer, how big is it, etc. Instead, aptitude-gtk currently shows you a big tree of all the package's dependencies. While that's useful, it should be something the user chooses from. I also find this tab to be visually unappealing, but I'm not entirely sure how to fix that. [UPDATE] Gunnar Wolf writes:
As you have mentioned in your blog post (quote this mail if you so wish) that you want to make the package information screen "sexier": I think it would be natural to integrate screenshots (from http://screenshots.debian.net/) into it. Of course, it would be worth measuring whether it imposes too high a load into that system (maybe it should only get a screenshot if the user explicitly asks for it) - but surely would be a net win.
I think this is a great idea and I'm definitely planning to incorporate this feature. [UPDATE] Michael Johnson writes:
One of the things I really like about aptitude-gtk over console-aptitude is how obvious it makes some things. The version display on this tab is one of those things. Maybe it could be more obvious, I don't know. I agree, the dependency list is not the most important thing. And it's missing the reverse dependencies. I use that more than the dependencies. As far as the actual display of the list, I can't think of anything besides a tree. Although the current implementation does feel quite clunky. What I'd more like to see first is the list of files in the package. But I can see how other people would have different priorties. So it should be really easy to change the default view.

Preferences tab vast gaping hole where the preferences tab should be One of the reasons that it is a stretch to say that the information tab is holding aptitude-gtk back is the preferences tab, which is a huge pile of not-yet-implemented-ness. In fact, it's not even designed, let alone implemented. Releasing a GUI program with no way to alter the settings strikes me as ... silly.
Preview tab annotated The preview tab is a bit weaker than the packages tab, in my opinion, but much stronger than the information tab. Like the information tab, I find it visually unappealing, but I'm not entirely sure how to improve it. I'm currently leaning towards the paned browser idea. [UPDATE] Michael Johnson writes:
I've never been comfortable using this tab. It never made much sense to me. I think the last one or two times I used aptitude-gtk it started making sense, but that seems to be too long a time. I think it's the mass of text at each top level entry. The console version has brief descriptions with more info in the details pane when the entry is selected. Perhaps healthy use of tool tips or an info pane would help with this. The paned browser idea sounds promising. I think it will be easier for new users to follow. And it provides a natural way to provide more information on what each section is about.

That's all folks!

2 May 2009

Andrew Pollock: [life] In Vancouver

It's time for the obligatory two-year E-3 visa renewal (well reapplication, technically), and this time we thought we'd stay local and do it in Vancouver. We flew up this morning, and we're going to get a ferry to Victoria and stay the night with my cousin and meet his wife and kids, then take a seaplane back to Vancouver on Sunday night. We've got an appointment at the US Embassy on Monday morning. If everything goes to plan, we'll fly back on Thursday evening. I'm looking forward to a bit of down time. The timing is unfortunate, given this H1N1 flu outbreak, but our visas expire at the end of the month, and consular appointments aren't particularly easy to come by (or flexible).

1 May 2009

Simon McVittie: Implementing D-Bus clients with telepathy-glib (and telepathy-qt4)

(The much-delayed part 2 in an ongoing series: shiny things in telepathy-glib) Over a year ago I explained my first major round of work on telepathy-glib, with which it could be used to implement D-Bus services. I started to write this post shortly after, but then got distracted by a bee or something; recent discussion about having a D-Bus binding in GLib has finally prompted me to finish it. The second major round of work on telepathy-glib dealt with implementing client code, and went sufficiently well that telepathy-qt4 (currently under development) uses essentially the same model. Again, while telepathy-glib is intended for Telepathy implementors, I think TpProxy's ideas are generically useful, particularly for "large" D-Bus APIs.

Some background: dbus-glib and libtelepathy
GObject-CRITICAL: Assertion failed: proxy->convenient
The life-cycle of a DBusGProxy (PD clipart credit: karderio and Andy)
The API provided by dbus-glib for client code is, er, rather less than ideal. The basic object is DBusGProxy, which has a few problems. There's one per interface, rather than one per object; this leads to a maze of twisty GObjects, all suspiciously similar. Our old client library, libtelepathy, got round this by subclassing DBusGProxy to make helper objects called TpChan, TpConn etc., which were simultaneously the proxy for the "main" interface (Channel, Connection etc.), and a factory for proxies for the other interfaces (like Channel.Type.Text and Channel.Interface.Password). This still wasn't ideal, but it was a start. If you use a DBusGProxy in any way after it has emitted the destroy signal, this is considered to be invalid use of the API, and dbus-glib asserts all over the place. We'd rather it didn't do that - remote objects becoming invalid is a fact of life, and if you don't immediately discard all your references to those objects, remote operations on them should just give you a runtime error. You have to be prepared to handle such runtime errors already, because any IPC call can fail at any time. The main API for calling methods uses varargs and is rather subtle. Notably, the calling convention for variant parameters (of D-Bus signature 'v') is not consistent with the calling convention for any other container. For any other container, for instance a GPtrArray *, you pass in a GPtrArray ** pointing to a GPtrArray * variable containing NULL; on success, a pointer to a new GPtrArray is written into that variable. For variant parameters, though, you must pass in a GValue * pointing to a zero-filled GValue, and the result will be written into that GValue. dbus-binding-tool generates thin wrappers around this method-calling API which provide type-safety, although they can't directly specify a non-default timeout. As for signals, before binding to a signal, you have to tell dbus-glib about its signature. This tells dbus-glib how it should push the signal arguments onto the C stack (in GObject terminology: how it should marshal them), to match the signature of the signal-handler function. The documentation claims that this isn't necessary for objects supporting the Introspect method, but that's untrue - on the other hand, if the documented behaviour actually happened, I would consider this to be a critical bug in dbus-glib, since it would enable remote objects to crash dbus-glib clients (by causing signal arguments to be pushed onto the stack in a way that does not match the signature of the signal handler). Of course, the signal-adding function takes varargs, and has to be called exactly once per signal per object. If you don't, dbus-glib asserts when you connect to the signal; if you call it twice, dbus-glib asserts anyway.

TpProxy TpProxy is a GObject subclass vaguely inspired by Python's dbus.proxy.ProxyObject. It isn't a subclass of DBusGProxy, which lets us encapsulate dbus-glib almost completely - in fact, all the references to DBusGProxy are in a separate header, proxy-subclass.h, only used by subclasses of TpProxy (as opposed to normal library API users). TpProxy instances are per-remote-object (per-object-path) like in dbus-python, rather than per-interface like in dbus-glib or QtDBus. As explained below, I believe that this is the most natural object mapping for D-Bus interfaces; in practice it tends to lead to clearer code for us, since one remote object often maps nicely to one UI element (of course, if your objects only have one interface, this approach is no better or worse than dbus-glib's). TpProxy provides support for the following common D-Bus things:
  • Calling methods
  • Connecting to signals
  • Objects becoming invalid
  • Objects with optional interfaces
  • Extensibility
It doesn't currently provide any particular help with Properties - the Properties interface is just another interface as far as we're concerned. We find that, in practice, that's not a problem (even though we use D-Bus properties extensively). In telepathy-qt4 we basically reinvented TpProxy in C++, as Tp::DBusProxy. I've put in some comments below illustrating how the general ideas we used in TpProxy translate into a different object mapping.

Calling methods Method calls on TpProxy are done through auto-generated wrapper functions, much like DBusGProxy. These look something like this:
typedef void (*tp_cli_channel_callback_for_close) (TpChannel *proxy,
    /* any 'out' arguments would go here - Close() doesn't have any */
    const GError *error, gpointer user_data,
    GObject *weak_object);
TpProxyPendingCall *tp_cli_channel_call_close (TpChannel *proxy,
    gint timeout_ms,
    /* any 'in' arguments would go here - Close() doesn't have any */
    tp_cli_channel_callback_for_close callback,
    gpointer user_data,
    GDestroyNotify destroy,
    GObject *weak_object);
Methods for some interfaces, like DBus.Properties, are available on TpProxy itself; others, like Telepathy's Channel.anything, are only available on a particular subclass, like TpChannel. Things to note here:
  • It's an asynchronous call with a callback. General design principle: "this is IPC, get over it". We don't try to hide the fact that IPC is taking place by doing pseudo-blocking calls.
  • The timeout is explicit (although you can always pass -1 to let libdbus pick a "reasonable" default for you). This is because the remote service might not respond, and API users should be at least vaguely aware of this: "this is IPC, get over it".
  • The callback isn't a GCallback; it has an explicit signature, for some semblance of type-safety (it's not much, but it's better than nothing).
  • The callback takes a GError, because any IPC call can fail for any reason.
  • A TpProxyPendingCall * is returned. This is a pointer to an object that only exists until just after the callback is called (so you can ignore it if you don't want it), with a method you can call to cancel the method call (with hindsight this is not ideal, and if I was writing this API now, I'd use gio's GCancellable). "Cancel" is perhaps slightly misleading: the method call still takes place (it was already in libdbus's outgoing queue) but the result gets ignored and the callback isn't called. This is mostly so you an object can forget all the calls it was busy making at the time that the results become irrelevant (e.g. the object is destroyed).
  • There is an extra weak_object argument, which is weakly referenced and is passed to the callback: in practice, most users of telepathy-glib use this as well as or instead of user_data. If the weak_object runs out of references, the callback is automatically cancelled, which means that in practice, explicit cancellation is almost never needed.
  • The generated code has as its first argument a suitable subclass of TpProxy, in this case TpChannel (we tell the code generator about subclasses).
  • You can't see it in the API, but the TpProxy gains an extra ref while a method call is in progress, so you never have to worry about what happens if the proxy gets unreffed during a method call.
  • There's an explicit destructor for the user_data, which is called even if you "cancel" the method call.
In telepathy-qt4, these methods are on small generated helper classes similar to dbus-python's dbus.Interface, one per interface (we provide accessors for them on the non-generated DBusProxy subclass). Instead of using callbacks, we return a temporary QObject per call, which emits a Qt signal on success or failure (that's how all async calls in QtDBus work).

Connecting to signals Similarly, signals have some generated functions:
typedef void (*tp_cli_channel_signal_callback_closed) (TpChannel *proxy,
    /* any arguments would go here - Closed doesn't have any */
    gpointer user_data, GObject *weak_object);
TpProxySignalConnection *tp_cli_channel_connect_to_closed (TpChannel *proxy,
    tp_cli_channel_signal_callback_closed callback,
    gpointer user_data,
    GDestroyNotify destroy,
    GObject *weak_object,
    GError **error);
API notes for these:
  • The callback doesn't take a GError any more, because signals can't fail; the weak_object and the user_data are the same as for method calls
  • This isn't actually a GObject signal at all: those aren't particularly typesafe, and lack namespacing. This might not be very binding-friendly, we haven't tried doing that yet... it might be worth introducing a signal with details, like in dbus-glib, for which these functions are "C bindings".
  • The returned TpProxySignalConnection lets you disconnect from the signal, just like the TpProxyPendingCall above; it can safely be ignored
  • Similarly, if the weak_object dies, then the signal automatically disconnects
  • It is possible for connecting to a signal to fail: this happens if the proxy doesn't actually have the requested interface. If this happens, it's graceful, not a crash. In practice, the flow of code is almost always such that error can safely be NULL because the interfaces are already known.
In telepathy-qt4 the per-interface generated helper classes emit Qt signals. In many cases, we end up proxying these signals by responding to them in the hand-written Tp::DBusProxy subclass by emitting a different signal, in order to give them a nicer representation.

Becoming invalid This is IPC, and any error can happen to you at any time. We found that it was useful to have a general concept of "this object is no longer useful", so we introduced the concept of an object becoming invalidated. The invalidation reason is stored on the object as a GError. If this GError is NULL (as it is initially), then the object is still expected to be valid; if it's non-NULL, the remote object has vanished and the local proxy no longer works. There are several ways a TpProxy can become invalid:
  • its bus name falls off the bus (the process exited or crashed)
  • application-specific reasons (usually triggered by a D-Bus signal in a subclass, like the Telepathy Channel's Closed signal)
  • the GObject gets disposed
Method calls on an invalidated object always fail, with the invalidation reason as the error. This means that calling a method on a TpProxy should never crash your process. The method's callback has to be prepared to handle an error in any case, because this is Sparta^WIPC, so there's no loss in giving it another error. Connecting to signals on an invalidated object always fails, and any existing signal connections are disconnected when it becomes invalidated. This means that if a new remote object appears, and it happens to have the same object path, bus name etc. as the old one, you won't get its signals. A TpProxy can either be bound to a unique bus name or a well-known bus name. In the equivalent code in telepathy-qt4, we call this "stateful" or "stateless" - these names don't capture the intention perfectly, but they're the best we could come up with. A proxy for a stateful API like Telepathy's Channel should always bind to a unique name - when the unique name falls off the bus, the TpProxy becomes invalidated automatically, representing the fact that the Channel you had no longer exists, and nothing can be a perfect replacement for it (the VoIP call has already been terminated, you've already left the chatroom, or whatever - if you make another Channel, that's e.g. a distinct VoIP call). A proxy for a stateless API like Telepathy's ConnectionManager, where an exiting process can disappear, be service-activated again, and still have exactly the same API, should bind to the well-known name. Proxies for well-known names aren't invalidated when the process exits. Qt doesn't have a natural equivalent for GError, so the invalidation reasons in telepathy-qt4 are just a pair of strings, the namespaced name and the message - basically a libdbus DBusError. The principle is the same, though.

Optional interfaces As mentioned above, TpProxy instances are per-remote-object (per-object-path) like in dbus-python, rather than per-interface like in dbus-glib or QtDBus. I believe that this is the most natural object mapping for the D-Bus object model, because the D-Bus interfaces on a remote object can behave like any of these:
  • classes and subclasses (Telepathy.Channel.Type.Text is a Telepathy.Channel)
  • shared interfaces (some Telepathy.Channel objects, of many Types, implement Telepathy.Channel.Interface.Group; any D-Bus object can implement DBus.Properties)
  • optional features (some Telepathy.Channel.Type.Text objects implement Telepathy.Channel.Interface.ChatStates, some do not)
  • discoverable extensions (some Telepathy.Channel.Type.Text objects implement Telepathy.Channel.Interface.Messages, which is more or less Text 2.0)
The way in which interfaces are discovered is also variable. The "classic" D-Bus way to discover interfaces would be to call Introspect. Telepathy services still support that style of introspection, but we don't use it for anything beyond d-feet:
  • Introspect returns a blob of XML, which you have to parse into something useful; if it was in a D-Bus data structure, you'd already have some sensible data structure.
  • Finding out more information about the supported interfaces than their names isn't very useful: in a static language like C you already need to know the methods, signals, properties and their signatures in order to write and compile your code, and in a dynamic language like Python consumers of Introspect end up being remotely crashable by services with unexpected method signatures (this is one of dbus-python's big mistakes in my opinion).
  • If a method that you want to call turns out to be missing, the worst that can happen (in a competently written service) is that it fails with a D-Bus error - and you have to handle D-Bus errors anyway, because this is IPC and anything could fail.
  • Static bindings like dbus-glib have poor support for removing interfaces for which C code exists at runtime, whereas Telepathy needs features like an IM connection that might or might not support avatars (we don't get to find out until we've successfully connected to the server).
Instead, our older interfaces have a method on the "base class" (Channel, Connection etc.) called GetInterfaces, which just returns an array of strings. Newer interfaces (like Account), and older interfaces that have been ported (like Channel), have a property called Interfaces which is, again, an array of strings - this lets us combine the download of the interfaces list with downloading other basic information in a GetAll call. To cater for all these ways to use interfaces, the TpProxy base class has very basic support for interface discovery - you can ask it whether it supports an interface, and you can tell it that it does, in fact, support an interface. Asking which interfaces are supported is directly useful for library users; it's also used as a check by the generated method-call and signal-connection stubs, which return a canned error (Telepathy.Error.NotImplemented in Telepathy's case) if the object isn't known to have the interface. Telling TpProxy that it does support an interface is intended for use by subclasses, and might have been protected if we were writing C++: what happens in practice is that a concrete subclass like TpChannel knows how to discover the fully supported interfaces for this particular object, does so, and calls methods on the TpProxy to tell it which interfaces can work.

Extensibility The API stubs used by TpProxy to call methods and bind to signals are generated from XML documents containing an augmented form of D-Bus introspection data. These XML documents contain various Telepathy-specific extensions, but none of the extensions are language-specific - telepathy-glib, telepathy-python and telepathy-qt4 all operate from exactly the same XML specification. telepathy-qt4's different object-mapping did require us to tighten up some rules that were previously only conventions, but even so, the format is the same. I think this is vitally important - it just doesn't scale to have one set of language-specific annotations in a D-Bus API for each language that will have bindings. One thing that we make heavy use of is what I call "Ugly_Case", which is camel-case with underscores at word boundaries. This gives us a simple, unambiguous and foolproof rule to use in code generators whenever we generate any of the popular conventions for identifiers:
  • CamelCase: delete underscores
  • javaCamelCase: force everything before the first underscore to lower case, then delete underscores
  • lower_case: force everything to lower case, retain underscores
  • UPPER_CASE: force everything to upper case, retain underscores
dbus-glib, by contrast, applies a complex and subtly buggy algorithm to the CamelCase D-Bus names, which results in our SendDTMF method being mapped into GLib as send_dt_mf, and requires that telepathy-glib's Python reimplementation of dbus-binding-tool uses a bug-for-bug compatible implementation (we ended up reimplementing dbus-binding-tool in order to generate the TpProxy-based bindings). Our code generation tools are still rather ad-hoc, because so is our spec format, but for draft interfaces it's possible to copy them into individual projects and use them to generate additional methods for TpProxy or any subclass. This is how we implement unfinished APIs like geolocation in Empathy, for instance. The Interfaces or GetInterfaces hook described above is entirely usable for these extension interfaces, and in fact that's how they're set up. In telepathy-qt4, the generated method stubs are genuine C++ methods, so we can't just append methods to an existing class: this is why we have one helper class per interface, so individual clients can generate a helper class for their particular version of an unfinished API, and instantiate an object of this class attached to a particular Tp::DBusProxy. When an interface becomes stable, it can be added to the set of interfaces for which code is generated in telepathy-glib or telepathy-qt4, at which point any client or service that was already using the final draft of that interface can easily be ported to the library version using sed (the API remains the same).

Becoming ready The concept of being "ready" does not directly exist in TpProxy, but is implemented in TpChannel, TpConnection and TpConnectionManager. The idea is that a freshly created proxy object isn't really fully usable yet - you have to connect to basic signals and recover the initial state of the remote object, as well as checking which extension interfaces are supported. In many well-designed D-Bus APIs you can do this initial setup with a few signal connections and a DBus.Properties.GetAll call. After doing that initial setup (which has to be done asynchronously, because it's IPC), the TpProxy subclass has a local cache of the remote object's state (not necessarily in the same format as the representation on the bus), which can be accessed synchronously at any time, and will be updated in response to change-notification signals. TpChannel and subclasses like it have explicit support for checking for readiness, and having a callback called when the object is ready or invalidated (whichever happens first). The "ready" property also supports the GObject notify signal. telepathy-qt4 took this concept and ran with it - there is library support for objects that can become ready, including a mixin. If I had as much time to work on telepathy-glib as I wish I had, this would be one of the first telepathy-qt4 features to be added to telepathy-glib.

Features becoming ready Going beyond that, in an extensible framework like Telepathy it's probable that not every client understands (or wants to understand) every feature of every object, so it's highly inefficient for every proxy object to subscribe to all the change notification signals and cache all the remote state on the off-chance that the library user wants them. In the API for TpContact (which is not actually a TpProxy for various reasons) we introduced the concept of optional features; telepathy-qt4 extended this idea throughout the library. The idea is that each library user knows which of the optional features are "interesting" to it, and makes a single asynchronous call (which expands into a series of D-Bus calls inside the library) to download the state for core functionality plus all of the selected features, and subscribe to change notification for all of those. This is another telepathy-qt4 thing that telepathy-glib still needs to catch up with; until someone works out how to make the clone() syscall apply to programmers, I fear all libraries are doomed to lag behind how their designers want them to look :-) (license: CC-BY-3.0 / LGPL-2.1+)

30 April 2009

Biella Coleman: On Chasing Plastic

Anyone who knew me prior to 2000, knew me as a fanatic Ultimate Frisbee player. I was (mostly) all about chasing a plastic disc on lush green fields. Ultimate Frisbee, which took my attention and soul my first year of college, commanded my attention, time, and body for years. The New York Times just ran a nice short piece piece about Ultimate Frisbee, which apparently has skyrocketed in popularity since 2003. One section of the article caught my attention:
It may be a non-contact sport according to its rules, but Ultimate is hardly free of injuries. The quick cutting and sprinting have made anterior cruciate ligament tears among women players especially common. JOY CHEN, a 33-year-old software developer in Alameda, Calif., considers herself lucky that herniated disks, a rotator cuff tear and ankle sprains have been the extent of her Ultimate injuries. We hit each other and the ground pretty hard, said Ms. Chen, who discovered Ultimate in college after years as a soccer and tennis player. She played with Stanford University s Superfly, which went on a three-year run as undefeated women s national collegiate champions.
Injury goes with the sport as hand and glove and young players tend to wear these injuries as a badge of pride. As much as I adore the sport and there are days I get pretty bummed that I no longer play I think that the UPA and older players should seriously skool the younger generation on the danger of injuries. It is an extreme sport that requires extreme care. Tournaments are usually composed of 4-7 games over the course of 2 days. If that is not demanding enough, the body gets pretty intimate with the the ground while laying out and then there are there all those sprained ankles and broken bones and ligaments from collisions. Today I suffer from bouts of knarly neck pain, for example, which is due in part from playing without taking proper precautions. One of my best friends, who was a stellar player in college, also suffers from pretty devastating back pain. It is an extreme sport that requires extreme care. I say toss out the pride in pain/injuries and in place, instill a healthy sense of fear of the injuries so that people get proper long term and sustained care for their injuries so that they can keep on playing the world s best sport. PS For those that don t know, UF also revolves around an ethical philosophy Spirit of the Game, which unfortunately the article makes no mention of, despite its centrality to the sport.

Pablo Lorenzzoni: EeePC: Surviving liquid spills

Last few months since I got my EeePC have been a lot of fun. Playing and tweaking the little bastard is a joy in the end of a busy day. Besides, since I loaded it with the most useful SysAdmin tools, it became a powerful device in my tool belt . Unfortunately, I ve been stupid enough to drink a glass of orange juice while messing with it. I know, I know! Silly thing to do. I should know better! But life is like that I spilled a few drops over it. Of course, the web is pouring off information on what to do in cases like this, so I ll just summarize what I did:
  1. Imediatelly, without thinking or questioning, I turned it upside down and removed the battery. It was a clumsy thing to do I ended up spilling the rest of my orange juice on the floor while worrying about the EeePC. Concearns about filesystem corruption (or whatever) crossed my mind, but I can always deal with that later First things first!
  2. I went online in another computer and found out how to disassemble it. For me it was easy, since I got other two computers at home but if I needed to leave it there while looking for information, I would! If it s upside down and has no power whatsoever (the battery was removed), it s safe, I think. The information was easily found. I decided I didn t need to disassemble all of it, but having those information at hand was pretty useful.
  3. I began by removing the keyboard. It s tricky but not difficult. The secret relies on the spring-mounted tabs near the screen. I checked for spills under it and cleaned with a cotton swab.
  4. I was not very confortable to open the case, but I decided that turning it back on without checking the electronic parts first was too risky. So I said goodbye to my warranty and unscrewed the 6 screws from the bottom and the 9 from the silver casing under the keyboard.
  5. There I found some little drops! Good decision to open it up! I dried it using cotton swabs again.
  6. Before putting it all together, I decided to leave it open until the next day. I was pretty sure everything was dry again, but better safe than sorry . The next day I successfully assembled it and turned it on. Great! Everything worked fine.
Now that was just what worked for me. My EeePC is back, fully restored but, of course, the warranty is void :-( So I cannot recommend you to do the same. Best advice I can tell you: Keep liquids away your EeePC!

29 April 2009

MJ Ray: Bristol Social Enterprise Summit Consultation

Last Thursday, I went to the Social Enterprise summit regional workshop that I mentioned. Apparently, SEC are hoping that ministers Mandelson, Purnell, Byrne and Blears will be at the summit, along with people from various famous co-ops. I took along some email feedback I received on supporting new blood in social enterprise about needing help to bridge the gaps (financial, social, training) between taking on new members and them being productive enough to break even . Happily, that was echoed and reinforced by other delegates - I shared a table with people from Trinity Community Arts, AvonCDA, Sofa Project, Somerset Co-operative Services and Community Action. Emboldened by that, I ranted about the Business Support Simplification Programme (which seems to mean that only BusinessLinkSW has any gov.uk money in our region and they re being really poor at co-op support) and I threw a couple of ideological-explosives into the consultation, suggesting that franchising has failed as a way of spreading social enterprise and we need to start offering General Public Licensing of our business models, because we re not franchising businesses and most of us don t want to be. I wonder if that idea will detonate somewhere helpful. The Social Enterprise Coalition officers had some details of the support programmes that are already announced. One of them is a golden hello where the enterprise gets money when a new person joins. It s run by jobcentreplus. So yesterday, when I was at a Business Link Real help for business event, I asked the jobcentreplus officers there about it: apparently it s useless to TTLLP because all our workers are partners and not employees. I was expecting more support for co-ops from a Labour+Co-op government, but it shouldn t've been a surprise after the budget. After that, I don t think it s worth posting details of the other SE assistance programmes mentioned: they ll probably turn out to be equally useless for co-ops and I don t want to waste your time. I ll rant about that and the BusinessLinkSW event another day or in another place. Ask me if you want details and I ll put them in a comment or email them. And in that spirit, it s back to programming for me!

Antti-Juhani Kaijanaho: Initramfs problems with the new kernel-package, and a solution

I ve been using Manoj s new kernel-package for some weeks now, and used it to compile two kernels (a reconfigured 2.6.29.1 and the new 2.6.29.2). Both times I ve had trouble with initrd. As the documentation says, kernel-package kernel packages no longer do their own initramfs generation. One must copy the example scripts at /usr/share/doc/kernel-package/examples/etc.kernel/postinst.d/initramfs and /usr/share/doc/kernel-package/examples/etc.kernel/postrm.d/initramfs to the appropriate subdirectories of /etc/kernel/. However, this is not enough. My /etc/kernel-img.conf file had the usual posthook and prehook lines calling update-grub. Unfortunately, those hooks are called before the postinst.d hooks, and so update-grub never saw my initramfs images. Fix? I removed those lines from /etc/kernel-img.conf and created a very simple postinst.d and postrm.d script:
#!/bin/sh
update-grub
I call the script zzz-grub-local, to ensure that it runs last.

28 April 2009

Russell Coker: Redundancy in Network Infrastructure

It s generally accepted that certain things need redundancy. RAID is generally regarded as essential for every server except for the corner case of compute clusters where a few nodes can go offline without affecting the results (EG the Google servers). Having redundant network cables with some sort of failover system between big switches is regarded as a good idea, and multiple links to the Internet is regarded as essential for every serious data-center and is gaining increasing acceptance in major corporate offices. Determining whether you need redundancy for a particular part of the infrastructure is done on the basis of the cost of the redundant device (in terms of hardware and staff costs related to installing it), the cost of not having it available, and the extent to which the expected down-time will be reduced by having some redundancy. It s also regarded as a good idea to have more than one person with the knowledge of how to run the servers, jokes are often made about what might happen if a critical person fell under a bus , but more mundane things such as the desire to take an occasional holiday or a broken mobile phone can require a backup person. One thing that doesn t seem to get any attention is redundancy in the machine used for system administration. I ve been using an EeePC [1] for supporting my clients, and it s been working really well for me. Unfortunately I have misplaced the power supply. So I need to replace the machine (if only for the time taken to find the PSU). I have some old Toshiba Satellite laptops, they are quite light by laptop standards (but still heavier than the EeePC) and they only have 64M of RAM. But as a mobile SSH client they will do well. So my next task is to set up a Satellite as a backup machine for my network support work. It seems that this problem is fairly widespread. I ve worked in a few companies with reasonably large sysadmin teams. The best managed one had a support laptop that was assigned to the person who was on-call outside business hours. That laptop was not backed up (to the best of my knowledge, it was never connected to the corporate LAN so it seems that no-one had an opportunity to do so) and there was no second machine. One thing I have been wondering is what happens to laptops with broken screens when the repair price exceeds the replacement cost. I wouldn t mind buying an EeePC with a broken screen if it comes with a functional PSU, I could use it as a portable server.

Florian Ragwitz: Implementing Typed Lexical Variables

For quite some time perl provided a form of my declarations that includes a type name, like this:
my Str $x = 'foo';
However, that didn't do anything useful, until Vincent Pit came along and wrote the excellent Lexical::Types module, which allows you to extend the semantics of typed lexicals and actually make them do something useful. For that, it simply invokes a callback for every my declaration with a type in the scopes it is loaded. Within that callback you get the variable that is being declared as well as the name of the type used in the declaration. We also have Moose type constraints and the great MooseX::Types module, that allows us to define our own type libraries and import the type constraints into other modules. Let's glue those modules together. Consider this code:
use MooseX::Types::Moose qw/Int/;
use Lexical::Types;
my Int $x = 42;
The first problem is that the perl compiler expects a package with the name of the type used in my to exist. If there's no such package compilation will fail. Creating top-level namespaces for all the types we want to use would obviously suck. Luckily the compiler will also try to look for a function with the name of the type in the current scope. If that exists and is inlineable, it will call that function and use the return value as a package name. In the above code snippet an Int function already exists. We imported that from MooseX::Types::Moose. Unfortunately it isn't inlineable. Even if it were, compilation would still fail, because it would return a Moose::Meta::TypeConstraint instead of a valid package name. To fix that, let's rewrite the code to this:
use MooseX::Types::Moose qw/Int/;
use MooseX::Lexical::Types qw/Int/;
my Int $x = 42;
Let's also write a MooseX::Lexical::Types module that replaces existing imported type exports with something that can be inlined and returns an existing package name based on the type constraint's name.
package MooseX::Lexical::Types;
use Class::MOP;
use MooseX::Types::Util qw/has_available_type_export/;
use namespace::autoclean;
sub import  
    my ($class, @args) = @_;
    my $caller = caller();
    my $meta = Class::MOP::class_of($caller)   Class::MOP::Class->initialize($caller);
    for my $type_name (@args)  
        # get the type constraint by introspecting the caller
        my $type_constraint = has_available_type_export($caller, $type_name);
        my $package = 'MooseX::Lexical::Types::TYPE::' . $type_constraint->name;
        Class::MOP::Class->create($package);
        $meta->add_package_symbol('&'.$type_name => sub ()   $package  );
     
    Lexical::Types->import; # enable Lexical::Types for the caller
 
1;
With that the example code now compiles. Unfortunately it breaks every other usecase of MooseX::Types. The export will still need to return a Moose::Meta::TypeConstraint at run time so this will continue to work:
has some_attribute => (is => 'ro', isa => Int);
So instead of returning a plain package name from our exported function we will return an object that delegates all method calls to the actual type constraint, but evaluates to our special package name when used as a string:
my $decorator = MooseX::Lexical::Types::TypeDecorator->new($type_constraint);
$meta->add_package_symbol('&'.$type_name => sub ()   $decorator  );
and:
package MooseX::Lexical::Types::TypeDecorator;
use Moose;
use namespace::autoclean;
# MooseX::Types happens to already have a class that doesn't do much
# more than delegating to a real type constraint!
extends 'MooseX::Types::TypeDecorator';
use overload '""' => sub  
    'MooseX::Lexical::Types::TYPE::' . $_[0]->__type_constraint->name
 ;
1;
Now we're able to use Int as usual and have Lexical::Types invoke its callback on MooseX::Lexical::Types::TYPE::Int. Within that callback we will need the real type constraint again, but as it is invoked as a class method with no good way to pass in additional arguments, we will need to store the type constraint somewhere. I choose to simply add a method to the type class we create when constructing our export. After that, all we need is to implement our Lexical::Types callback. We will put that in a class all our type classes will inherit from:
Class::MOP::Class->create(
    $package => (
        superclasses => ['MooseX::Lexical::Types::TypedScalar'],
        methods      =>  
            get_type_constraint => sub   $type_constraint  ,
         ,
    ),
);
The Lexical::Types callback will now need to tie things together by modifying the declared variable so it will automatically validate values against the type constraint when being assigned to. There are several ways of doing this. Using tie on the declared variable would probable be the easiest thing to do. However, I decided to use Variable::Magic (also written by Vincent Pit - did I mention he's awesome?), because it's mostly invisible at the perl level and also performs rather well (not that it'd matter, given that validation itself is relatively slow):
package MooseX::Lexical::Types::TypedScalar;
use Carp qw/confess/;
use Variable::Magic qw/wizard cast/;
use namespace::autoclean;
my $wiz = wizard
    # store the type constraint in the data attached to the magic
    data => sub   $_[1]->get_type_constraint  ,
    # when assigning to the variable, fail if we can't validate the
    # new value ($_[0]) against the type constraint ($_[1])
    set  => sub  
        if (defined (my $msg = $_[1]->validate($  $_[0]  )))  
            confess $msg;
         
        ();
     ;
sub TYPEDSCALAR  
    # cast $wiz on the variable in $_[1]. pass the type package name
    # in $_[0] to the wizard's data construction callback.
    cast $_[1], $wiz, $_[0];
    ();
 
1;
With this, our example code now works. If someone wants to assign, say, 'foo' to the variable declared as my Int $x our magic callback will be invoked, try to validate the value against the type constraint and fail loudly. WIN! The code for all this is available github and should also be on CPAN shortly. You might notice warnings about mismatching prototypes. Those are caused by Class::MOP and fixed in the git version of it, so they'll go away with the next release. There's still a couple of caveats, but please see the documentation for that.

27 April 2009

Gunnar Wolf: Damn you pigopolists! (or whatever)

We have had a quite strange couple of days... Everything was smooth as usual on Thursday. As I posted here, I cycled to Iztacala to give a talk and back, and basically had a good time. We had heard news some days earlier on the radio that the usual seasonal flu was still present by mid-April, while usually it disappeared by early March... But nothing more. But Friday morning, as I listened to my usual news program, Aristegui repeated over and over that the Health ministry had ordered (in a press conference at 23:00 the previous day) schools of all levels not to hold activities... Quite unusual, but WTF... Got to work as usual, around 9 AM. The first thing I see in the Institute, our Academic Secretary telling us all to finish our most urgent business and head back home, do not pass go, do not collect $200. And... During the morning it started sinking in. This is a very weird and somehow scary situation. We are facing -as you all must know by now- a previously unknown strain of flu virus (influenza porcina H1N1B, AFAICT). During the past couple of days, we have seen the scenes we wondered about during the past decade, mainly in South East Asia (with SARS and with bird flu): Everybody is scared, nobody really understands what they are scared of, people do stay at home. The streets are eerily quiet, and many people are seen with masks covering nose and mouth. I must recognize our federal and local governments are acting very well coordinated (for the first time in probably over a decade, since they were from different parties for the first time). This has been clearly labeled as an epidemic (over 1600 sick people reported at hospitals, and over 100 deceased) and has spread to many of our country's states (as well as to other many countries, although it still seems to be controlled there - But we have got reports from the USA, Canada, France, Spain, Israel and New Zealand so far). I will most probably spend the next full week at home, as my University (as well as all schools and universities in this city and at least the Mexico, Nuevo Le n and San Luis Potos states) will be closed until May 6th. Of course, sports and cultural activities are all suspended as well. Many (most?) bars and restaurants remain closed. Today, my parents came from neighbouring Cuernavaca (where no alerts have yet been emitted, but will surely follow), and we went out for lunch (to a nice Yucatan food place, chosen partly as it had very little concurrence and because we could sit outdoors. Yes, I must specially thank them for being as imprudent as coming over here, given the generalized scare... I know there was nothing I could do to prevent them from doing so :-) And... In this strange climate, I can only thank I am not a party-organizer or anything like that, as I'd have had my plans frustrated. Here I sit next to my laptop, in my halfway-re-windowed house, with a still shrink-wrapped book that looks beautiful (La bicicleta: Rito, t cnica y pasi n), eager to open it (Thanks, Nadezhda! :-* ). Happy birthday to me. Take off the mask, blow 33 candles, put mask back on. Thankfully there is no cake to eat, as it could be messy with the mask on.

26 April 2009

Dirk Eddelbuettel: R / Finance 2009

Our inaugural R / Finance conference, mentioned here twice is now over. We were fortunate to get seven outstanding invited keynote speakers, as well as eleven excellent presentations. This was preceded by four short tutorials (and I'll post slides from my Introduction to High-Performance Computing with R soon). With about 150 registered participants, plus keynoters, presenters, committee members, representatives from the sponsors (a quick shout of Thanks! to them), some folks from UIC (especially Holly without whom few things would have happened), we were probably around 200 people gathered at UIC. And then there was an extended social program at Jaks which is rather appropriate as we had numerous important committee meetings there over the preceding months. All in all it seems like a successful event. We may even do it again.

Florian Ragwitz: Declaring Catalyst Actions

For a long time the Catalyst Framework has been using code attributes to allow users to declare actions that certain URLs get dispatched to. That looks something like this:
sub base    : Chained('/')    PathPart('') CaptureArgs(0)   ...  
sub index   : Chained('base') PathPart('') Args(0)          ...  
sub default : Chained('base') PathPart('') Args             ...  
It's a nice and clean syntax that keeps all important information right next to the method it belongs to. However, attributes in perl have a couple of limitations. For one, the interface the perl core provides to use them is horrible and doesn't provide nearly enough information to do a lot of things, but most importantly attributes are just plain strings. That means you will need to parse something like "Chained('base')" into (Chained => 'base') yourself to make proper use of them. While that's easy for the above example, it can be very hard in the general case because only perl can parse Perl. It's one of the reasons you can't use Catalyst::Controller::ActionRole to apply parameterized roles to your action instances, because parsing parameters out of things like Does(SomeRole => names => [qw/affe tiger/], answer_re => qr/42/ ) would be awful and wrong. With Catalyst 5.8 most of the attribute related code has been removed from the internals. It's now using MooseX::MethodAttributes to do all the heavy lifting. Also the internals of how actions are registered have been refactored to make it easier to implement alternate ways without changing the Catalyst core. As a proof of concept for this I implemented a new way of declaring actions that's very similar to how Moose provides it's sugar functions. You can get it from github. With that, the above example looks like this:
action base    => (Chained => '/',    PathPart => '', CaptureArgs => 0) => sub   ...  ;
action index   => (Chained => 'base', PathPart => '', Args    => 0    ) => sub   ...  ;
action default => (Chained => 'base', PathPart => '', Args    => undef) => sub   ...  ;
It also moves method declaration from compiletime to runtime, making this possible:
for my $action (qw/foo bar baz/)  
    action $action => (Chained => 'somewhere', Args => 0) => sub  
        my ($self, $ctx) = @_;
        $ctx->stash->  $action   = $ctx->model('Foo')->get_stuff($action);
     ;
 
Admittedly, that's all very ugly, but illustrates well what kind of things we're able to do now. But it doesn't need to be ugly. With Devel::Declare we have a great tool to add our own awesome syntax to perl, similar to how things like MooseX::Method::Signatures, MooseX::MultiMethods and MooseX::Declare do. So how would a declarative syntax for Catalyst controllers look like? I don't know. Ideas include something like this:
under /some/where, action foo ('foo', $id)   ...  
to mean:
sub foo : Chained('/some/where') PathPart('foo') CaptureArgs(1)   ...  
Adding Moose type constraints to this would be interesting, too, and make validation of captures and arguments a lot easier. Multi dispatch similar to MooseX::MultiMethods could be handy as well:
under /some/where  
    action ('foo', Int $id)  
        # find and stash an item by id
     
    action ('foo', Str $name)  
        # search items using $name
     
    action ('foo', Any $thing)  
        # display error page
     
 
So you see there are a lot of possibilities that should be explored. Unfortunately I have no idea what kind of syntax and features people would like to have, so your feedback on this would be much appreciated. :-)

Next.

Previous.