pylint icon indicating copy to clipboard operation
pylint copied to clipboard

"ImportError: Unable to find module" when using implicit namespaces when they already exist in site-packages

Open felixfontein opened this issue 8 months ago • 0 comments

Bug description

I have an implicit namespace test1 that exists both in site-packages and in a local project checkout:

site-packages/test1  # <-- just an empty directory already reproduces the problem
project/test1
project/test1/test2
project/test1/test2/__init__.py
project/test1/test2/test.py

Now if I run pylint --source-roots . test1/test2 in project/, I get

Traceback (most recent call last):
  File "/tmp/test/.venv/bin/pylint", line 8, in <module>
    sys.exit(run_pylint())
             ~~~~~~~~~~^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/__init__.py", line 34, in run_pylint
    PylintRun(argv or sys.argv[1:])
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/run.py", line 240, in __init__
    linter.check(args)
    ~~~~~~~~~~~~^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 701, in check
    ast_per_fileitem = self._get_asts(fileitems, data)
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 712, in _get_asts
    for fileitem in fileitems:
                    ^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 875, in _iterate_file_descrs
    for descr in self._expand_files(files_or_modules).values():
                 ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 886, in _expand_files
    result, errors = expand_modules(
                     ~~~~~~~~~~~~~~^
        files_or_modules,
        ^^^^^^^^^^^^^^^^^
    ...<3 lines>...
        self._ignore_paths,
        ^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/expand_modules.py", line 175, in expand_modules
    modpath = _modpath_from_file(
        subfilepath, is_namespace, path=additional_search_path
    )
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/expand_modules.py", line 22, in _modpath_from_file
    return modutils.modpath_from_file_with_callback(  # type: ignore[no-any-return]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        filename, path=path, is_package_cb=_is_package_cb
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/tmp/test/.venv/lib/python3.13/site-packages/astroid/modutils.py", line 294, in modpath_from_file_with_callback
    raise ImportError(
        "Unable to find module for {} in {}".format(filename, ", \n".join(sys.path))
    )
ImportError: Unable to find module for test1/test2/test.py in /tmp/test/root, 
/tmp/test/.venv/bin, 
/usr/lib/python313.zip, 
/usr/lib/python3.13, 
/usr/lib/python3.13/lib-dynload, 
/tmp/test/.venv/lib/python3.13/site-packages

If site-packages/test1 does not exist, this works fine.

(See below for a minimal reproducer that creates the directories and files in /tmp/test.)

I can reproduce this with the latest pylint from PyPI in a clean venv (with Python 3.13.2).

Configuration


Command used

mkdir /tmp/test
cd /tmp/test
python -m venv .venv
. .venv/bin/activate
pip install pylint
pushd .venv/lib/python*/site-packages/
mkdir test1
popd
mkdir -p root/test1/test2/
cd root
touch test1/test2/__init__.py
touch test1/test2/test.py
pylint --source-root . test1/test2

This installs for me:

Successfully installed astroid-3.3.9 dill-0.3.9 isort-6.0.1 mccabe-0.7.0 platformdirs-4.3.6 pylint-3.3.5 tomlkit-0.13.2

Pylint output

Traceback (most recent call last):
  File "/tmp/test/.venv/bin/pylint", line 8, in <module>
    sys.exit(run_pylint())
             ~~~~~~~~~~^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/__init__.py", line 34, in run_pylint
    PylintRun(argv or sys.argv[1:])
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/run.py", line 240, in __init__
    linter.check(args)
    ~~~~~~~~~~~~^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 701, in check
    ast_per_fileitem = self._get_asts(fileitems, data)
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 712, in _get_asts
    for fileitem in fileitems:
                    ^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 875, in _iterate_file_descrs
    for descr in self._expand_files(files_or_modules).values():
                 ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 886, in _expand_files
    result, errors = expand_modules(
                     ~~~~~~~~~~~~~~^
        files_or_modules,
        ^^^^^^^^^^^^^^^^^
    ...<3 lines>...
        self._ignore_paths,
        ^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/expand_modules.py", line 175, in expand_modules
    modpath = _modpath_from_file(
        subfilepath, is_namespace, path=additional_search_path
    )
  File "/tmp/test/.venv/lib/python3.13/site-packages/pylint/lint/expand_modules.py", line 22, in _modpath_from_file
    return modutils.modpath_from_file_with_callback(  # type: ignore[no-any-return]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        filename, path=path, is_package_cb=_is_package_cb
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/tmp/test/.venv/lib/python3.13/site-packages/astroid/modutils.py", line 294, in modpath_from_file_with_callback
    raise ImportError(
        "Unable to find module for {} in {}".format(filename, ", \n".join(sys.path))
    )
ImportError: Unable to find module for test1/test2/test.py in /tmp/test/root, 
/tmp/test/.venv/bin, 
/usr/lib/python313.zip, 
/usr/lib/python3.13, 
/usr/lib/python3.13/lib-dynload, 
/tmp/test/.venv/lib/python3.13/site-packages

Expected behavior

It does some linting instead of showing that exception.

Pylint version

pylint 3.3.5
astroid 3.3.9
Python 3.13.2 (main, Feb  5 2025, 08:05:21) [GCC 14.2.1 20250128]

OS / Environment

Arch Linux

Additional dependencies


felixfontein avatar Mar 16 '25 11:03 felixfontein