Monthly Archives: May 2010

Death or beachball

[Pierre Igot][igot]’s post about [Adobe’s use of a new cursor in CS5][cs5] draws attention to how Adobe is continuing to fail to adhere to Macintosh user interface conventions.

But I disagree that the correct cursor to use for a blocking task that cannot be cancelled is the spinning beachball of death. That cursor after all is the cursor automatically provided by the operating system when an application is _not responding to input events_. As such when I see the beachball I associate it with a stuck application, one that may need to be forcibly quit.

Previous versions of Photoshop showed the watch cursor for actions which took a significant length of time. Showing the watch cursor is friendlier than showing the beachball of death because it indicates that the application is busy, too busy to handle your clicks but everything is hunky dory and the train _will_ arrive at the station.

There is no watch cursor listed in [Apple’s documentation on cursors][cursors]. However the cursor is still present in the system and can be found in the headers for the carbon appearance manager:

kThemeWatchCursor = 7, /* Can Animate */

If you have Xcode 3.2.2 installed you can find this in `/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Appearance.h`, line 634.

I don’t know enough about Macintosh programming to say whether it is possible to employ this cursor from a Cocoa-based application.

[igot]: http://www.betalogue.com
[cs5]: http://www.betalogue.com/2010/05/18/cs5-cursor/
[cursors]: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSCursor_Class/Reference/Reference.html

More Python features that I really like

Another thing that makes using [Python][python] pleasing is decorators. [A decorator is a wrapper for a function][decorators] (or method) that takes a function (or method) as an argument and returns a new function (or…) which is then bound to the name for the original function.

The newly-decorated function can then do things like checking the called arguments before invoking the original un-decorated function.

[Django provides decorators for authentication][django] so that you can wrap a view function with a check for client credentials before deciding whether to return the original response or a deny access.

In this manner Django’s authentication decorators encourage orthogonal code: the logic for displaying a view is separated from the logic for deciding whether you should be permitted to see the view’s output. By keeping them separate, it becomes simpler to re-use the authentication logic and apply it to other views.

Suppose you have a view that accepts [a Django request object][request] and checks whether the user is signed in:

def administration_page(request):
if request.user.is_authenticated():
return HttpResponse(“Welcome, dear user.”)
else:
return HttpResponseRedirect(“/signin/”)

With a decorator you can simplify and clarify things:

@login_required
def administration_page(request):
return HttpResponse(“Welcome, dear user.”)

For older versions of Python (pre 2.4) [which don’t understand the `@` operator][syntax] one must explicitly decorate the view function like so:

def administration_page(request):
return HttpResponse(“Welcome, dear administrator.”)

administration_page = login_required(administration_page)

Note in the example that the original `administration_page` function is passed to the decorator. The `@` syntax in the first example makes that implicit but the two are equivalent.

The implementation of a decorator is interesting. It takes the function itself as an argument and returns a new function which does the actual checking. Here is how the decorator used above might do its stuff:

def login_required(view_function):
def decorated_function(request):
if request.user.is_authenticated():
return view_function(request)
else:
return HttpResponseRedirect(“/signin/”)

return decorated_function

_The actual [implementation of Django’s `login_required` decorator][login_required] is considerably less idiotic. Python’s [functools module][functools] has helpers for writing well-behaved decorators._

Because functions in Python are themselves objects the decorator can accept a function reference, construct a new function that checks for authentication and then return a reference to that new function.

Simples!

(Simples gets less simples when you want to write a decorator that accepts configuration arguments because you then need either another layer of nested function definitions or a class whose instances can be called directly, but I’m going to ignore you for a bit and _wow is that Concorde…?_)

[python]: http://www.python.org
[decorators]: http://docs.python.org/reference/compound_stmts.html#function
[django]: http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test
[request]: http://docs.djangoproject.com/en/dev/ref/request-response/
[syntax]: http://docs.python.org/whatsnew/2.4.html#pep-318-decorators-for-functions-and-methods
[functools]: http://docs.python.org/library/functools.html
[login_required]: http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/auth/decorators.py

Nginx and WordPress

My [Nginx][nginx] and [Wordpress][wp] configuration on [Debian Linux 5 (Lenny)][debian]. This has Nginx as the Web server using the fastcgi module to talk to php-cgi processes that run WordPress with pretty URLs.

The virtual private server I installed this on (from [John Companies][jc]) has a 256 megabyte slice, so I figured a regular Apache + mod_php setup might be in trouble seeing as one of the sites I am running gets several thousand visits a day. Up to now I have always used Apache with mod_php to run WordPress, and anyway it is fun to learn how unfamiliar software works ([Lotus Notes][notes] excepted).

On a side note, [SysV run-levels][sysv] and /etc/rcX.d directories are needlessly clever. [sysv-rc-conf][sysvrcconf] makes editing those easy.

server {
listen 80;
server_name example.com;

root /home/david/example.com;
index index.php index.html index.htm;
error_page 500 502 503 504 /50x.html;

location / {

}

location = /50x.html {
root /var/www/nginx-default;
}

# deny access to .htaccess files, if Apache’s document root
# concurs with nginx’s one
location ~ /\.ht {
deny all;
}

location /b/ {
if (!-e $request_filename) {
rewrite ^(.+)$ /b/index.php?q=$1 last;
}
}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

# Rewrite www.example.com to example.com
server {
listen 80;
server_name www.example.com;
rewrite ^ http://example.com$request_uri?;
}

This configuration is for WordPress installed under http://example.com/b/ on my server.

[nginx]: http://nginx.org/
[wp]: http://wordpress.org/
[jc]: http://www.johncompanies.com/
[notes]: http://www.ibm.com/software/lotus/products/notes/
[sysvrcconf]: http://sysv-rc-conf.sourceforge.net/
[sysv]: http://www.redhat.com/docs/manuals/linux/RHL-9-Manual/ref-guide/s1-boot-init-shutdown-sysv.html
[debian]: http://wiki.debian.org/DebianLenny