Monday, December 25, 2006
Saturday, December 23, 2006
Draft 3
[reading: Tanya Huff, "Smoke and Mirrors"]
Finally got around to taking another pass over my scribblings on software engineering. It's been a fair while since I last looked at it—around eight months—which means I've now got enough distance to be able to spot (some of) my own typos.
I'm also finding that I rather like it as I re-read it, which is a slight surprise (almost no-one else that I've shown it to seems to have been able to wade through it, which augured badly). I've got a couple more small sections I'd like to add, but I think it's in fairly decent shape.
[A:40878 B:3278 C:346 D:9187 E:64522 Total:118211]
Time:
5:43 PM
0
comments
Tags:
hqse
Thursday, December 14, 2006
Scanned Scan
I've seen ultrasound scans before, and I could never quite understand the enthusiasm with which they were presented. They always seemed like a grainy collection of vague blobs to me, and so I thought the enthusiasm was just early-onset baby obsession.
Now that I've seen the scan in action, it makes a lot more sense. Any individual still image is grainy and vague, but as the 'camera' moves around you build up a 3D image in your head which is much more impressive. It's like being in a really dark room with a single lightbulb swinging far overhead, so that the shadows gradually converge into shapes. (Actually, that makes me think of Doom 3, which probably isn't the best association).
Time:
1:15 PM
1 comments
Tags:
sproglet
Wednesday, December 13, 2006
Django Su
It's always a sign of good design when adding a new feature turns out to be easy.
In the
Django
authentication system, I
wanted a way for an administrator to view the site as if they were
a particular user; effectively an equivalent to
su in UNIX-land.
The first easy step was to invent a URL to correspond to this action, which gets
encoded in
urls.py:
(r'^su/(?P<username>.*)/$', 'qlockweb.accounts.views.su', {'redirect_url': '/qlockdata/'}),
That done, the second and final step is to write some view code.
@user_passes_test(lambda u: u.is_staff)
def su(request, username, redirect_url='/'):
su_user = get_object_or_404(User, username=username)
if su_user.is_active:
request.session[SESSION_KEY] = su_user.id
return HttpResponseRedirect(redirect_url)
Seven lines of code and we're done (modulo a bunch of import statements).
Expanding what's going on here:
(r'^su/(?P<username>.*)/$', 'qlockweb.accounts.views.su', {'redirect_url': '/qlockdata/'}),
urls.py
line above; the /(?P<username>.*)/ part of the regexp pulls out "fred" and this gets
passed as a parameter named username into the function su
in qlockweb/accounts/views.py. This function also gets passed a parameter
called redirect_url with value '/qlockdata/'.@user_passes_test(lambda u: u.is_staff)
su function. The
line before the function definition is a Python
decorator: some extra code wrapping the function that gets
executed just before the function itself is executed. This decorator needs some expansion of its own:
@user_passes_test(lambda u: u.is_staff)
@user_passes_test(lambda u: u.is_staff)
contrib/auth/decorators.py); its first
argument test_func is a function that does the test. This test function is given
a single parameter: the current User. If the test function returns
true, the wrapped view code is called; if not, then the user gets redirected to a login page.
@user_passes_test(lambda u: u.is_staff)
is_this_a_staff_user(u) that
checks whether its argument u is an administrator. However, as this is the
only place that the function is used, we don't bother to give it a name—we just use
a lambda expression
to give the definition right here and now.@user_passes_test(lambda u: u.is_staff)
User class
that indicates whether the user is an administrator or not.def su(request, username, redirect_url='/'):
su function itself, and if we've got this far we're guaranteed that the person viewing the
page is logged in as an is_staff user. The function has the username
and redirect_url parameters mentioned earlier; it also has a request
parameter that holds all of the information about the original web request (in a
HttpRequest
object).su_user = get_object_or_404(User, username=username)
User object for the username that was
specified—fred in other words. If there isn't a user called fred, then
a Http404 exception gets raised, which will percolate up the stack and display a (surprise,
surprise) 404 page.if su_user.is_active:
is_active field in the standard User model.request.session[SESSION_KEY] = su_user.id
return HttpResponseRedirect(redirect_url)
redirect_url page.(Statutory disclaimer: I am not a security expert, nor do I play one on TV. Adding this to a production system is probably not a good idea.)
Another Django snippet: I finally
discovered
that the follow argument to the standard
Manipulators
allows you to list fields in the model that the form should leave untouched. Very helpful: the
end result is more compact
and less brittle than the code I'd put together to manually override all of the hidden fields.
[A:37385 B:3278 C:346 D:9187 E:62544 Total:112740]
Time:
5:29 PM
3
comments
Tags:
django,
software
Saturday, December 02, 2006
Mind Hack #39
[reading: Jón Árnason, Alan Boucher (translator), "Icelandic Folk Tales"]
One of the MindHacks that doesn't include an easy demonstration is Hack 39, where you're less likely to notice a trigger event if it occurs soon (say, <0.5s) after another trigger event.
(Now that I've got into the content rather than being distracted by the typesetting, the book is turning out to be rather good.)
My first attempt to test this out is below, but I have to say that the effect didn't seem all that strong to me—so maybe there's a bug or I've implemented it wrong. Or maybe I'm just too impatient to run it for long enough to get statistically significant data.
After hitting "Go", this applet will display letters for a tenth of a second each. You should hit a key whenever the letter displayed is either "X" or is displayed in white. To stop the applet, hit "Stop" or press the Escape key.
After running the applet, the bar graph shows the time between triggers (on the X axis) against how many triggers there were with that delay; the white is the total number shown, the black is the subset of them that were missed. Hitting "Go" again accumulates more data.
Technical Details: letters are picked uniformly (so there's a 1/26 chance of a letter X trigger) and white is used for the colour 1/20 of the time. A trigger is considered hit if there's a keypress within 1 second after the trigger, but each keypress only counts once (so "trigger, trigger, keypress, letters…" would count as one hit then one missed trigger, with a delay of 1).
[A:37385 B:3278 C:346 D:9187 E:46445 Total:96641]
Time:
2:32 PM
0
comments
Tags:
applet,
books



