Attempted relative import beyond toplevel package
<p>Here is my folder structure:</p>

<pre><code>Mopy/ # no init.py !
   bash/
     __init__.py
     bash.py # &lt;--- Edit: yep there is such a module too
     bass.py
     bosh/
       __init__.py # contains from .. import bass
       bsa_files.py
     ...
   test_bash\
     __init__.py # code below
     test_bosh\
       __init__.py
       test_bsa_files.py
</code></pre>

<p>In <code>test_bash\__init__.py</code> I have:</p>

<pre><code>import sys
from os.path import dirname, abspath, join, sep
mopy = dirname(dirname(abspath(__file__)))
assert mopy.split(sep)[-1].lower() == 'mopy'
sys.path.append(mopy)
print 'Mopy folder appended to path: ', mopy
</code></pre>

<p>while in <code>test_bsa_files.py</code>:</p>

<pre><code>import unittest
from unittest import TestCase

import bosh

class TestBSAHeader(TestCase):
    def test_read_header(self):
        bosh.bsa_files.Header.read_header()

if __name__ == '__main__':
    unittest.main()
</code></pre>

<p>Now when I issue:</p>

<pre><code>python.exe "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py" C:\path\to\Mopy\test_bash\test_bosh\test_bar.py true
</code></pre>

<p>I get:</p>

<pre><code>Traceback (most recent call last):
  File "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py", line 124, in &lt;module&gt;
    modules = [loadSource(a[0])]
  File "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py", line 43, in loadSource
    module = imp.load_source(moduleName, fileName)
  File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py", line 4, in &lt;module&gt;
    import bosh
  File "C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\bash\bosh\__init__.py", line 50, in &lt;module&gt;
    from .. import bass
ValueError: Attempted relative import beyond toplevel package
</code></pre>

<p>Since 'Mopy" is in the sys.path and <code>bosh\__init__.py</code> is correctly resolved why it complains about relative import above the top level package ? <em>Which is the top level package</em> ?</p>

<p>Incidentally this is my attempt to add tests to a legacy project - had asked in <a href="http://stackoverflow.com/q/34694437/281545">Python test package layout</a> but was closed as a duplicate of <a href="http://stackoverflow.com/q/61151/281545">Where do the Python unit tests go?</a>. Any comments on my current test package layout is much appreciated !</p>

<hr>

<p>Well the <a href="http://stackoverflow.com/a/40022629/281545">answer below</a> does not work in my case:</p>

<p>The <em>module</em> bash.py is the entry point to the application containing:</p>

<pre><code>if __name__ == '__main__':
    main()
</code></pre>

<p>When I use <code>import bash.bosh</code> or <code>from Bash import bosh</code> I get:</p>

<pre><code>C:\_\Python27\python.exe "C:\_\JetBrains\PyCharm 2016.2.2\helpers\pycharm\utrunner.py" C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py true
Testing started at 3:45 PM ...
usage: utrunner.py [-h] [-o OBLIVIONPATH] [-p PERSONALPATH] [-u USERPATH]
                   [-l LOCALAPPDATAPATH] [-b] [-r] [-f FILENAME] [-q] [-i]
                   [-I] [-g GAMENAME] [-d] [-C] [-P] [--no-uac] [--uac]
                   [--bashmon] [-L LANGUAGE]
utrunner.py: error: unrecognized arguments: C:\Dropbox\eclipse_workspaces\python\wrye-bash\Mopy\test_bash\test_bosh\test_bsa_files.py true

Process finished with exit code 2
</code></pre>

<p>This usage messgae is from the main() in bash. No comments...</p>

<p>TLDR: Do</p>

<pre><code>import bash.bosh
</code></pre>

<p>or</p>

<pre><code>from bash import bosh
</code></pre>

<p>If you also just happen to have a construct like <code>bash.bash</code>, you have to make sure your package takes precedence over its contents. Instead of appending, add it to the front of the search order:</p>

<pre><code># test_bash\__init__.py
sys.path.insert(0, mopy)
</code></pre>

<hr>

<p>When you do</p>

<pre><code>import bosh
</code></pre>

<p>it will import the <em>module</em> <code>bosh</code>. This means <code>Mopy/bash</code> is in your <code>sys.path</code>, python finds the file <code>bosh</code> there, and imports it. The module is now globally known by the name <code>bosh</code>. Whether <code>bosh</code> is itself a module or package doesn't matter for this, it only changes whether <code>bosh.py</code> or <code>bosh/__init__.py</code> is used.</p>

<p>Now, when <code>bosh</code> tries to do</p>

<pre><code>from .. import bass
</code></pre>

<p>this is <em>not</em> a file system operation ("one directory up, file bass") but a module name operation. It means "one package level up, module bass". <code>bosh</code> wasn't imported from its package, but on its own, though. So going up one package is not possible - you end up at the package <code>''</code>, which is not valid.</p>

<p>Let's look at what happens when you do</p>

<pre><code>import bash.bosh
</code></pre>

<p>instead. First, the <em>package</em> <code>bash</code> is imported. Then, <code>bosh</code> is imported as a module <em>of that package</em> - it is globally know as <code>bash.bosh</code>, even if you used <code>from bash import bosh</code>.</p>

<p>When <code>bosh</code> does</p>

<pre><code>from .. import bass
</code></pre>

<p>that one works now: going one level up from <code>bash.bosh</code> gets you to <code>bash</code>. From there, <code>bass</code> is imported as <code>bash.bass</code>.</p>

<p>See also <a href="http://stackoverflow.com/a/39932711/5349916">this related answer</a>.</p>

python python-2.7 python-import python-unittest relative-import