GTG GSoC, week 7 — "Testing, testing, 1, 2, 3..."

Recently I have been working on two things related to achieving a client-server separation in Getting Things GNOME!

One is a test suite that will cover all aspects and functionality of the DBus interfaces. The second is low-level code to support the interfaces themselves.

Why not do them in sequence? Well, tinkering with the low level code is helping to outline what will and will not be possible with the
"DBus magic" I've blogged about on two previous occasions. Tests don't have to target against code that already exists, but they should at least target code that could exist.

To explain more, the concept is to have more than just a DBus interface on the server. For the client, the dbus-python ProxyObject and Interface classes are a useful starting point, but I want to go further and let GTG! clients behave as if the objects they are handling were local (although, as James pointed out, clients will be faster if they don't naïvely trigger too many calls on the bus). This means providing a client library that clients can optionally import and use, instead of grappling directly with the server's DBus interface.

In coding this client library several interesting winkles have come up. For example, the DBus tutorial discusses the distinction between well-known names ('org.gnome.GTG') and unique names (:34-907)—but these are only for buses. Each object (e.g. a GTG! Tag or Task) available on a bus needs to have an object path ('/org/gnome/GTG/Task/12345' or '/org/gnome/GTG/Task/54321').

Because of the DBus message-passing architecture, there is no way to know if anything exists at a given object path, until you try to access it. By analogy, the Internet's Domain Name System (DNS) can tell you that my website paul.kishimoto.name exists at such-and-such an IP. But to determine if there is anything at a specific URL (http://paul.kishimoto.name/notapage), you need to try to access it and maybe get an HTTP .

Clients only care about actual Tasks and Tags, and repeatedly checking that its proxies still reference valid targets would be a pain in the neck. The solution is to provide helper code that checks the remote object exists before it hands a proxy to the client.

Another problem that is cropping up is that the client needs to be able to understand and manipulate the tree hierarchy of Tags and Tasks, over the bus. But that will be another post...

Ignorance, or spite

Some thoughts on the occasion of the G20 summit in Toronto.

The police presence and violent protest were both of a scale unprecedented for this city. The security cost, at over $1 billion, was also unprecedented in the history of the G-summits and is unlikely to ever be equalled.

Much ink will be shed on the taxonomy of protesters (a term which, apparently, also now includes opportunist vandals with no policy demands), the validity of their various motives and the contemptible nature of their actions. Equally, the actions of individuals among the tens of thousands of police involved will be put under the microscope.

Both those debates will prove fruitless. To me, it is more important to see the three outsized aspects of the event—police presence, violence and cost—as foreseeable consequences of the unnecessary and astoundingly poor choice of a venue for the summit.

I have heard two believable theories about how the choice was made: ignorance and spite.

The 'ignorance' theory was advanced on CBC's The Current by Deborah Cowen of the University of Toronto. She noted that the Conservative government, with almost no seats in Toronto, Montréal or Vancouver, has an essentially rural background on which it draws and little firsthand knowledge about how large cities actually are. The implication is that they might have honestly but falsely believed that the effect of promoting Toronto, Ontario and/or Canada would outweigh any disruption caused by security measures and protests.

The 'spite' theory (of my more cynical friends) holds that the disruption was expected and anticipated by the government. In this view, the decision was to be seen—and appreciated—by the Conservatives' rural base as a giant middle finger raised towards Toronto and its citizens.

The first explanation wins by Ockham's Razor, at least; but whichever is more accurate, it is certain the decision was made for political, not economical (read: cost-saving) reasons.

To explain a bit more why I think the choice was 'astoundingly poor,' and the consequences 'predictable' I will channel Jane Jacobs, late Torontonian, whose The Death and Life of Great American Cities I recently read and enjoyed. Any errors in my paraphrase of her writings are, of course, my own.

One of Jacobs' criteria for distinguishing Great (very big, large scale; important) Cities is diversity of use. On a summer weekend in Toronto, the downtown streets might be used by shoppers, baseball fans, theatregoers, businesspeople, diners, marketers, people-watchers, store clerks, deliverymen, walkers, those passing through to the lake or parts west, east or north, local residents, café patrons, cyclists, taxi drivers, buskers, runners, transit staff, and a whole cast of others my imagination is too weak to summon. The vast majority of these people are strangers to one another, but their mere presence civilizes the streets, so that events like the 2005 Boxing Day shooting of Jane Creba are truly rare, unexpected and shocking.

Jacobs contrasts diverse use with the atmosphere in single-use residential projects, where the same advantages (many eyes at all hours) are not enjoyed and, not coincidentally, comparatively more gang-related violence occurs.

During an event like the current summit, normal usage is suppressed. Within the security perimeter, there is no use at all by locals. Security measures impede normal use in surrounding areas, so that the Blue Jays and theatres take their business elsewhere or cancel whole performances (even at large cost). People who would have attended these larger events have no reason to be in the same areas for meals and other secondary activities. The secondary businesses they would have frequented, always sensitive to demand, run reduced staffs, further depleting the stock of people on the streets. And so on. In the current, extraordinary situation, even residents flee who are able to stay with friends in the suburbs or out of town.

Note that at no point is a collective decision made along the lines of, "Let's turn over the streets to rioters!"; instead, the deadening is an aggregate result of reasonable responses by normal individuals.

The few uses that remain can be numbered on one hand: peaceful protesting, spectating (both amateur and professional), policing and violence. The dead streets are a boon only to those engaged in the latter two activities, who find it easier to identify members of the other groups without actual citizens around.

Without any hysterics about professional anarchists or police agents provocateurs, then, it is easy to see why emptying the city invites situations that would be impossible under everyday circumstances. That this conclusion can be reached on the basis of accessible, popular writing from the 1960s makes me doubt that no one in government raised an objection to the choice of location. Mayor David Miller and other representatives of the city claim openly that they put forward the Exhibition grounds (which, note, are already largely empty) as an alternative.

Those voices were obviously disregarded when the decision was made, and that disregard is the root cause of everything we have witnessed.

GTG GSoc, week 4 — Magic, dates, specs and more shuffling

My fourth Getting Things GNOME! Summer of Code week had four work foci (a trend which will hopefully not continue 'til week 10...)

One, I put up some code to the Planet, having been encouraged by good responses to earlier queries. This time I stuck my neck out by proposing something larger, and in short order was told three new things to consider—for example, the mixin concept. With this input, I have improved my FancyInterface, which lets you access DBus properties as Python attributes of ProxyObjects. Check out the code (standalone, for the moment) here.

Many of the the fields in the GTG data model will be exported as DBus properties using the above code. These chunks of XML code give an overall picture of the interfaces that will be used in GTG, in the standard DBus introspection format.

Third, I've proposed a new Date class for GTG. Dates in GTG go beyond what's provided by the datetime module, because we support some 'fuzzy' concepts like now, soon and later. Not only must these be stored and sorted (alongside fixed dates and non-/null dates), but they'll have to go over DBus as strings once my project is complete...hence the new class.

Fourth and last, the divorce proceedings for existing code continue! With OfflineIMAP (highly recommended) as my inspiration, this merge will make the "gtg" executable your one-stop shop for GTK, command-line and other, future UIs. Forcing "gtcli" and "gtg" together helped me see which dependencies were of one UI; which were of all UIs, and which things are needed by both the UIs and core.

Class attributes with dbus-python

DBus is great, and so is Python—each for their own reasons. One mismatch is that everything passing over the bus must be a message or signal. You wind up with Python code that looks like

  proxyobject.SetThis('foo')
  bar = proxyobject.GetThat()
  proxyobject.DoSomeOtherStuff()

But then you realize the dbus-python binding is very Pythonic, so you can extend it in a Pythonic way. Here's something I banged together in about half an hour:

import dbus

class FancyInterface(dbus.Interface):
    """A fancier DBus Interface.
    
    Derived classes should define a list of strings __dbus_properties__ and a
    _dbus_interface. For every listed property ('foo') the named interface
    should support two methods:
      * GetFoo() -- accepts nothing, returns a single value.
      * SetFoo(..) -- returns nothing, accepts a single value of the same type
        as GetFoo.
    
    Then DerivedClass.foo may be accessed as if it were a normal variable.
    
    """
    def __init__(self, object):
        # next four lines from dbus.Interface.__init__()
        if isinstance(object, dbus.Interface):
            self._obj = object.proxy_object
        else:
            self._obj = object
        # set up properties
        for a in self.__dbus_properties__:
            fget = lambda self: self._obj.get_dbus_method('Get' +
              a.capitalize())()
            fset = lambda self, value: self._obj.get_dbus_method('Set' +
              a.capitalize())(value)
            setattr(self.__class__, a, property(fget, fset))


class Sample(FancyInterface):
    _dbus_interface = 'com.example.SampleInterface'
    __dbus_properties__ = ('foo', 'bar',)
    def __init__(self, object): FancyInterface.__init__(self, object)
    # this class is 'empty' otherwise...

Using FancyInterface, it becomes even easier to forget you're talking to a proxy of a remote object:

    bus = dbus.SessionBus() 
    o = Sample(bus.get_object('com.example.SampleService',
      '/SomeObject'))
    o.foo = 'Hello, '
    o.bar = 'world!'
    print o.foo, o.bar

Look for this stuff being used in GTG in the near future! (Also, fixes to my blog CSS...)