[Distutils] Egg depency order

Phillip J. Eby pje at telecommunity.com
Tue Jan 15 16:28:31 CET 2008

At 08:11 AM 1/15/2008 +0200, Iwan Vosloo wrote:
>We are writing an app on top of postgresql, using sqlobject. The thing
>is broken into different re-usable modules - not all of tcanhese modules
>need to be installed together.  The idea is to package a module in an
>egg, and have the egg advertise all the sqlobject classes (ie, those
>that are persisted) via entry points.
>We can then write a seperate generic tool which (given the resource spec
>of an arbitrary module) can, for example go and create all the database
>tables necessary. But this is something that needs to happen in a
>specific order because some tables depend on others.

Ah.  In that case, just use something roughly like this:

     def create_tables_for_requirement(req, memo=None):
         if memo is None: memo = {}
         for dist in pkg_resources.require(req):
             create_tables_for_dist(dist, memo)

     def create_tables_for_dist(dist, memo):
         if dist not in memo:
             memo[dist] = 1
             for name, ep in dist.get_entry_map('foo.tables'):
                 create_table_for_entry_point(ep, memo)

     def create_table_for_entry_point(ep, memo):
         create_tables_for_requirement(ep.dist.requires(ep.extras), memo)
         # actually create the table here

This might be slightly more complex due to the fact that the tables 
in a given distribution might depend on each other, and there isn't 
any dependency data in eggs that can tell you about *that*.  You 
might find it simpler to have an entry point for an object that lists 
the distribution's tables.

In fact, the simplest approach of all would be for your table objects 
to simply import their dependencies and have attributes that you can 
follow for that.  In which case, you don't need *any* of this code, 
because simply loading the entry point would then suffice for 
resolving the dependencies.

>The tool can do many other things besides creating tables. For example,
>we'd also like to develop a generic framework on top of sqlobject which
>will allow us to easily specify the necessary database schema changes,
>new tables, changed tables and so on (migrations) that are necessary
>when upgrading from one version of our eggs to another.
>The idea is that knowledge of classes, tables, and how to migrate old
>data would be contained in each module's egg. But the generic code to
>create /change databases would be in its own egg.

But also note that you don't need to encode everything as egg 
metadata -- the Python objects referred to by the entry points can 
have arbitrary complexity.

More information about the Distutils-SIG mailing list