pylint
pylint copied to clipboard
Relative imports broken in pylint 2.5.2
Pylint fails with relative imports within a package. Having a package b in directory a with three files:
a/b/__init__.py
from .one import ONE from .two import TWO
a/b/one.py
ONE = 1
a/b/two.py
from .one import ONE TWO = ONE + ONE
pylint 2.4.4 + astroid 2.3.3 do not generate any warning or error, which is as expected.
pylint 2.5.2 + astroid 2.4.1 generates an import-error:
$ export PYTHONPATH=/full/path/to/a $ cd /full/path/to $ pylint a ************* Module a.b a/b/__init__.py:2:0: E0401: Unable to import 'a.b.two' (import-error)
Versions:
$ pylint --version pylint 2.5.2 astroid 2.4.1 Python 3.8.3 (default, May 17 2020, 18:15:42) [GCC 10.1.0]
I also run into this. But I get "E402 : Attempted relative import beyond top-level package (relative-beyond-top-level)" instead of E401. Also the error depends on what $(pwd)
is when pylint
is launched. A reproducer that you can copy-paste:
cd /tmp
mkdir -p a/
touch a/__init__.py
echo -e "s = 1\nprint(s)" > a/b.py
echo -e "from .b import s\nprint(s)" > a/c.py
cd /tmp/a/
pylint /tmp/a/c.py # error E402
cd /tmp/
pylint /tmp/a/c.py # ok
cd /
pylint /tmp/a/c.py # ok
I also run into this. But I get "E402 : Attempted relative import beyond top-level package (relative-beyond-top-level)" instead of E401. Also the error depends on what
$(pwd)
is whenpylint
is launched. A reproducer that you can copy-paste:
Thank you! That issue is already reported, but it is a different case. If you want to test the case that is described in this issue:
mkdir -p /tmp/a/b echo -e "ONE = 1" > /tmp/a/b/one.py echo -e "from .one import ONE\nTWO = ONE + ONE" > /tmp/a/b/two.py echo -e "from .one import ONE\nfrom .two import TWO" > /tmp/a/b/__init__.py echo -e "import b\nprint(b.TWO)" > /tmp/a/main.py cd /tmp pylint a
Setting PYTHONPATH (to /tmp/a) does not make a difference.
I noticed that this issues is very sensitive to the environment - i.e. it triggered on the dev machine but not the CI. The discrepancy appears even with tox inside the identical docker image.
Apparently the reason is that it is sensitive to the order in which files are iterated (os.walk
) by asroid.
I'm seeing this was fixed in PyCQA/astroid@2ee20ccdf62450db611acc4a1a7e42f407ce8a14 (2.9.1). A test would be a good idea, though, since it looks a little orthogonal to what was described there.
See a report in https://github.com/PyCQA/pylint/issues/5319#issuecomment-1192998978 that this isn't fixed yet on astroid 2.11.7.
See an attempt at a regression test in #7117
In the original example, a
is not a package. In more modern versions of pylint/astroid --recursive=y
is the solution for iterating directories to find packages, e.g. b
. #7117 adds a test to ensure a/b
can be linted.