Import aliases for moving a module?

Z

zopyxfilter

For a while a maintained a Python package 'foo' with a number of
modules (including a nested structure of module). Now the package
moved into a namespace package
'a.b.foo'. What is the way to approach making old code work with the
new package in order
that imports like

import foo.bar.xxx
or
from foo.bar import xxx

remain working for existing code.

-a
 
G

Gabriel Genellina

En Thu, 26 Mar 2009 15:23:50 -0300, (e-mail address removed)
For a while a maintained a Python package 'foo' with a number of
modules (including a nested structure of module). Now the package
moved into a namespace package
'a.b.foo'. What is the way to approach making old code work with the
new package in order
that imports like

import foo.bar.xxx
or
from foo.bar import xxx

remain working for existing code.

A quick and dirty solution is to have a foo package with an __init__.py
that imports *every* single name in the old package, from the new one, and
puts it in sys.modules under the old name.

C:\temp>tree /f a
C:\TEMP\A
│ __init__.py
│
└───b
│ __init__.py
│
└───foo
one.py
three.py
two.py
__init__.py


C:\temp>tree /f foo
C:\TEMP\FOO
__init__.py

C:\temp>type foo\__init__.py
import warnings
warnings.warn("The 'foo' package is obsolete; use 'a.b.foo' instead",
DeprecationWarning, 2)

import sys
from a.b import foo
from a.b.foo import one, two
sys.modules['foo.one'] = one
sys.modules['foo.two'] = two

# very last line!
sys.modules['foo'] = foo
# now *this* module is gone

C:\temp>type a\b\foo\one.py
print "This is one.py", __file__, __name__

C:\temp>type a\b\foo\two.py
print "This is two.py", __file__, __name__

C:\temp>type a\b\foo\three.py
print "This is three.py", __file__, __name__

All other __init__.py files are empty. Now, you can import foo and its
contents under the old and new names:

py> import foo
__main__:1: DeprecationWarning: The 'foo' package is obsolete; use
'a.b.foo' ins
tead
This is one.py a\b\foo\one.pyc a.b.foo.one
This is two.py a\b\foo\two.pyc a.b.foo.two
py> import foo.one
py> import a.b.foo.one
py> a.b.foo.one
<module 'a.b.foo.one' from 'a\b\foo\one.pyc'>
py> foo.one
<module 'a.b.foo.one' from 'a\b\foo\one.pyc'>
py> foo.one is a.b.foo.one
True
py> import foo.two
py> import a.b.foo.two

Note that one.py and two.py are imported only once. *BUT* notice what
happens when you import three.py, that was NOT included in foo\__init__.py:

py> import foo.three
This is three.py a\b\foo\three.pyc foo.three
py> import a.b.foo.three
This is three.py a\b\foo\three.pyc a.b.foo.three

That module was imported *twice*. So it's important to pre-import (inside
foo\__init__.py) *every* name that was present in the old foo package. If
this is not feasible (there are many names, or loading all of them would
be too slow, or whatever) you may implement a "lazy" importer. See
__init__.py in the email package for an example.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top