Here’s a snippet of code from within TurboGears 1.0.6:
[dispatch.generic(MultiorderGenericFunction)] def run_with_transaction(func, *args, **kw): pass
I can’t figure out how putting a list before a function definition can possibly affect it.
In dispatch.generic’s docstring, it mentions:
Note that when using older Python versions, you must use ‘[dispatch.generic()]’ instead of ‘@dispatch.generic()’.
OK, so it apparently is a way to get decorator-like behavior in pre-decorator versions of Python, but how the heck can it possibly work?
The decorator syntax is provided by PyProtocols.
”’ Finally, it’s important to note that these ‘magic’ decorators use a very sneaky hack: they abuse the sys.settrace() debugger hook to track whether assignments are taking place. Guido takes a very dim view of this, but the hook’s existing functionality isn’t going to change in 2.2, 2.3, or 2.4, so don’t worry about it too much. This is really a trick to get ‘early access’ to decorators, and the 2.4 lifecycle will be plenty long enough to get our code switched over to 2.4 syntax. Somewhere around Python 2.5 or 2.6, add_assignment_advisor() can drop the magic part and just be a backward compatibility wrapper for the decorators that use it. ”’ http://dirtsimple.org/2004/11/using-24-decorators-with-22-and-23.html
So it sounds like these work by wrapping the actual decorator in some magic that hooks into special code for debuggers to manipulate what actually gets assigned for the function.
The python docs say this about settrace
”’ Note The settrace() function is intended only for implementing debuggers, profilers, coverage tools and the like. Its behavior is part of the implementation platform, rather than part of the language definition, and thus may not be available in all Python implementations. ”’