Reputation: 27050
How to use a module as both a namespace package and as a container for classes in a specific subproject? That is, how can I import something directly from a namespace package instead of its subpackages?
An example can make the question clearer.
calc
Suppose I want to create a namespace package called calc
, and there are three projects on it (sscce: calcs.tar.gz). The first one, found at the calc-add
directory, has the following structure:
calc-add/calc/
calc-add/calc/add.py
calc-add/calc/__init__.py
The content of calc-add/calc/__init__.py
is just
__import__('pkg_resources').declare_namespace(__name__)
as required by namespace packages, and add.py
has only the following function:
def op(n1, n2):
return n1 + n2
There is another project, at the calc-sub
directory, has the following structure:
calc-sub/calc/
calc-sub/calc/sub.py
calc-sub/calc/__init__.py
The __init__.py
file is identical to the previous one and sub.py
has only a simple function:
def op(n1, n2):
return n1 - n2
Finally, I have a calc-main
directory with the following content:
calc-main/calc/
calc-main/calc/main.py
calc-main/calc/__init__.py
Again, the __init__.py
has only the mentioned line, yet main.py
has the following code:
import calc.add, calc.sub
def apply(n1, n2, op):
if op == "add":
return calc.add.op(n1, n2)
else:
return calc.sub.op(n1, n2)
apply()
functionIf I invoke the Python interpreter with $PYTHONPATH
set as below:
$ PYTHONPATH=$PYTHONPATH:../calc-add/:../calc-sub/ python
then I can call apply()
this way:
>>> import calc.main
>>> calc.main.apply(2, 3, 'add')
5
However, I would like to call apply()
directly from calc
, as below:
>>> import calc
>>> calc.apply(2, 3, 'add')
5
It apparently works if I add the following line to calc-main/calc/__init__.py
:
from main import apply
However, setuptools documenation is very clear:
You must NOT include any other code and data in a namespace package's __init__.py. Even though it may appear to work during development, or when projects are installed as .egg files, it will not work when the projects are installed using "system" packaging tools -- in such cases the __init__.py files will not be installed, let alone executed.
So how can I get what I want without breaking the restriction on __init__.py
files? Is that possible?
Upvotes: 3
Views: 257