[Import-sig] import with versions

Michel Sanner sanner@scripps.edu
Fri, 23 Mar 2001 10:56:11 -0800


Hi,

and thank you to all of you who answered my previous email.

here is what I came up with:

def setVersion(version):
    import os, sys

    # get the generic package name (no version number, say A)
    modDir, modName = os.path.split(__path__[0])

    # build the name of the sub package with version (A_1_0)
    modVersName = modName+'_'+version

    # build the fully qualified package name (A.A_1_0)
    fqModVersName = modName+'.'+modVersName

    # import the sub package DejaVu.DejaVu_1_0 and get a handle to in modVers
    mod = __import__(fqModVersName)
    modVers = getattr(mod, modVersName)

    # temporarly replace the generic module by the module with a version number
    # to enable from A.B import C as all modules of A.A_1_0 are pulled in
    import sys
    sys.modules[modName]=modVers


    # import everything from the module with version. This relies on the
    # __init__.py of the module with version to define __all__.
    modVers = __import__( fqModVersName, locals(), globals(), ['*'] )

    # restor generic module
    sys.modules[modName]=mod

    # loop over the imported objects and added them to the generic
    # module's name space to make "A.A_1_0.B()" valid
    # If the value is a module we also added it to sys.modules to make
    # "from A.A_1_0 import B" valid
    for k,v in modVers.__dict__.items():
        if k[:2]=='__': continue
        setattr(mod,k, v)
        if type(v)==types.ModuleType:
            sys.modules[modName+'.'+k] = v

I place this function in the __init__.py file of my package A.I can then say

>>> import A
>>> A.setVersion('1_0')
>>> from A import B
>>> B
>>> <module 'A.A_1_0.B' from 'A.A_1_0.B.py'>

so this works ! :)

The only problem I could not resolve is the following:

if B.py contains:

>>> from A.C import D

and E.py contains

>>> from C import D

these two classes end up being different. the first one will be
<class A.C.D at 102495e8>
while the second one will be
<class A.A_1_0.C.D at 1025ff40>

In other words this can only work if all imports within the package are done in
a "relative" way ie "from C import D" rather than using a fully qualified name
ie "from A.C import D".

as a consequence many "isinstance(a, b)" test in my code break depending on
whether the class b has been imported in a relative or an absolute way.

I do not understand the details of importing enough to know if this can be
worked around. Suggestions and comments are welcome :)

It would be great to be able to have multiple versions of a package online at
the same time and it should not limit the language's syntax (as some versioning
schemes described earlier do, for instnce not allowing the from package import
.. statment).

-Michel

-- 

-----------------------------------------------------------------------

>>>>>>>>>> AREA CODE CHANGE <<<<<<<<< we are now 858 !!!!!!!

Michel F. Sanner Ph.D.                   The Scripps Research Institute
Assistant Professor			Department of Molecular Biology
					  10550 North Torrey Pines Road
Tel. (858) 784-2341				     La Jolla, CA 92037
Fax. (858) 784-2860
sanner@scripps.edu                        http://www.scripps.edu/sanner
-----------------------------------------------------------------------