Small Timezone Code Snippet

Today, I was looking at how to adjust a time stamp from a log file without a timezone info to contain the local timezone, so I can stuff a timezone aware value into a database. It turns out that this is a somewhat under-polished part of the Python standard library, at least as of Python 2.6, which I am using (don't ask why). While looking for a solution, I frequently came across code that used pytz , but I wanted something that would stay within the standard library.

So here's my hodgepodge solution to the problem, which should work in most of Europe:

import time

def getTimeOffset():
    offset = time.timezone
    if bool(time.localtime().tm_isdst):
        offset = offset - 3600
    stz = "%+02.2d%02d" % (offset / 3600, offset % 3600)
    return stz

This approach is a straightforward extension of the idea presented here.

Back to top

Open Letter To Authors: Please Choose Your Publisher With Care!

Dear Author,

recently I had a discussion with a publisher where I asked for a translation of a popular non-fiction book from English into German, and offered to create it. The background for this discussion was that there are certain works, which are most relevant to their field and not easily, or even usefully, replaced, nor re-created, but which set the "gold standard" in their respective fields. Re-doing such a work is usually futile and amounts to throwing away the already-accumulated knowledge, and makes it harder for people to quote a common reference to each other. If only - in this example - an English language edition of the book exists, one can expect that people with little command of the English language will not benefit from such a book and, as a consequence, may not get into the field covered by the book, have a harder than necessary time acquiring proficiency, and/or may opt out of the field completely, turning, or staying with possible alternative technology, for which sufficient coverage in their native language is being provided.

To return to the original topic, the publisher claimed that maintaining translations was too much of a burden to them, but also declined to support, or authorize, or sub-license, content in order for me to create a translation. I can understand these arguments, as a translation will either create cost, if the publisher does it himself, or possibly (imho marginally) lost opportunity, if someone else publishes a competing book - and a licensed translation is bound to eat into the sales figures of the original book. So at first glance, immediate greed suggest that such - let's say - "derivative works" must be shot down.

However, I strongly disagree with this position, as I think the general disemination of knowledge must not be artificially restricted. In my opinion, the publisher does not only have a moral obligation to satisfy obvious market demands, but that not doing so is against the interests of both the original author of the book, as well as the - in this case - user community at large, who are factually excluded from a significant part of knowledge. The adverse effect on the author is easy to see: His name will not be known as widely as it could be, and his book sales will hit an upper bound rather sooner than later, thus directly limiting his potential revenue. For the users, the adverse effect is also obvious: Being cut off a knowledge pool requires more investment into one's own research, thus driving up cost for the topic covered in the book. And for the supplier side (where I am located), this also creates a problem, as it impedes user adoption and thus contributes to limiting the market share.

I therefore ask authors to please double-check your contracts, or the contracts proposed to you, to either force the publisher to supply translations upon request and in a timely manner, or to grant reasonable licenses for third parties to create and publish such translations, or to exclude translations from coverage, so you are free to contract someone else to create such a translation if you deem them to be useful, and in the event that publishers demand complete control over your work, that you go with a different publisher who does not require you to sign such an adhesion contract.

Thank you!

Back to top

Trackers - a Rough Overview

I've been asked to compare various issue trackers. While I don't really feel qualified do to so, I have an opinion nonetheless. So here are my two cents about it:

  • There are trackers for various use cases, various technologies, and licenses (eg. Jira is imho mostly commercial software).

  • I've not yet found a package which is equally suitable for handling customer (self-?) support tasks outside of software development, and software development tasks.

  • I don't have real experience with Jira, and only a very cursory impression about eg. OTRS (Perl) and Mantis (PHP).

  • From all trackers I have seen so far, OTRS, RT (Perl) and roundup (Python) are basically suitable to customer support tasks, but less suitable to software development tasks.

  • OTOH, Trac and Redmine seem to support software development tasks much better (and Redmine, written with RoR, much better than Trac, written in Python, imho).

For me, so far only Roundup and RT mattered for the customer-support space, but I intend to take a look at OTRS, now that they claim to support ITIL-conformant processes (whatever that means, but it's a requirement of some potential customers). When I talk about RT, I mean RT 3.x, not RT 4.x. I also ignore all PHP stuff for principal reasons.

  • Roundup's advantage, compared to RT, is that it is very lightweight.

  • Roundup's permission system seems to be more flexible than RT's, but all-in-all, changing anything requires rolling out a new revision of the installation (eg. to include the new permissions). This stuff is highly intertwined with the rest of roundup, and I've yet to see (didn't try) how to eg. migrate the database from one version of the software to the next.

  • RT's advantage is the much larger functionality out of the box, and esp. support for distributed workflows, with auto-escalation, re-assignment, hierarchical tickets with dependencies, statistics, multiple external authentication sources and what-not. It's much more heavy-weight, though, and the UI is clumsier, too. RT can be scripted, and the scripts seem to end up in the database, making it comparatively easy to migrate an instance. It's Perl, though, and the main author(s) are afaik on the forefront of Perl development themselves, so you frequently find that you have to pull in brand-new versions of modules from CPAN that you've never heard of, and that have had little exposure.

  • OOTB, RT's permission system is much more powerful than what is distributed with Roundup, though.

  • Roundup seems to be much more geared towards a "one customer project, one tracker" situation, where eg. general access control is of not very high importance.

In the software development space, integrating a tracker, a wiki, and a repository browser was popularized probably by SourceForge, and has led to the creation of packages like Trac and Redmine, the latter allegedly being a clone of Trac (imho it isn't, if you run the two side-by-side).

  • Roundup has no integration with either a wiki or a repository browser out of the box, so one would have to do manual work to use it in that manner. One also has to find suitable wiki and repository browser software to integrate with, first, and except for the wiki (MoinMoin), there are imho no obvious candidates.

  • Of the remaining two, Redmine imho has much better support for multi-project scenarios, seems to support a broader range of databases, and also provides much more functionality.

  • It can also be much easier extended by Joe Average User because of a plethora of plugins, supporting popular use cases.

  • Redmine appears to be easier to host than Roundup, using thin.


Back to top

ZopeProfiler on Plone4

As per the author's statement, using ZopeProfiler together with Plone4 is unsupported. It really is. First, get a current version of ZopeProfiler instead. Implement in your buildout as usual and run buildout. In the relevant instance's (eg. secondary) zope.conf, one has to enable it, too:

enable-product-installation on

You also need to fix the output from the pstats module. In Debian, this is located at /usr/lib/python2.6/ Copy to your virtualenv's lib/python2.6 and manually apply the patch mentioned here:

After that, following the instructions generally works, except for that the site now runs orders of magnitudes slower, and (at least) I get this error when trying to view the stats (sample traceback):

2011-05-04 13:47:56 ERROR Zope.SiteErrorLog 1304509676.940.218731970327 http://localhost:9082/Control_Panel/ZopeProfiler/showHigh
Traceback (innermost last):
  Module ZPublisher.Publish, line 127, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 47, in call_object
  Module Shared.DC.Scripts.Bindings, line 324, in __call__
  Module Shared.DC.Scripts.Bindings, line 361, in _bindAndExec
  Module App.special_dtml, line 185, in _exec
  Module DocumentTemplate.DT_Let, line 76, in render
  Module DocumentTemplate.DT_Util, line 202, in eval
   - __traceback_info__: stdnameRe
  Module <string>, line 1, in <module>
  Module Products.ZopeProfiler.ZopeProfiler, line 237, in getStatistics
  Module pstats, line 353, in print_stats
ValueError: I/O operation on closed file

I've seen the latter error on various other occasions as well, esp. when a long time has passed between the original activity and the display of results (eg. when running ExternalMethods). If someone has a fix for that, I'd highly appreciate it!

Back to top

Python BarCamp 2011

Yesterday, I went to the Python BarCamp. In the process, I discovered the collaboration tool etherpad, which nicely complements PasteBins (eg.,, or The session protocls have their own etherpad page.

The disscussions covered a broad range of subjects, including how to interface with modules written in C, practical hosting questions, several talks on testing, the small high-performance web server Tornado, and the latest developments in Django, now in version 1.3. Regarding Django, the speaker highlighted a number of new features which were being implemented by using mixin classes. Although some quantitative analysis would be required to really assess this development, I had some strong repercussions about the Zope2 development that eventually caused the initially painful, but highly liberating, Zope3 development.

For everyone interested, the event continues to this evening, so hurry if you haven't been there yet. You should already be in or near Cologne, though, due to the limited time remaining.

Back to top