Skip to content

Introspection of CFFI compiled modules is broken in 2.15 #7399

Closed
pylint-dev/astroid
#1777
@rjarry

Description

@rjarry

Bug description

With the following script:

# build.py
import cffi

builder = cffi.FFI()
builder.cdef("int bar(int, int);")
builder.set_source(
    "_foo",
    "static int bar(int a, int b) { return a + b; }",
)
builder.compile()

You can produce a compiled cffi module:

$ ls
build.py
$ python3 build.py
$ ls
build.py  _foo.c  _foo.cpython-310-x86_64-linux-gnu.so*  _foo.o

This module can then be imported and the C function can be invoked:

# to_analyze.py
from _foo import lib

assert dir(lib) == ["bar"]
assert lib.bar(4, 5) == 9
$ python3 to_analyze.py
$ # no error

When analyzing this file with pylint 2.15:

Traceback (most recent call last):
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/lint/pylinter.py", line 769, in _lint_file
    check_astroid_module(module)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/lint/pylinter.py", line 1029, in check_astroid_module
    retval = self._check_astroid_module(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/lint/pylinter.py", line 1079, in _check_astroid_module
    walker.walk(node)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/utils/ast_walker.py", line 93, in walk
    self.walk(child)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/utils/ast_walker.py", line 90, in walk
    callback(astroid)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/checkers/imports.py", line 523, in visit_importfrom
    self._add_imported_module(node, f"{imported_module.name}.{name}")
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/checkers/imports.py", line 833, in _add_imported_module
    importedmodname = astroid.modutils.get_module_part(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 438, in get_module_part
    file_from_modpath(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 334, in file_from_modpath
    return file_info_from_modpath(modpath, path, context_file).location
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 384, in file_info_from_modpath
    return _spec_from_modpath(modpath, path, context)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 590, in _spec_from_modpath
    found_spec = spec.find_spec(modpath, [context])
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 392, in find_spec
    finder, spec = _find_spec_with_path(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 354, in _find_spec_with_path
    spec = finder_instance.find_module(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 204, in find_module
    submodule_path = sys.modules[modname].__path__
AttributeError: cffi library '_foo' has no function, constant or global variable named '__path__'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/lint/pylinter.py", line 734, in _lint_files
    self._lint_file(fileitem, module, check_astroid_module)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/lint/pylinter.py", line 771, in _lint_file
    raise astroid.AstroidError from e
astroid.exceptions.AstroidError

Configuration

No response

Command used

pylint --extension-pkg-allow-list _foo to_analyze.py

Pylint output

************* Module to_analyze
to_analyze.py:1:0: C0114: Missing module docstring (missing-module-docstring)
Exception on node <ImportFrom l.1 at 0x7fbe8ecba920> in file '/home/rjarry/tmp/pylint-cffi/to_analyze.py'
Traceback (most recent call last):
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/utils/ast_walker.py", line 90, in walk
    callback(astroid)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/checkers/imports.py", line 523, in visit_importfrom
    self._add_imported_module(node, f"{imported_module.name}.{name}")
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/pylint/checkers/imports.py", line 833, in _add_imported_module
    importedmodname = astroid.modutils.get_module_part(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 438, in get_module_part
    file_from_modpath(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 334, in file_from_modpath
    return file_info_from_modpath(modpath, path, context_file).location
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 384, in file_info_from_modpath
    return _spec_from_modpath(modpath, path, context)
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/modutils.py", line 590, in _spec_from_modpath
    found_spec = spec.find_spec(modpath, [context])
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 392, in find_spec
    finder, spec = _find_spec_with_path(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 354, in _find_spec_with_path
    spec = finder_instance.find_module(
  File "/home/rjarry/tmp/pylint-cffi/foo/lib64/python3.10/site-packages/astroid/interpreter/_import/spec.py", line 204, in find_module
    submodule_path = sys.modules[modname].__path__
AttributeError: cffi library '_foo' has no function, constant or global variable named '__path__'
to_analyze.py:1:0: F0002: to_analyze.py: Fatal error while checking 'to_analyze.py'. Please open an issue in our bug tracker so we address this. There is a pre-filled template that you can use in '/home/rjarry/.cache/pylint/pylint-crash-2022-09-02-10-21-03.txt'. (astroid-error)

Expected behavior

With pylint 2.14:

$ pylint --extension-pkg-allow-list _foo to_analyze.py 
************* Module to_analyze
to_analyze.py:1:0: C0114: Missing module docstring (missing-module-docstring)

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

Pylint version

pylint 2.15.0
astroid 2.12.5
Python 3.10.6 (main, Aug  2 2022, 00:00:00) [GCC 12.1.1 20220507 (Red Hat 12.1.1-1)]

OS / Environment

Fedora 36

Additional dependencies

$ pip freeze
astroid==2.12.5
cffi==1.15.1
dill==0.3.5.1
isort==5.10.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
platformdirs==2.5.2
pycparser==2.21
pylint==2.15.0
tomli==2.0.1
tomlkit==0.11.4
wrapt==1.14.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Crash 💥A bug that makes pylint crashNeeds astroid updateNeeds an astroid update (probably a release too) before being mergablenamespace-package

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions