A simple piece of advice: If you are throwing an exception (or logging an error) about a value being incorrect in some way, include the value itself. It will make it so much easier for the poor sap who has to figure out why the exception is happening.

I found myself in this situation, this code throwing an exception:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, ("Keys must be str()'s, not"
            "unicode.  Convert your unicode strings using "
            "mystring.encode(charset)!") 

There are a few things wrong with this message, the first being that the multi-line string concatenation is missing a space, so the message actually has the word "notunicode" in it. Why are we so sure the wrong value is Unicode in the first place? And of course, it should include the actual value:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %r" % key
        )

If you want to be paranoid, you can limit the amount of repr text that will appear in the message:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %.60r" % key
        )

If you are really paranoid, you're worried that getting the repr of your unknown object could itself throw an exception:

def safe_repr(o):
    try:
        return repr(o)
    except:
        return "??norepr?"

...

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %.60s" % safe_repr(key)
        )

or even:

def safe_repr(o):
    try:
        return repr(o)
    except Exception, e:
        return "??norepr (%s)?" % e

Good error handling is always a pain, but it's worth it when things start hitting the fan and you have to figure out what's going on.

Armin's post about Whitespace sensitivity in Ruby piqued my interest. It points out that in Ruby, foo[42] is different than foo [42] and that foo/bar is the same as foo / bar but different than foo /bar.

So I wanted to learn more about Ruby, and looked at a bunch of tutorials, finally ending up at Mitch Fincher's Ruby Tutorial with Code Samples, which had the right breezy pace with no, "a variable is like a box for your numbers" stuff in it.

But I had originally gotten to Mitch's page from a Google search for ruby puts gets. If you try it, you'll see that when you get to Mitch's page, a small box appears near the top, saying,

Welcome. You seem to have come here from a search engine. Your search words (ruby puts gets) are highlighted on this page for your reading pleasure.

I thought "nice," then I thought, "that looks familiar," then I realized it was almost exactly the box that appears at the top of my pages when you visit from a search engine (try it: batchelder white house adventure). In fact, it used the same colors. I looked at his page, and it used near-verbatim copies of my three Javascript files, though a few years ago I consolidated them into one.

I was amused, and wondered where else the code is being used. But the search engines are smart enough not to index comments in Javascript files, or names of Javascript files referenced in HTML pages, unless there's some tricky syntax I don't know about.

PS: about whitespace sensitivity: I've decided that phrase means a programming language needs tokens consisting of only whitespace in order to be parsed properly. Python and Ruby are whitespace-sensitive, and C is not, for example.

tagged: , » 3 reactions

My wife's book Making Peace with Autism is now available in Korean: 자폐아 가정의 좌충우돌 성장 이야기.

Making Peace with Autism in Korean

The publishing business is a strange place. The first we knew the book was being translated into Korean was when a box of the books was delivered to our doorstep. Apparently there was also an entry in the latest sales statement from the publisher, but those things are completely indecipherable, so we didn't notice.

The Korean culture also seems to value cute more than we Americans do: the book is full of cartoony decorations. I guess that chipper salaryman on the cover is me!

I'm a recent convert to virtualenv, it's a great way to maintain a number of different Python installations so that you can install packages for one project without it polluting the environment for all your projects.

I also work on Windows, which can be a pain. In particular, many interesting Python packages involve compiling extensions, which is not always easy, and especially not easy on Windows. So I'm glad when package authors provide pre-built binaries for Windows. These are typically delivered as .exe Windows installers.

Here's the problem: these installers know to look in the registry to find the Python installation. There are many things developers dislike about Windows, and the registry is often at the top of the list. One of the bad things about it is that it encourages a mindset of their being one of everything. Starting with the concept of "one registry", it seeps into the whole culture of Windows, invading even to Python, which cannot abide more than one installation of a major release.

So when running a Windows package installer, it will find the Python 2.6 installation in the registry, and that's the only option you've got for where the code is going to go. Your nice isolated virtualenvs are completely out of the picture.

I asked on Stack Overflow if there's a way to install Windows package installers into virtualenvs, and didn't get the answers I wanted.

So I decided the best approach was to change the registry, install my package, then change the registry back. I adapted a classic script to register Python installations, to create what I've called the_python.py:

# script to register Python 2.0 or later for use with win32all
# and other extensions that require Python registry settings
#
# Adapted by Ned Batchelder from a script
# written by Joakim Low for Secret Labs AB / PythonWare
#
# source:
http://www.pythonware.com/products/works/articles/regpy20.htm

import sys

from _winreg import *

# tweak as necessary
version = sys.version[:3]
installpath = sys.prefix

regpath = "SOFTWARE\\Python\\Pythoncore\\%s\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs\\" % (
    installpath, installpath, installpath
)

def RegisterPy():
    try:
        reg = OpenKey(HKEY_LOCAL_MACHINE, regpath)
    except EnvironmentError:
        try:
            reg = CreateKey(HKEY_LOCAL_MACHINE, regpath)
        except Exception, e:
            print "*** Unable to register: %s" % e
            return

    SetValue(reg, installkey, REG_SZ, installpath)
    SetValue(reg, pythonkey, REG_SZ, pythonpath)
    CloseKey(reg)
    print "--- Python %s at %s is now registered!" % (version, installpath)

if __name__ == "__main__":
    RegisterPy()

Use your desired Python to run this script, and it will be entered into the registry as the Python. When you run your Windows package installer, it will go into your virtualenv. Don't forget to run it again at the end to put things back the way they were.

Zach Anner is a funny guy, who happens to have cerebral palsy, as Zach puts it, "the sexiest of the palsies". He submitted a video to Oprah's Search for the next TV star:

He ended up with 2.5 million votes:

I really like Zach's humor because it doesn't avoid his disability, and it isn't just about his disability. It's about funny Zach and the funny world, and Zach's cerebral palsy is part of it, but just a part. He strikes just the right balance, and he's got a great attitude. Watch him train for the 2011 Austin marathon:

He has more stuff with Lark the Beard. I hope he goes far.

tagged: » 1 reaction

¶  RT @catherinedevlin: I am so moving to France. Castle under construction w/ 100% historical technology. http://tinyurl.com/3acrbve (Jul 02)

¶  Awesome and sweet.. RT @sgalineau: http://www.youtube.com/watch?v=-CVYOCMpJRY #classic #starwars (via @bcongdon) (Jun 28)

¶  Not often you get bitingly mean graphic design humor: RT @jackschofield: Missing cat poster story http://www.27bslash6.com/missy.html [Cat lovers beware] (Jun 25)

¶  Tons of recreational math stuff! Sadly, no RSS: http://www.mathpuzzle.com/ (Jun 20)

¶  The Omnificent English Dictionary In Limerick Form: http://www.oedilf.com. Really. (Jun 20)

¶  iPad + autism = win! http://www.blogher.com/ipad-nearmiracle-my-son-autism (Jun 18)

¶  About time we took a hard look at couch architecture: http://blog.buildllc.com/2010/04/couch-cushion-architecture-a-critical-analysis/ lol. (Jun 09)

¶  Pretty, in a geometry/typography kind of way: http://www.flickr.com/photos/quasimondo/4644498892/in/photostream/ See the paintings in the stream too. (Jun 05)

¶  RT @sgalineau: Once in a while Smashing Mag surprises: Arabic, East Asian and Indic calligraphy & writing systems http://www.smashingmagazine.com/2010/05/18/the-beauty-of-typography-writing-systems-and-calligraphy-of-the-world/ #i18n (May 29)

In the last year, people have been experimenting with 3D variations of the Mandelbrot fractal. The first to get a lot of attention was the Mandelbulb, but I didn't like it, it just looks blobby to me, with no apparent self-similarity.

Then in February, a new formula appeared, called Mandelbox. It's a clever two-step formula using folding, first with squares, then with circles. The combination provides a very rich generative source.

Being a 3D structure, you can fly through it:

There's an amazing variety of textures and structures here, reminiscent of many other fractals. Some of the vistas seem like science-fiction sets, but generated by a formula rather than drawn by hand. Fascinating.

Mandelbox is a rich world to explore, and it's really new, so we can expect to see lots more innovation and exploration.

tagged: , » react

It is said that English has about a quarter million words. So it surprises me when I can't find a word I want.

For example, we have a bunch of words that mean, "tastes good": delicious, scrumptious, delectable, appetizing, yummy, toothsome, and mouthwatering. So why is there no word that means just, "tastes bad"? We have disgusting, unpleasant, gross, and disagreeable, but none of those apply only to eating. Even the literal distasteful or unsavory are almost quaint when applied to food.

And if scary means "fills me with fear", as do terrifying, frightening, horrifying, and hair-raising, where is the word that means "fills me with anxiety"? Unnerving or nerve-racking seem to be the closest I can find, but even those seem closer to fear than to anxiety.

Time for some new words?

In a comment on my last post, drozzy wrote:

PS: Whenever I try to post a comment on your blog, my email always gets @ and . replaced by (at) and (dot) symbols, so that I have to retype it before clicking on "add it" button. This is a bug methinks. Fyi I am using chrome.

I tried it, and sure enough, Chrome would not let a comment be submitted.

Somewhere in the reptilian brain of my comment code, I was cloaking email addresses by changing "." to "(dot)" and "@" to "(at)". This meant that when previewing a comment, the valid email that you had entered now is not a valid email address.

This is fine, except in Chrome. A couple of months ago, I changed the comment form's field to use an HTML5 type="email" field. I figured it wouldn't hurt anything, and would give iPhone users a nicer email-specific keyboard to use.

But it turns out Chrome is being even more "helpful": it won't let a form submit if an email field has an invalid email address in it. And "ned(at)nedbatchelder(dot)com" is not a valid email address, no matter how obvious it is to us humans what is meant.

I couldn't remember why I wanted to cloak email addresses like that in the first place, since they aren't displayed on the site anyway, and even if they were, it should be output like that, not input like that. So I removed the cloaking, and Chrome is working again.

Playing with Chrome a bit, it seems that they're using the same ultra-liberal validation I recommended in Humane email validation: stuff, at, stuff, dot, stuff, where stuff can't have at-signs or spaces in it, although they don't trim the string first, so a leading or trailing space will prevent the form submission. I'm a bit surprised that they unilaterally perform this validation, since there's no UI to let the user know what's going on: the field is given focus, but there's no other indication as to why the form didn't work.

It seems browser incompatibilities are inevitable. This is a big difference between the way the browsers work. And one of the key theories of HTML5 email fields is that they don't break anything, just make it nicer. Mark Pilgrim closes his exhortation on HTML5 email fields with:

To sum up: there’s no downside to converting all your email address form fields to type="email" immediately. Virtually no one will even notice, except iPhone users, who probably won’t notice either. But the ones who do notice will smile quietly and thank you for making their web experience just a little easier.

Seems to me like someone noticed...

One more thing: I considered digging into the Chromium source to find the validation to see what the real rule was, and whether it could be disabled or controlled in some way, but the Chrome project uses all custom tools, and even just pulling the source from svn indicates the use of gclient, whatever that is. Too much trouble.

tagged: , » 5 reactions

A quote from Alain de Botton which spoke to me:

The real issue is not whether baking biscuits is meaningful, but the extent to which the activity can seem so after it has been continuously stretched and subdivided across five thousand lives and half a dozen different manufacturing sites. An endeavor endowed with meaning may appear meaningful only when it proceeds briskly in the hands of a restricted number of actors and therefore where particular workers can make an imaginative connection between what they have done with their working days and their impact upon others.

(found on a working library.)

tagged: » 2 reactions

I'm 30

Wednesday 16 June 2010

Today's my birthday, I'm now 30. Well, 0x30, that is, 48.

Aging, whether it be biological or psychological, seems to be about two things: accretion and flexibility. The older we get, the more we have: experiences, skills, opinions, debts, possessions, and on and on. Some are positive, and some are negative. The trick is to find ways to keep the good and shed the bad, to use your accumulated stuff to make you happier and more able.

Flexibility seems to be a big part of it. Some things you carry along with you help you react well to new situations: you have experience to draw on, you have people who can help you. Some can prevent you from adapting: old habits, strongly held beliefs that no longer hold. People have a natural tendency to try to replicate past successes, to cling to what has worked. You can try to stay inside your comfort zone, but it may keep you from finding new successes. Your comfort zone can shrink over time to box you into a very narrow set of choices.

So stay nimble, keep the good, junk the bad, learn new things, shift from your center.

Or maybe another year isn't to be taken too seriously:

tagged: » 7 reactions

I used to write many more short posts on this blog pointing to stuff I'd seen and liked on the web, in the spirit of the original weblogs. Now, those "go look at this" posts go onto Twitter instead. But I've missed having them here, so I'm going to occasionally pull some of my tweets into blog posts like this one.

My son Max helped by hacking together the code to grab the tweets and HTML-ify them, including un-shortening URLs where possible. He also helpfully pointed out that doing this sort of cross-posting would permanently mark me as a clueless dinosaur who didn't understand Twitter!

In any case, some of my recent tweets:

¶  curly-bracketeers vs. the indentationites vs. the parenthesesophiles: http://alarmingdevelopment.org/?p=422 (May 29)

¶  The next phase of telecommuting: http://anybots.com/ Fascinating. (May 19)

¶  How come there aren't cat cafes around here? http://seaofshoes.typepad.com/sea_of_shoes/2010/05/cat-cafes.html (May 08)

¶  Computer graphics incunabula: http://translab.burundi.sk/code/vzx/index.htm (Apr 22)

¶  RT @catherinedevlin: It's frankly impossible to imagine any security failure disrupting operations as much as our sec policies do every day. (Apr 06)

¶  Web dev's lament: http://www.youtube.com/watch?v=_DvEpWR66_8 (Apr 02)

¶  vim + soothing speaker = great! RT @tsmarsh: Great vim lessons, almost relaxing http://vimcasts.org/ (Mar 31)

¶  More stuff made purely with CSS: an entire typeface: http://desandro.com/resources/curtis-css-typeface/ (Mar 29)

¶  At last, I can properly categorize my social circles: http://matthewwmason.wordpress.com/2009/09/22/dweeb-dork-geek-or-nerd/ (Mar 27)

¶  RT @tsmarsh: This made my inner math geek very happy http://www.youtube.com/watch?v=kkGeOWYOFoA (Mar 23)

¶  Auto-generated editor themes. Why waste time picking colors when you can waste time watching code do it? http://inspiration.sweyla.com/code (Mar 23)

¶  The hazards of merely dabbling in social media: Chocolate Meltdown: http://www.ericfoster.org/?p=221 (Mar 19)

¶  Engaging tweet enticing you to watch this funny spoof of movie trailers: http://www.youtube.com/watch?v=nFicqklGuB0 (Mar 16)

¶  Nice alternative docs for jQuery: http://www.jqapi.com/ (Mar 09)

Older:

Even older...