[Distutils] Changing the "install hooks" mechanism for PEP 426

Nick Coghlan ncoghlan at gmail.com
Wed Aug 14 17:36:32 CEST 2013

I spent last weekend at "Flock to Fedora", mostly due to my day job
working on the Beaker integration testing system
(http://beaker-project.org) for Red Hat, but also to talk to folks
about Fedora and Python interactions.

A completely unexpected discovery over the weekend, was that some of
the RPM folks are exploring the idea of switching the *user* facing
format for the packaging system away from spec files and towards
directly executable Python code. Thus, you'd get away from the painful
mess that is RPM conditionals and macros and have a real programming
language to define what your built packages *should* look like, while
still *producing* static metadata for consumption by installers and
other software distribution tools.

Hmm, does that approach sound familiar to anyone? :)

Anyway, we were talking about how they're considering approaching the
install hook problem, and their approach gave me an idea for a better
solution in PEP 426.

Currently, PEP 426 allows a distribution to define "install hooks":
hooks that will execute after the distribution is installed and before
it is uninstalled.

I'm now planning to change that to allowing distributions to define
"export hooks", based on the cleaned up notion of "export groups" in
the latest version of PEP 426. An export hook definition consists of
the following fields:

* group - name of the export group to hook
* preupdate - export to call prior to installing/updating/removing a
distribution that exports this export group
* postupdate - export to call after installing/updating/removing a
distribution that exports this export group
* refresh - export to call to resynchronise any caches with the system
state. This will be invoked for every distribution on the system that
exports this export group any time the distribution defining the
export hook is itself installed or upgraded

If a distribution exports groups that it also defines hooks for, it
will exhibit the following behaviours:

    Fresh install:
        * preupdate NOT called (hook not yet registered)
        * postupdate called
        * refresh called

        * preupdate called (old version)
        * postupdate called (new version)
        * refresh called (new version)

    Complete removal:
        * preupdate called
        * postupdate NOT called (hook no longer registered)
        * refresh NOT called (hook no longer registered)

This behaviour follows naturally from *not* special casing
self-exports: prior to installation, the export hooks won't be
registered, so they won't be called, and the same applies following
complete removal.

The hooks would have the following signatures:

    def preupdate(current_meta, next_meta):
       # current_meta==None indicates fresh install
       # next_meta==None indicates complete removal

   def postupdate(previous_meta, current_meta):
       # previous_meta==None indicates fresh install
       # current_meta==None indicates complete removal

    def refresh(current_meta):
        # Used to ensure any caches are consistent with system state
        # Allows handling of previously installed distributions


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Distutils-SIG mailing list