MacVim Quicktip: Tab switching with Command-[0-9]

Up until now, I've been wondering how to bind Command hotkeys in MacVim. The answer is <D-foo>.

So, because I simply love Cmd-[0-9] and Cmd-Shift-Right/Left in my Terminal and browser, here's how to bind these in MacVim:

noremap <D-1> 1gt
noremap <D-2> 2gt
noremap <D-3> 3gt
noremap <D-4> 4gt
noremap <D-5> 5gt
noremap <D-6> 6gt
noremap <D-7> 7gt
noremap <D-8> 8gt
noremap <D-9> 9gt
noremap <D-9> 10gt
noremap <D-S-right> gt
noremap <D-S-left> gT

simples3 1.0-alpha

In keeping with my new year's resolution to release one-dot-ohs of my two mature projects, I now give you the 1.0 alpha release of simples3.

In case you missed it, simples3 is a simple S3 interface that has no dependencies other than Python, and has a daughter project named gaes3, which makes it work on Google App Engine (although some people have noted that simples3 should work on its own just fine.)

Without further ado:

simples3 1.0-alpha


Return Statements and Parentheses

This was originally posted on my old blog on the 24th of February, 2008

I've been trying to come up with an argument as to why you shouldn't be using parentheses around your return statements in Python for a few minutes, and I got it. Consider:

>>> def myfunc():
...     return(1)
... 
>>> myfunc()
1

Above is the classic example of people treating the return statement as a function. This could go bad, consider:

>>> def myfunc():
...     return()
... 
>>> myfunc()
()

An empty parenthesis pair is the literal for empty tuples in Python, which I find is a good reason, beyond aesthetics.


GAE and simples3

One of the projects I work on, aptly named simples3, doesn't work on Google's App Engine architecture.

This is, or rather used to be, somewhat of a problem for me, as I'm a heavy-duty S3 user and also one of those guys who just want to avoid this whole issue of deployment altogether. Then for obvious reasons, Google App Engine (GAE henceforth) has been very interesting to me.

However, since Google decided that Python's standard library URL fetching mechanisms were insecure for their purposes, they designed their own one. What this further means is that anything that uses urllib2, urllib or httplib will need to be rewritten.

The above is why I wrote the piece of code I want you to know about, which is also fairly aptly named gaes3. What it does is sit on top of simples3, and overrides certain methods so that the simples3 code actually uses Google's URL fetching APIs.

Check it out at
gaes3 on GitHub, or opt for the easy way and go easy_install gaes3.


SSH agent forwarding and GNU screen

I'm an avid user of both gateway-based SSH and GNU screen.

By gateway-based SSH, I mean first SSHing to one machine and then from there getting access to the machine I was looking for, as a security measure or just because the machine in question has no external IP address.

This, up until now, has never worked for me when using OpenSSH's excellent agent forwarding.

Agent forwarding is what it sounds like - your SSH agent (the one that keeps your unlocked SSH keys in memory) gets forwarded to another machine. This is enabled with the -A option to OpenSSH.

Commonly, I'd get an issue like this:

laptop $ ssh -At gateway ssh -A svett
svett $ screen -r
svett $ svn up
Password:

I mean, who the hell uses passwords these days anyway? So, on to the solution. It's quite simple, actually.

OpenSSH's forwarding is pretty simple, and the reason it doesn't work in the above case is that the screen session was started with another SSH agent tunnel, which is now dead. How do we fix it? Simple. Just fix your environment.

laptop $ ssh -At gateway ssh -A svett
svett $ echo $SSH_AUTH_SOCK
/tmp/ssh-abcdef/agent.1234
svett $ screen -r
svett $ export SSH_AUTH_SOCK=/tmp/ssh-abcdef/agent.1234
svett $ svn up
At revision 1234.

And that's all there is to it. You could even set up aliases for this if you do it often enough, but then again then you'll be dependent on that alias on every machine you use, so...


Debugging Django: Using Flickzeug

It came to my attention that some people haven't realized you can use the excellent Pocoo creation known as Flickzeug with a Django project.

Flickzeug lets you find memory leaks, generate profiling data, look at that same data and is pretty awesome in general.

Step one is to make a new manage.py. Obviously, you won't be able to use that same name in a Django project, as Django already uses it. Choose on of your liking. I myself don't use Django's manage.py and so replace it.

from werkzeug import script

if __name__ == "__main__":
    script.run()

The above is a bare-bones skeleton of making your own management script using the Werkzeug helper system.

At this point, you'll need to run a Django project as a mere mortal WSGI application. Fortunately, this is relatively simple.

from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

application = WSGIHandler()

if __name__ == "__main__":
    script.run()

An issue with this, however, is that Django requires you to set up your environment before importing anything non-trivial from within Django. This is one of the... "design choices" that convinced me of the backwardness of Django, but I digress.

So, to take this into account, we have to set the Django settings module environment variable first, and also make sure our project is importable.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

if __name__ == "__main__":
    script.run()

There, now that we have our application, we can make a simple Werkzeug runserver — which, by the way, is much more light-weight and nicer to work with than Django's.

To do this, we define a variable called action_runserver, as Werkzeug's script module looks for action_* variable names.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

action_runserver = script.make_runserver(lambda: application,
    use_reloader=True, use_debugger=True)

if __name__ == "__main__":
    script.run()

There, we've got our first management command. Try it out! python new-manage.py runserver should do the trick. Pass -h for help.

On to the Flickzeug part then. Flickzeug works as a WSGI middleware, that is to say, you wrap a WSGI application in Flickzeug, and the application gains the functionality desired.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

def make_leakfinder():
    from flickzeug import LeakFinder
    filter = lambda v: (not v.startswith("foo.")
                    and not v.startswith("bar."))
    return LeakFinder(application, filter=filter)

action_runserver = script.make_runserver(lambda: application,
    use_reloader=True, use_debugger=True)
action_runserver_leakfinder = script.make_runserver(make_leakfinder,
    use_reloader=True, use_debugger=True)

if __name__ == "__main__":
    script.run()

So what we did was pass a different callable to make_runserver, which returns a Flickzeug-wrapped version of our application instead.

The Flickzeug LeakFinder optionally takes a filter argument, which I find very useful indeed to filter out the noise made by Django and any other third-party component you mightn't necessarily be interested in.

The same approach can be used for any other part of Flickzeug, or indeed any other WSGI middleware you might want to use.

Also, now that you have the skeleton for making a Werkzeug-based management script, you should probably look into the werkzeug.script module: http://werkzeug.pocoo.org/documentation/0.5.1/script.html


pylibmc 1.0 alpha release!

My project pylibmc, the memcached client C extension for Python, has now reached the milestones I set out for it to go 1.0. So I'm making a 1.0 alpha release, i.e. what others might call a release candidate.

What does this mean? Normally, it would for a library mean that the API is considered stable. But for a project that has as a primary objective to mimic an already-existing API, that stability guarantee has already been made.

However, what I want you to do is to test pylibmc out on as many platforms as you can, file as many bug reports as you can over at the GitHub issue tracker thing.

pylibmc 1.0-alpha over at PyPI

Oh, and happy 2010, folks.


RSS 2.0