Quiet Mac App grants blessed silence

May 6th, 2011 No comments

Us over at WireLoad have released a new Mac app. It is called Quiet and it’s a focus app.

Quiet has already become indispensable in my own work day because of what I think is its most handy feature: it marks me as busy in Skype and Adium and hides the otherwise ever distracting Growl messages I get. New email, new chat messages, new tweets. I don’t know about everyone else, but to me these things are incredibly distracting when I’m trying to crack a difficult programming or design problem.

Sure, I could quit all the communication apps. But then I miss out on stuff I might need to respond to. With Quiet, I can easily work for a while, then take a break and check the communication apps, and then immediately dive back into another work session. If I’m feeling antsy a work session might just be 10 minutes. If I really have to get into it I’ll stay in Quiet mode for an hour at a time (after which some people are guaranteed to be screaming for attention when I finally come out, but they’ll deal with it!).

Learn more about Quiet on its homepage.

Categories: Mac OS X Tags: ,

Diary app Chronicle.im peeks out.

July 17th, 2010 No comments

Our latest project, Chronicle.im, which we’ve been working on secretly for about nine months now, now has a teaser preview up online at www.chronicle.im. In the next few weeks we hope to start opening up for beta testing of this online journal writer, so if you want in now is the last chance to sign up. Just enter your email address on that page. I guarantee we wouldn’t mind if you sent us a tweet or two regarding the site too!

Categories: News, Programming Tags:

Find git commits which still need to be merged

May 29th, 2010 No comments

If you have a git branch which you are working on which is a clone from an upstream ‘official’ branch, and you sometimes submit your commits to be integrated upstream, there’ll surely be times when your patches are not accepted or fall between the cracks. After a while it can get a little hairy to figure out which commits are unique to your branch and which ones are incorporated in the main repo.

The ‘git cherry’ command can help with this. It lists all commits in one branch which are not in another. It works like this simply:

git cherry -v upstream my_branch

The man page describes the command succinctly:

Every commit that doesn’t exist in the <upstream> branch has its id (sha1) reported, prefixed by a symbol. The ones that have equivalent change already in the <upstream> branch are prefixed with a minus (-) sign, and those that only exist in the <head> branch are prefixed with a plus (+) symbol.
The problem is that sometimes the cherry command does not identify ‘equivalent changes’. I’m not sure why, but perhaps this happens when the main tree has cherry picked commits and made changes to whitespace or resolved merge conflicts. Or maybe it doesn’t work well at all with cherry pick. Either way, I had a list of changes which cherry returned which I knew had in fact been merged. So I whipped up up this silly little Python script to filter a cherry results list from a complete log of the upstream repo and to remove all commits with the same commit message. This is obviously not bullet proof as different commits may have the same message. But it was good enough for me in this case. So without further ado, here it is:
import sys

cherry = open(sys.argv[1], "r")
filtr = open(sys.argv[2], "r")
lines = filtr.readlines()
unmatched = []

for line in cherry.readlines():
  plus, sha, message = line.split(" ", 2)
  for existing in lines:
    esha,emessage = existing.split(" ", 1)
    if message == emessage:
      break
  else:
    unmatched.append((sha, message))

for sha, message in unmatched:
  print "+ %s %s" % (sha, message)

Usage:

$ git checkout upstream
$ git log --oneline >all_commits.txt
$ git cherry -v upstream my_branch >cherry_commits.txt
$ python filter_cherry.py cherry_commits.txt all_commits.txt 

Categories: Programming Tags: ,

Good Django Celery Overview

October 14th, 2009 No comments

Happy stream of thoughts has a good overview over how RabbitMQ, Celery and Django work together to make distributed task processing easy and convenient in Django. The example described is for video processing.

RabbitMQ, Celery and Django

Categories: Programming Tags: , ,

Cool politics tool (for Americans)

October 11th, 2009 No comments

While I think avoidance is the best way to deal with US politics, what with all their internal spying and lack of constitutional backbone, here is a glimmer of light for those of you still hoping for improvement. The Truth-o-meter, a tool showing how well political promises are being kept. Wish we had a site like that in Sweden too (and then some tool to make the foolish masses actually care).

Categories: Site Tags:

Slashdot Slashdotted? Google Expunges Pirate Bay From Search Results story broken

October 3rd, 2009 No comments

Something weird happened to me this morning. I saw this article in my RSS feed:

Slashdot Story | Google Expunges Pirate Bay From Search Results

Barence writes “According to PC Pro, Google has removed all search result links to The Pirate Bay, the notorious file-sharing site. The move is a reaction to a takedown notice issued under the United States Digital Millennium Copyright Act (DMCA), although it’s unclear who filed the complaint. The ban isn’t particularly effective: The top result is now The Pirate Bay’s Wikipedia entry, which provides a prominent link to the site’s homepage. It’s also possible to search The Pirate Bay itself using Google’s site search.”

But when I tried to go read it I got the following error message:

The item you’re trying to view either does not exist, or is not viewable to you.

Weird. There’s not even a Google cache for it. I hope the article comes back alive later.

Update 1: Some people over at Slashdot noticed too and provided a link to an updated version of the real story on Cnet. Looks like Google reacted incorrectly to a DMCA takedown request, and Google has since added The Pirate Bay back in to their index.

The prompt reindexing may have been helped by a letter sent by Peter Sunde:

Peter Sunde-Kolmisoppi told Swedish newspaper Svenska Dagblated that The Pirate Bay’s attorney sent a letter to both Google and the companies that are suspected of being behind the allegations and demanded that the Pirate Bay be returned to Google’s index. The Pirate Bay accused Google of censoring a competitor and of stifling free expression, the paper reported.

The whole thing is a little curious when you think about it since Google lists plenty of torrent files without actually hosting any content, just like The Pirate Bay. It would have been a funny case of the pot calling the kettle black hadn’t it just been a mistake.

Categories: News Tags: , ,

Migrate Eventum to Redmine.

August 27th, 2009 No comments

I have migrated more stuff to the new Redmine setup. This time I pulled all issue data from an old and well used Eventum setup. I made some educated guesses about how the Eventum data was laid out and then hacked up the Redmine trac migration script until it worked for Eventum.

It’s really not a very pretty script but since I won’t be doing any more work on it I’ll release it here in the spirit of open source. Whether it works for you or not is anyone’s guess, but one thing is for sure: if it was just sitting on my hard drive it definitely would not.

Download: migrate_from_eventum.rake

See instructions in the beginning of the file.

Categories: Programming Tags: , , ,

A trick for Safari 4.0.3 table with border-radius and row background color leak.

August 22nd, 2009 No comments

While working on EmailServiceGuide I have been using the new border-radius property to get rounded corners without a ton of extra markup and images. It won’t work in Internet Explorer, but the idea is that people who run Internet Explorer are probably not that concerned about visuals anyhow.

Unfortunately the border-radius stuff is in development right now, so it doesn’t always work the way you expect it to. In particular I have this table with rounded corners and zebra pattern on the rows. In Safari the background color of the rows breaks through the rounded border of the table, sticking out sharply and concealing part of the table border. Neither overflow:hidden nor background-clip: border help.

What does help is to follow these instructions and make sure that the inner element with a background-color has a matching rounded border.

The sad thing with that is that in the table case you then have to use CSS to select and round off the top left, top right, bottom left and bottom right th or td elements which adds a lot of silly markup.

Here’s a little trick to cut down on that extra markup: make the zebra color on odd rows. Now the 0 row will have the table’s background color – which does get properly clipped to the table borders – and you know that the only possible place there could be trouble is if if the last row happens to be odd. So you can apply the rounded borders to the corner elements of the last row only and don’t have to do the first row!

Saves you several lines of CSS. : )

Categories: Site Tags:

Refactor Serializable Java Class

August 20th, 2009 4 comments

Today I renamed and moved a class in a Java program. It was a Serializable class containing some preferences. As we are getting rid of it I renamed it from Preferences to LegacyPreferences, with the intention of starting a new Preferences class using a regular config file instead of serialization. Bad idea. Java refused to load serialized data into the new class for two reasons: one obvious and expected and one seriously braindamaged in true Java fashion.

The first problem was that the deserialization class could no longer find the class to deserialize to. No wonder since it was in a new package and had a new name. No problem. I subclassed ObjectInputStream and overrode resolveClass(ObjectStreamClass desc) to properly load the class from its new name and location.

That’s when Java freaked out with the following piece of brilliance:

local class name incompatible with stream class name X

Well, duh. Of course the name is different, that’s the point of a refactoring. What exactly were they trying to accomplish when they added this name check? The class has already been found, its interface is an exact match. The name of the class is irrelevant at this point.

I proceeded by overriding readClassDescriptor() with the intention to simply replace the name of the class with the new name when reading the stream. Java would never even realize the class used to have another name. But no: that method must return a java.io.ObjectStreamClass object, which you can’t instantiate or override unless you’re in the java.io package. And if you just grab the super.readClassDescriptor() instance you aren’t allowed to make any changes to it.

At this point I considered my favorite solution to Java damage. I’d like to call it “corrective Java surgery” – use reflection to force your way into the class and fix it. This is a very gratifying solution since you can undo the mistakes in Java and set things truly right. The drawback of course is that different versions of Java may require different corrective code.

That wasn’t necessary in this case since reading the source code of ObjectInputStream revealed a static method for creating ObjectStreamClasses: ObjectStreamClass.lookup. With that tool things fell into place very simply like so:

@Override
protected java.io.ObjectStreamClass readClassDescriptor() throws IOException ,ClassNotFoundException {
	ObjectStreamClass desc = super.readClassDescriptor();
	if (desc.getName().equals("com.trueship.base.Preferences")) {
		return ObjectStreamClass.lookup(LegacyPreferences.class);
	}
	return desc;
};

Hope that’ll help anyone else looking to rename and deserialize classes in Java.

Categories: Programming Tags:

SQLAlchemy 0.5.3 and 0.5.5 error: Set changed size during iteration

August 3rd, 2009 2 comments

Update 1: See Mike Bayer’s comment below – looks like there’s a fix for this coming up in 0.5.6. Very responsive work by Mr. Bayer. Thanks!

YippieMove has been running into some spurious problems with SQLAlchemy. When upgrading Python from 2.5 to 2.6 the errors became a lot more frequent. The error is “Set changed size during iteration” and happens in all kinds of random code paths when using the ORM layer. Today I saw it happen when getting a result object from a query by index, and then again when iterating over the result of another query.

The end of the traceback looks something like this:


  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/orm/dynamic.py", line 192, in __iter__
    sess = self.__session()
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/orm/dynamic.py", line 181, in __session
    sess.flush()
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/orm/session.py", line 1354, in flush
    self._flush(objects)
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/orm/session.py", line 1359, in _flush
    if (not self.identity_map.check_modified() and
  File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/SQLAlchemy-0.5.5-py2.6.egg/sqlalchemy/orm/identity.py", line 56, in check_modified
    for state in self._mutable_attrs:
RuntimeError: Set changed size during iteration

The code in question looks like this:


    for state in self._mutable_attrs:
        if state.modified:
            return True

The program is single threaded and it sure didn’t look like “state.modified” would cause the iterated over set to change. Weird. After snooping around for a while I found this post which suggests an async GC being the problem.

Sure enough the problem appears to have gone away when automatic GC is disabled. It’s not a nice workaround because the garbage collector in Python collects cyclic garbage. But it did solve the problem for now so here it is if anyone else needs it:

import gc
gc.disable()

Unless you want to be buried in garbage, make sure to collect it once in a while in a safe spot in your code using gc.collect().

Hopefully this will be fixed in a future version.

Categories: Programming Tags: ,