Pylint: Python modules without __init__.py failed to be parsed since 2.5.0

Created on 27 Apr 2020  ·  12Comments  ·  Source: PyCQA/pylint

Pylint 2.5 fails to parse modules without __init__.py while 2.4.4 works fine.
I found nothing in the changelog regarding this, so I guess it's a bug.

Steps to reproduce

  1. create a python module without __init__.py
  2. run pylint --disable=C,R ${MODULE_NAME}

Current behavior

raises:

************* Module ${MODULE_NAME}
${MODULE_NAME}/__init__.py:1:0: F0010: error while code parsing: Unable to load file ${MODULE_NAME}/__init__.py:
[Errno 2] No such file or directory: '${MODULE_NAME}/__init__.py' (parse-error)

Expected behavior

No error expected since __init__.py are optional since python 3.4+

pylint --version output

pylint==2.5.0
python==3.6.10

bug regression

Most helpful comment

On second look, the fix turned out to be simpler than what I imagined. It's semantically the same with the old behaviour except sys.path is not modified.

All 12 comments

I saw that but thought this was "normal" and the same than #352

I've done a git bisect on this. Seem like the culprit is https://github.com/PyCQA/pylint/commit/a6d7ffc4679b0ad2258cf6c31c6dfbeeb2b331ef. I guess we don't want to revert it entirely? What do you think @PCManticore ?

@Pierre-Sassoulas This is the exact same thing as #352. pylint never managed to analyze directories without __init__.py files.

I was able to reproduce it with the following version as well, which does not have the changes in the linked commit:

pylint 2.4.4
astroid 2.3.3
Python 3.8.1 (default, Feb 13 2020, 10:17:07)
[Clang 8.1.0 (clang-802.0.42)]

@nicocti Until we have a fix for #352, you'll need to either have a __init__.py in the directory that you are passing to pylint as an argument or you need to rely on shell expansion as in running pylint with pylint your_module/*.

Strange, I tested by creating a directory called module with a test.py inside it and no __init__.py. Then, the test was:

pip3 install .;python3 pylint/__main__.py module

This was clearly working for 2.4.4 and until the commit which I linked, or am I missing something?

No, you're right, for some reason my testing resulted in the same results on both versions.

On second look, the fix turned out to be simpler than what I imagined. It's semantically the same with the old behaviour except sys.path is not modified.

Thanks a lot for this quick fix :) Will keep you updated once I switch to 2.5.1 !

I think this caused a regression I am seeing; I was having no issues as of 2.4.4 nor 2.5.0:

layout:

qemu/
  lib/
    __init__.py
    qmp.py
    machine.py
    qtest.py

qtest.py has an import statement like this:

from .machine import QEMUMachine

If CWD is qemu/lib and I execute:
> pylint qtest.py

2.4.4:

Your code has been rated at 10.00/10 (previous run: 9.82/10, +0.18)

2.5.0:

Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)

but 2.5.1:

qtest.py:24:0: E0402: Attempted relative import beyond top-level package (relative-beyond-top-level)

Current setup:

pylint 2.5.1
astroid 2.4.1
Python 3.7.7 (default, Mar 13 2020, 21:39:43) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)]

If I install a dev copy of 4756b3c611ef710c99b51d2fe5f04d72b28e75d6 (origin/master as of writing) and revert this change, the explicit relative import works again.

From what I can tell, it seems as if the fact that I have an __init__.py is getting ignored (?), and my file is being processed as if it wasn't in a package.

@PCManticore sorry for the pester; should I port my reply here into a new issue?

@jnsnow No worries. Yes, please open a new issue as it's more likely to get attention. Thank you!

Note that you will get the same behavior as in the first message when you're linting some local implicit namespace package that (for whatever reason) has the same name as another regular package from sys.path. For example,

<some-other-path-from-sys.path>/xyz/
└── __init__.py
./xyz/
└── module.py

$ pylint --disable=C,R xyz
************* Module xyz
xyz/__init__.py:1:0: F0010: error while code parsing: Unable to load file xyz/__init__.py:
[Errno 2] No such file or directory: 'xyz/__init__.py' (parse-error)

At the same time it will run perfectly fine for
<some-other-path-from-sys.path>/abcd/ └── inner └── __init__.py abcd └── inner └── module.py

Was this page helpful?
0 / 5 - 0 ratings