En Thu, 26 Mar 2009 15:23:50 -0300, zopyxfil...@googlemail.com
<zopyxfil...@googlemail.com> escribió:

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.

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to