Doctest and relative imports
Asked Answered
R

4

24

I'm having trouble using doctest with relative imports. The simple solution is just to get rid of the relative imports. Are there any others?

Say I have a package called example containing 2 files:

example/__init__.py

"""
This package is entirely useless.
>>> arnold = Aardvark()
>>> arnold.talk()
I am an aardvark.
"""

from .A import Aardvark

if __name__ == "__main__":
    import doctest
    doctest.testmod()

example/A.py

class Aardvark(object):
    def talk(self):
        print("I am an aardvark.")

If I now attempt

python example/__init__.py

then I get the error

Traceback (most recent call last):
  File "example/__init__.py", line 8, in <module>
    from .A import Aardvark
ValueError: Attempted relative import in non-package
Rodneyrodolfo answered 28/10, 2010 at 21:16 Comment(2)
I would get rid of the relative imports, many Python style guides strongly discourage them, most forbid them.Lunch
@JasonScheirer Are there any examples for this discouragement? In projects like numpy these are very common.Euratom
P
21

Create another file my_doctest_runner.py:

if __name__ == "__main__":
    import doctest
    import example
    doctest.testmod(example)

Execute my_doctest_runner.py to run doctests in example/__init__.py:

$ python2.7 my_doctest_runner.py
**********************************************************************
File "/tmp/example/__init__.py", line 4, in example
Failed example:
    arnold.talk()
Expected:
    I am an aaardvark.
Got:
    I am an aardvark.
**********************************************************************
1 items had failures:
   1 of   2 in example
***Test Failed*** 1 failures.
Pietje answered 28/10, 2010 at 21:32 Comment(1)
Thanks for the answer. In the end I've ended up changing the relative import to an absolute one, (from example.A import Aadvark) based on Jason Scheirer's comment.Rodneyrodolfo
E
3

Pytest's --doctest-modules flag takes care of relative imports:

$ ls example/
A.py  __init__.py
$ pytest --doctest-modules example
==================== test session starts ====================
...

example/__init__.py .                                 [100%]

===================== 1 passed in 0.03s =====================
Espy answered 26/6, 2022 at 21:29 Comment(1)
Just note that this won't work well with relative imports in namespace packages, so you might need to place an empty __init__.py if you currently have none.Trishatriskelion
O
-1

Just do

from A import Aardvark
Ology answered 28/10, 2010 at 21:21 Comment(2)
well, I am afraid this breaks python 3 compatibility.Ashes
While this code may answer the question, it is better to explain how to solve the problem and provide the code as an example or reference. Code-only answers can be confusing and lack context.Hardaway
F
-1

As of pytest 6.0.0, importlib is a valid import mode. Using that solved the problem for me.

pytest --import-mode=importlib
Fortis answered 9/3, 2023 at 11:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.