
One of the challenges maintaining the Debian archive kit (dak) is
dealing with Debian-specific requirements: fundamentally because there
are a lot of them, and they can get quite hairy – yet at the same time,
you want to keep them as separate as possible both so dak can be used
elsewhere, and just so you can keep your head around what’s going on.
You can always add in hooks, but that tends to make the code even harder
to understand, and it doesn’t really achieve much if you hadn’t already
added the hook.
However, dak’s coded in python, and being an interpreted language
with lots of support for introspection, that more or less means there’s
already hooks in place just about everywhere. For example, if you don’t
like the way some function in some other module/class works, you can
always change it (
other_module.function = my_better_function).
Thus, with some care and a bit of behind the scenes kludging, you
can have python load a module from a file specified in dak.conf that can
both override functions/variables in existing modules, and be called directly
from other modules where you’ve already decided a configurable hook would
be a good idea.
So, at the moment, as a pretty simple example there’s an
init() hook invoked from the main
dak.py
script, which simply says
if userext.init is not None:
userext.init(cmdname).
But more nifty is the ability to replace functions, simply by writing
something like:
# Replace process_unchecked.py's check_signed_by_key
@replace_dak_function("process-unchecked", "check_signed_by_key")
def check_signed_by_key(old_chk_key):
changes = dak_module.changes
reject = dak_module.reject
...
old_chk_key()
That’s made possible mostly by the magic of python decorators – the
little @-sign basically passes the new
check_signed_by_key
function to
replace_dak_function (or, more accurately,
the function
replace_dak_function(...) returns), which does
the dirty work replacing the function in the real module. To be just a
little bit cleverer, it doesn’t replace it with the function we define,
but its own function with simply invokes our function with an additional
argument to whatever the caller supplied, so we can invoke the original
function if we choose (the
old_chk_key parameter – the
original function takes no arguments, so our function only takes one).
Right now, we don’t do much interesting with it; but that should change
once
Ganneff’s little patch is finished, which should be RSN…
Hopefully, this might start making it easier to keep dak maintained
in a way that’s useful for non-Debian installs – particularly if we
can get to the point where hacking it for Debian generally just implies
changing configuration and extension stuff – then we can treat updating
all the real scripts as a regular software upgrade, just like it is
outside Debian.