Biking to Work

Finally made it up to biking to work 3 times this week! Had only been averaging about once every 2 weeks for the past couple months. Sam & I recently moved to North Portland which is flat. We had been living in the very hilly Southwest area of town, and biking to work from there was killer.

I really didn’t realize how much my situation had improved until my friend, Aaron Colflesh, pointed me to HeyWhatsThat.com which generates elevation change profiles for you based on coordinates:

My current route from home to work:
current route to work

It has a good 100′ hill in it. Not fun on the way home, but it doesn’t last too long.

Now compare that to my old route from home to work:
old route to work

No wonder I never did it more than once a week! It was brutal coming home.

We’re much happier in North Portland in general, but finding these diagrams made me feel much better about struggling to get on bike at the old place. :-)

Posted in Personal | Tagged , , | 1 Comment

jQuery Plug-ins for Checkboxes and Disabling Inputs

Here are 3 helper jQuery functions from my ever-mutating util.js file.

jQuery.check(); – Checks or unchecks a checkbox input field based on the boolean you pass it. Very simple, but a handy shortcut. Does not trigger any events like click or change by design.

jQuery.enable()/jQuery.disable() – Does 3 things:

  1. Adds or removes the “disabled” class on all matched elements.
  2. Sets the disabled HTML DOM property on elements which support it (input and select).
  3. Adds or removes the “disabled” class for any labels whose for attribute matches the ID of an affected input.

That last little side effect is what makes these 2 helper functions so handy. I like to subtly theme label.disabled to indicate when a field is disabled.

(function(){
	jQuery.fn.extend({
		check: function(on) { return this.each(function() {
			this.checked = true ? on !== false : false;
		});},
		enable: function() {
			this.removeClass('disabled');
			return this.each(function() {
				if (this.disabled !== undefined) {
					// Only disable elements that support it
					this.disabled = false;
 
					// Affect labels as well
					$("label[for="+this.id+"]").removeClass("disabled");
				}
			});
		},
		disable: function() {
			this.addClass('disabled');
			return this.each(function() {
				if (this.disabled !== undefined) {
					// Only disable elements that support it
					this.disabled = true;
 
					// Affect labels as well
					$("label[for="+this.id+"]").addClass("disabled");
				}
			});
		}
	});
})();

Would love to hear feedback.

Posted in Open Source, Technology | 2 Comments

Good-bye Lo-Fi Art, Hello YouGov

Next week I’ll be leaving Lo-Fi Art to start working for YouGov Polimetrix (aka PMX). For the past couple of years I’ve been consulting with Chris Pitzer mostly as a Python web developer specializing in Django. It will be sad to stop working for a company I own with a friend, but I’ve been working part time for PMX and am excited to work for them full time.

There are many reasons for my decision, but I should make it clear that it has nothing to do with Chris! It has been great working with him, and I’m glad we get to continue to share office space even if we’re working on different things. There is plenty of client work stacking up for him to do as well, so I’m not bailing on a sinking ship.

So why am I leaving Lo-Fi Art?

The biggest reason is probably stress. I’ve just stopped enjoying client work because if I’m not stressed about getting the current client done on time, I’m stressed about finding the next client. If its not one of those two things, I’m probably stressed about when the next check is coming in. How much was it for again? Wait, did I already get that one? Argh! On top of that I’m terrible at managing money. While Chris does a great job with the company books, that doesn’t keep me from screwing up my own (don’t even ask me about how my tax return went this year).

On top of that, contracting gigs just have a lot of overhead. For me overhead is anything that keeps me from writing code. I really don’t enjoy writing proposals and meeting with clients to discuss (or often: haggle over) implementation details. Its not that I don’t like people. I love people! But I like working with a team more than a client.

Some people really thrive in the consulting world. I think its just taken me years to realize I’m not one of those people. I could see returning to consulting someday, but I can’t imagine it would ever be back to the 2-4 week projects I currently spend most of my time on.

Why am I joining YouGov Polimetrix?

I’ve been a consultant for PMX working on the BrandIndex project for over a year now, and it was getting to the point where I needed to either commit or focus purely on Lo-Fi work. It was a really hard decision, but in the end PMX just gives me the opportunity to do what I love. I work in a fantastic team* with lots of fun technology in an organization that places high value on their IT resources. What more could I ask for? Oh yeah, a steady paycheck. That was a plus too. ;-)

* Some of the dev team at PMX: Jamie Turner (@jamwt), Christian Wyglendowski (@dowskimania), Eric Larson (@ionrock), and Robert Brewer (fumanchu on irc.oftc.net).

Posted in Personal | Tagged , , , | 1 Comment

I Love Python: ZipFile Edition

For a client web project I needed to create a zip file containing a number of generated XML files. This isn’t something I need to do very often, so I briefly considered just writing the XML files to disk and running a zip command. Ugly, but surely trying to dig up a pleasant Python zip library would be more work?

Turns out Python has had a wonderful zip library in its standard library since 1.6! The zipfile module makes creating zip files a breeze:

import os
from zipfile import ZipFile, ZIP_DEFLATED
 
from django.template.defaultfilters import slugify
 
from somewhere_else import render_spam_xml, render_egg_xml
 
ZIP_PATH = "/some/system/path/for/zips"
 
def create_zip(spam):
    spam_slug = slugify(spam.name)
    filename = "%s.zip" % spam_slug
    abspath = os.path.join(ZIP_PATH, filename)
 
    # Create zip
    z = ZipFile(abspath, "w", ZIP_DEFLATED)
 
    # Write spam xml directly to zip
    z.writestr("%s.xml" % spam_slug, render_spam_xml(spam))
 
    # Write xml files to zip
    for egg in spam.egg_set.all():
        egg_slug = slugify(egg.name)
 
        # Renders the egg object to an xml string
        xml = render_egg_xml(egg)
 
        # Note how easy it is to specify paths in the zip file:
        z.writestr("eggs/%s.xml" % egg_slug, xml)
 
    # Zip file must be closed to be valid
    z.close()
    return abspath

(Sorry for the Django bits in there, but they should be easy to replace.)

My favorite part is that you can use either the ZipFile.write method to add files to the zip or the ZipFile.writestr method to write bytes (strings in my case) directly to the zip file.

At any rate, just wanted to blog about it, so when I need to do it again in a few years I don’t do something stupid like running the zip command.

Posted in Open Source, Python, Technology | Tagged , | 2 Comments

Web Server Shootout Slides

The presentation has been given.

The slides are available as HTML or the source OpenOffice.org Impress file.

Thanks to everyone who attended, and thanks to the Open Source Bridge organizers for putting on an excellent conference!


I have a bzr repository full of my log files I’m considering uploading. Unfortunately the meanings of the log files are mostly in my head, so I think I should clean them up before unleashing them on the world. Ping me by tweet or e-mail.

Posted in Open Source, Personal, Technology | Tagged , | Leave a comment

My Gnome 3.0: A Real Web Desktop

So I missed the stream of What I Want for Christmas Gnome 3.0 by … a while, but better late than never!*

The Win

Essentially what I want for Gnome 3.0 is what Tomboy just got: a web interface called Snowy. Part synchronization, part collaboration, all “cloud” for those buzzword minded among us.

The Fail

Luckily there’s already Conduit which I think does the synchronization bit… I say “I think” because I’ve never actually gotten Conduit to work. I drag & drop F-Spot onto the canvas**, neat. I drag & drop Network to the right of F-Spot, neat. Now what? There’s no configure option for Network. Heck, there’s not even a Remove*** for Network. I right click and select Synchronize in hopes it will prompt me for details, but instead it happily reports synchronization is finished. Huh?!

I poke around in Preferences hoping for guidance on how to sync to another computer over a network. Wow. The first tab is fine, but the other 2 tabs are just long lists of text. Wait a second, if you scroll horizontally to the right in the Data Providers tab you can see a checkbox to load/unload them! Why you’d want this option other than for development, I’m not sure, but its there if you know where to look.

At this point Conduit has failed to gain my trust, so I give up. I’m fine with Pidgin being crash happy or Eclipse being ridiculously complex to configure. The former isn’t mission critical and the latter is intended for developers.

However, I’m expected to entrust all of my files to Conduit. Files and account information for network resources if I could figure out how to get that to work. I have pretty high expectations for anything I’m entrusting my files and passwords too. Right now Conduit seems more like a demo of GTK+’s canvas drawing abilities (it is pretty looking) than a powerful synchronization tool.

The Dream

My expectations for web enabling Gnome are insanely high. Synchronization isn’t enough (although it’d be an excellent start). I need web enabled collaboration features as well. I need it to Just Work™ as well as be Secure By Default™.

This means:

  • All applications can synchronize their settings and data.
  • All data has some sort of web viewable format and ideally a way to interact with it on the web as well.
  • By default all settings and data should be private.
  • Fine-grained CRUD permissions for all settings and data. The Create and Update are key here: not only should I be able to give other users the ability to edit my files but Grandma should be able to upload photos to my photo album.
  • While I’m dreaming can I add versioning support (like Dropbox)? Cool, thanks. ;-)

The Implementation

Unfortunately I think Conduit is the wrong way to go. The concept is sound, but Worse Is Better™: each application needs to be allowed to implement their own integration with the cloud synchronization and collaboration system. There’s too many application specific tasks to accomplish intuitive synchronization and collaboration features outside the main application.

Tomboy has had pretty good synchronization for a while now. Firefox is getting it with Weave.

In a way F-Spot and Banshee support 1-way synchronization and collaboration. F-Spot can upload photos to a variety of services which have all (or at least most) of the features I’m pining for. Banshee’s ability to download Podcasts and music synchronize to iPods (note: I’ve never used that feature) is a sort of primordial synchronization. If only Banshee Web had survived (and wasn’t written in ASP.NET, the ickiest of all webdev platforms). Abiword has been toying with cloud services for a little while as well.

Perhaps Evolution is the poster child for this: I currently use it as a Gmail and Gcal interface sometimes because there are certain use cases for which I prefer it (shocking I know!). Despite its past reputation for being bloated and buggy, it Just Works&tm; these days and integrates beautifully with the rest of the Gnome desktop (are those calendar events in my system tray calendar?! amazing! Pidgin integration?! <3 Evolution). Evolution lives completely in the cloud and synchronizes everything locally beautifully (after years and years of effort).

Why Gnome Can Do It

Gimp is actually the first Gnome app to really make me realize working on the web can and should be as easy as working locally. All it did was utilize Gnome’s VFS to edit and save images via FTP or SSH. With Gnome’s screenshot tool, I can save a screenshot to a web accessible location in 1 keypress and 2 clicks. Amazing! Thats almost as fast and easy as using a pastebin tool on the command line for sharing text.

Snowy seems like an excellent poster child for the web interface I’m whining about. I haven’t used it yet, but the very idea that Tomboy already has an open source reference implementation is an excellent start. 3rd parties could implement the protocols and offer competing services.

In an ideal world this would create a revenue stream for open source applications: services like Dropbox could support the synchronization and collaboration protocols and in return support development of the projects. The more people who use apps that integrate seamlessly with Dropbox, the more people who pay for Dropbox… or box.net or Amazon or… you get the idea.

FreeDesktop.org Does What?!

That’s right, FreeDesktop.org needs to lead the charge here. Its not enough that the protocols are open, application developers need libraries to make synchronization and collaboration easy. In that way Conduit is right: each application should not completely reinvent the wheel.

FreeDesktop.org needs to follow Mozilla’s lead. Mozilla realized early on that in order for their browser business to succeed, they needed open standards to succeed. FreeDesktop.org needs to do the same. A KDE application should be able to synchronize to the same service as a Gnome app (this is where Conduit’s monolithic-master-synchronization-app model seems too optimistic to succeed). OSX and Windows apps should be able to use the base synchronization libraries as well, even if they don’t use GTK+ or QT.

At the end of the day I should be able to sync my photos, documents, and mp3s between my laptop, desktop, cell phone, Kindle, etc as well as any relevant application settings (Tomboy for Kindle?! yes please!). …and so much more.

* Not always true. For example: posting opinions on a piece of software long after the roadmap has been made.
** Strike 1 against Conduit: “Canvas” isn’t a very end user friendly term IMHO. A minor complaint, but as confusing as the UI already is, it needs all the help it can get. Perhaps the problem isn’t the name “Canvas” but rather that the fact that it doesn’t even need to be said. Remove all references to it and just put a textbox that says “Drop data providers here.” when the canvas is empty. The “Clear canvas” option can just be “Clear” as there’s really only 1 thing that can be cleared.
*** Strike 1.5: “Remove” would be better than “Delete”. Delete makes me wonder if its going to erase my files! Remove seems more descriptive and precise. Also, drop “item” from the end of each right click menu option. Its redundant when every option operates on the item you clicked.

Posted in GNU/Linux, Open Source, Technology | Tagged , | Leave a comment