Recent blog entries for jdahlin

16 Aug 2006 (updated 16 Aug 2006 at 17:45 UTC) »
Testing a dynamic language

A colleague recently complained to me that I'm forcing him to write a unittest without a good reason. He had written a small method which he told me that there's almost no way of breaking, it's so trivial that it doesn't need a test.

The code in question was written in Python and looked like this:

from some.module import Settings

class Object(Base): def is_fluff(self): return self.state == Settings.STATE_FLUFF

In his change he added the is_fluff method, which wasn't previously defined (but self.state) was.

I told him that there are a actually possible to break the method in a number of different ways:

  1. by changing the method name
  2. by changing the attribute name
  3. by changing the constant name
  4. by changing the constants module name
  5. by changing the type of the attribute
  6. by changing the type of the constant
  7. by changing the value of the constant
  8. by changing the operator
  9. by changing the function prototype
  10. by removing the return keyword
  11. by subclassing the object and overriding the method

This is not a complete list since Python is a very dynamic language. You can change the behavior of objects in various interesting ways. Overriding attribute lookup, the comparision operator, class creation, method invocation etc etc etc

So by writing a very simple test like this:

o = Object()
o.state = Settings.STATE_KLARKE
assert not o.is_fluff()
o.state = Settings.STATE_FLUFF
assert o.is_fluff()

The moral of the story is that we're actually testing a lot more than just a simple comparision in a dynamic language like Python where the compilation process is very simple.

This is not an attack on dynamic languages like Python. A language which does extensive type checking at compilation time is likely to catch a few of the possible errors I listed, but not all of them. The most dangerous one is changing the value of the constant, no tool in the world can help you catch that. (assuming our object is going to live longer than the time of our program, eg the values are going to be saved in a database)

You'll need to write a unittest for your program regardless of the language you choosed to implement it in. Python makes it easy to write and maintain code and since unittests should be written anyway it's on the winning side ;-)

Pyflakes and Subversion

Pyflakes is a nice little utility that checks your Python code for errors. The main advantage over PyChecker and PyLint is that it is much faster and gives almost no false positives. Today I wrote a little hack on top of the enforcer pre-commit script which forces the code you check in to pass pyflakes. Eg, the users of svn will see the following output if they try to check in code which has errors pyflakes can detect:

$ svn ci -m "fix" completion.py
Sending        completion.py
Transmitting file data .svn: Commit failed (details follow):
svn: 'pre-commit' hook failed with error output:
Pyflakes found 1 error(s)/warning(s):
kiwi/trunk/examples/completion.py:1: undefined name 'test'

The small "configuration" file for enforce can be found here.

Planet filtering

Today I decided to figure out how to filter out certain blogs from Planet GNOME. It turned out to be much easier than I thought. Just create a csimple rule using css selectors and add it to our chrome-UserContent.css file.

So if you're tired of listening to the complaints of the scandinavian cabal, add this to your customized css file:

@-moz-document domain(planet.gnome.org) {
  div.richard,
  div.hallski,
  div.uraeus { display: none; }
}
Mozilla/Firefox only, perhaps only 1.5 or newer, who cares.
31 Mar 2006 (updated 31 Mar 2006 at 10:53 UTC) »
Gedit plugins

Richards little devhelp plugin for Gedit made me motivated enough to start looking at the plugin framework.

As he points out, the interface nice: simple and straight-forward. I decided to give it a go and wrote a little plugin to do remote editing, a la gobby. It allows you to share a buffer and connect to a remote one. It's little more than a proof of concept, but it allows you to edit the same document from different instances of gedit. All done in about 200 lines of python, including a custom protocol for remote editing. Twisted made that experience almost trival.
If anyone is curious and want to try it out fetch the tarball from here.

PyGTK

Today I finally branched for Gtk+ 2.10. There are quite a few bugs with simple patches attached to in bugzilla. Gustavo suggested that we should do a bug day, which would be great. Especially if we can get a couple of new contributors.

Yesterday I got inspired by the performance work federico posted. I decided to take a look on why gnome_vfs_get_volume_monitor() was so slow. After some investigation, a few modifications (adding colors and crude execve support) to the nice pycairo script federico wrote to plot strace logs and adding some markers to bonobo-activation, I came up with the following plot:

The python script I used to test can be found here.

Just before running this I did the tail /dev/zero trick (with swap turned off) to "flush" the kernel cache.

As the graph quite clearly states, bonobo-activation-server is spending about one second listing directories, reading and parsing .server (xml) files. The gconfd-2 startup is probably not so bad (it used to be a lot worse), but I do wonder why it takes so long time to import gnomevfs.

When can we have DTrace for Linux?

18 May 2005 (updated 18 May 2005 at 12:49 UTC) »
Introspection
Been working quite a bit lately to get the new GObject introspection going. Spent too much time hunting various memory corruptions, but I finally managed to get to a point where I can do the following:

  import bank
  import Poppler
  doc = Poppler.Document('test.pdf', '')
  pages = doc.getNPages()
  print 'Document has', pages, 'pages.'

which prints out:

  Document has 247 pages.

The Poppler module is built completely from the introspection information, the Document class and all its methods are created in runtime (not lazily yet though). The constructor maps to a C function, poppler_document_new_from_file which is invoked in runtime, with help of libffi, the reference is saved and sent to getNPages which calls poppler_document_get_n_pages.

Poppler is a pdf library, which I used as a testcase because that's the only library available which has introspection information written down, all thanks to jrb.

This stuff looks really good, it's a bit more complex then manually created bindings for python, but once it's finish it'll be a lot less work. We anticipate that the python bindings, in which most of the work can be done in runtime, will be dramatically reduced, perhaps to 20-25% of the size it has today.

If you're interested to look at this stuff, it can be found in the pybank module in gnome cvs.
There is not a lot too see yet though, unless you're also developing a language binding

J5: that looks very similar to deferreds, found in twisted.
Although in a twisted world with deferreds you don't really need to specify the return type as you did in your example.

Perhaps it's worth designing the python bindings after features found in recent python versions such as generators and decorators, which wingo wrote about a couple of days ago. You might also want to take a look at xmlrpclib, which is very easy to use, thanks to excessive getattr usage. Not sure if you want to walk down that road for D-BUS, but it's definitely worth looking at.

7 Jan 2005 (updated 7 Jan 2005 at 19:51 UTC) »
PyGTK
Lot's of things happening here.
We had a great Mega BOF at MatarĂ³, most of the developers participated, we even got John to fly in from Boston for the meeting! Plenty of things discussed, we know have a better idea of what needs to be improved and what we're going to do over the next few months.
GNOME 2.10 feature freeze is just around the corner. I have a big patch from Gustavo to merge to be able to implement virtual methods. Once they're in we can finally subclass GtkContainer and GtkCellRenderer properly. And with just a little more work interfaces should be implementable as well.
On the application side it seems like the next version of Bittorrent will use PyGTK. The ui looks a lot nicer, but still has some issues (resizing, no file chooser). The cool thing is that it's also used on win32, which means our user base will increase by millions.

Life
December went by very quickly. Travelled a lot, from Ulricehamn in the country side of Sweden to Rio de Janeiro for Christmas. Finally settled down in Brazil. It's great to be back here, even I haven't realized how much I missed things here. But not for too long, a trip to Asia is not far on the horizon.

  • Fluendo
    Today is my last day for Fluendo. It's been a great year, doing tons of interesting stuff and learning even more. But great things always comes to an end. I owe some people here a big thank for believing in me and giving me a chance to work here. I'm sure I'll miss Thomas, Wim, Christian and Julien.
    Thank you guys.

  • Ubuntu conference
    I'll attend the major part of the Ubuntu conference, in Mataro, just outside of Barcelona. We're going to have a big PyGTK BOF and almost all active developers are going to be present. It'll be a great to meet everybody in person. I did a PyGTK 2.5.0 release the other day, so now people can start using the new goodies from the Gtk+ development branch. John Finlay already has an updated reference manual.

  • Seamless
    Martin Soto finally, by doing a nigera scam, released his DVD player, which is using gstreamer and python. Really fun to see people using gst-python for application. It's the missing glue for applications. We were particulary impressed by the design choice to do have the DVD virtual machine implemented in python. We didn't have any movies in the office, so I had to resort to other things for testing. The Buffy DVDs thomas had worked flamelessly with subtitles, synchronized audio/video, fullscreen and fast seeking.

  • Advogato
    I'm your master.

  • Brazil
    If I can sort my visa out, I'll be there before Christmas. Can't wait.

25 Oct 2004 (updated 25 Oct 2004 at 23:58 UTC) »

I wrote a small GConf directory wrapper using a type and GObject properties. Using this you can just select a gconf directory and then modify the properties using the standard set/get accessors from GObject:

>>> obj = watch_directory('/apps/metacity/general)
>>> obj.get_property('theme')
'Metabox'

notify:: if you want to get notification if any/some properties changes. In Python, all it takes to get notifications for a directory is this:

>>> def notify_cb(obj, pspec):
...   print obj, pspec.name, obj.get_property(pspec.name)
...
>>> obj.connect('notify', notify_cb)
As jamesh points out, I should probably separate the type creation and instantiation of the object, so it can be possible to point the type against a schema directory and instantiate over several different configuration directories.

The code can be found here, unfortunately it requires gconf from gnome-python CVS HEAD, due to some missing functions. If there is enough interest I might port this to C, because I think it would be useful to have it, in for example GConf itself.

8 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!