Packages in same namespace: declare version in code
<p>I'm curious about the following situation. Let's say I have two projects named <code>project_alpha</code> and <code>project_bravo</code>, both defining a top-level namespace package <code>mymeta</code>. The layout:</p>

<pre><code>project_alpha/
   -&gt; mymeta/
        -&gt; __init__.py
        -&gt; project_alpha/
             -&gt; __init__.py
             -&gt; version.py
   -&gt; setup.py

project_bravo/
   -&gt; mymeta/
        -&gt; __init__.py
        -&gt; project_bravo/
             -&gt; __init__.py
             -&gt; version.py
   -&gt; setup.py
</code></pre>

<p>Both <code>mymeta/__init__.py</code>s contain only the line <code>__import__('pkg_resources').declare_namespace(__name__)</code> (according to <a href="http://setuptools.readthedocs.io/en/latest/setuptools.html#namespace-packages" rel="nofollow">namespace section in setuptools docs</a>). Contents of both <code>version.py</code>s:
</p>

<pre><code>__version_info__ = (0, 9, 9, 'dev0')
__version__ = '.'.join((str(entry) for entry in __version_info__)) 
</code></pre>

<p>The <code>setup.py</code> script for <code>project_alpha</code> is pretty simple. The namespace package <code>mymeta</code> is declared, and the version is taken from the <code>version</code> module:
</p>

<pre><code># project_alpha
from setuptools import find_packages, setup
from mymeta.project_alpha.version import __version__

setup(
    name='mymeta.project-alpha',
    version=__version__,
    namespace_packages=['mymeta'],
    packages=find_packages(),
)
</code></pre>

<p>The <code>setup.py</code> script for <code>project_bravo</code> has the same structure, but with a twist: <code>project_bravo</code> depends on <code>project_alpha</code> when building:
</p>

<pre><code>from setuptools import find_packages, setup
from mymeta.project_bravo.version import __version__

setup(
    name='mymeta.project-bravo',
    version=__version__,
    namespace_packages=['mymeta'],
    setup_requires=['mymeta.project-alpha'],
    packages=find_packages(),
)
</code></pre>

<p>When building <code>project_bravo</code>, I get the following error:</p>

<pre><code>~/project_bravo $ python setup.py sdist 
Traceback (most recent call last):
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 156, in save_modules
    yield saved
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context
    yield
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 246, in run_setup
    DirectorySandbox(setup_dir).run(runner)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 276, in run
    return func()
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 245, in runner
    _execfile(setup_script, ns)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 47, in _execfile
    exec(code, globals, locals)
  File "/tmp/easy_install-ahmxos98/mymeta.project-alpha-0.9.9.dev0/setup.py", line 6, in &lt;module&gt;
    try:
ImportError: No module named 'mymeta.project_alpha'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "setup.py", line 22, in &lt;module&gt;
    packages=find_packages(),
  File "/usr/lib64/python3.5/distutils/core.py", line 108, in setup
    _setup_distribution = dist = klass(attrs)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 315, in __init__
    self.fetch_build_eggs(attrs['setup_requires'])
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 361, in fetch_build_eggs
    replace_conflicting=True,
  File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 853, in resolve
    dist = best[req.key] = env.best_match(req, ws, installer)
  File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1125, in best_match
    return self.obtain(req, installer)
  File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1137, in obtain
    return installer(requirement)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 429, in fetch_build_egg
    return cmd.easy_install(req)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 665, in easy_install
    return self.install_item(spec, dist.location, tmpdir, deps)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 695, in install_item
    dists = self.install_eggs(spec, download, tmpdir)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 876, in install_eggs
    return self.build_and_install(setup_script, setup_base)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1115, in build_and_install
    self.run_setup(setup_script, setup_base, args)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1101, in run_setup
    run_setup(setup_script, args)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 249, in run_setup
    raise
  File "/usr/lib64/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context
    yield
  File "/usr/lib64/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 168, in save_modules
    saved_exc.resume()
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 143, in resume
    six.reraise(type, exc, self._tb)
  File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/_vendor/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 156, in save_modules
    yield saved
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context
    yield
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 246, in run_setup
    DirectorySandbox(setup_dir).run(runner)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 276, in run
    return func()
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 245, in runner
    _execfile(setup_script, ns)
  File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 47, in _execfile
    exec(code, globals, locals)
  File "/tmp/easy_install-ahmxos98/mymeta.project-alpha-0.9.9.dev0/setup.py", line 6, in &lt;module&gt;
    try:
ImportError: No module named 'mymeta.project_alpha'
</code></pre>

<p>Unfortunately, I don't understand the error here. It has something to do with the imports order, right? If I comment out the import of <code>mymeta.project_bravo.version</code> in <code>project_bravo/setup.py</code> and replace the <code>version</code> with some hard-coded string, suddenly the build succeeds...</p>

<hr>

<p>Edit: I introduced a workaround for this issue. Instead of trying to import the version directly, I <code>exec</code> the version module to avoid the import problems. Of course, this is not a proper solution, thus not posting this as answer, but still here it is:
</p>

<pre><code>__version__ = None # if the exec fails, leave the version unset, the resulting build version will be 0.0.0
version_script_path = os.path.relpath(os.path.join(os.path.dirname(__file__), 'mymeta', 'project_alpha', 'version.py'))
with open(version_script_path) as version_script:
    exec(version_script.read())
</code></pre>

<p>After the version script is read and executed, the version is initialized, thus no need to import anything from <code>mymeta</code> package.</p>

<p>As mentioned in the comments: The command</p>

<pre><code>$ python setup.py sdist
</code></pre>

<p>for <code>mymeta.project_bravo</code> downloads an egg of <code>mymeta.project_alpha</code> from a private pypi repo.</p>

<p>Namespace packages are very delicate concerning their imports. </p>

<p>e.g. I found out that when I install <code>ns.a</code> and <code>ns.b</code> regularly in my environment and supply the import path of <code>ns.d</code> in a .pth file in the site-packages directory, it will not work, no matter what. However when I symlink to <code>ns.d</code> in site-packeges/ns directory it will work.</p>

<p>If I install none of the components and supply all paths in a .pth in the site-packages directory, everything works fine.</p>

<p>If I install all of the components regularly also everything works fine.</p>

<p>Just when I mix concepts it will not work.</p>

<p>Therefore I suspect that this might also be the issue here: Different strategies for the import paths.</p>

<p>You might want to try to modify your <code>__init__.py</code> file to:</p>

<pre><code>from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
__import__('pkg_resources').declare_namespace(__name__)
</code></pre>

<p>I regret my decision to do namespace packages. I would never do it again. </p>

python setuptools