nelfin / pylint-protobuf

A plugin for making Pylint aware of the fields of protobuf-generated classes
MIT License
29 stars 12 forks source link

pylint-protobuf raises AttributeError if protobuf extension is unavailable (Windows, Python 3.8+) #50

Closed dsandbrink closed 3 years ago

dsandbrink commented 3 years ago

Hi,

currently the protobuf Python package does not contain the C++ extension when installing on Windows for Python 3.8+, see ImportError: cannot import name '_message' from 'google.protobuf.pyext' on windows and python3.8 #7765.

This causes an AttributeError when trying to run pylint with the pylint-protobuf plugin installed:

>>> python -m pylint src tests
Traceback (most recent call last):
  File "C:\Git\sampleproject\CPython.3.8.7\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Git\sampleproject\CPython.3.8.7\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint\__main__.py", line 9, in <module>
    pylint.run_pylint()
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint\__init__.py", line 24, in run_pylint
    PylintRun(sys.argv[1:])
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint\lint\run.py", line 330, in __init__
    linter.load_plugin_modules(plugins)
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint\lint\pylinter.py", line 503, in load_plugin_modules
    module = astroid.modutils.load_module_from_name(modname)
  File "C:\Git\sampleproject\venv\lib\site-packages\astroid\modutils.py", line 212, in load_module_from_name
    return importlib.import_module(dotted_name)
  File "C:\Git\sampleproject\CPython.3.8.7\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint_protobuf\__init__.py", line 8, in <module>
    from .transform import transform_module, is_some_protobuf_module, to_pytype, is_composite, is_repeated, is_oneof
  File "C:\Git\sampleproject\venv\lib\site-packages\pylint_protobuf\transform.py", line 101, in <module>
    FieldDescriptor.TYPE_BOOL: bool,
AttributeError: type object 'FieldDescriptor' has no attribute 'TYPE_BOOL'

The root cause is at the top of transport.py, where some types are imported from the extention:

    from google.protobuf.pyext._message import (
        Descriptor,
        EnumDescriptor,
        FieldDescriptor,
    )

I think this should fall back to the pure Python definition of those classes if the _message module is unavailable for any reason:

    from google.protobuf.descriptor import (
nelfin commented 3 years ago

Hi @dsandbrink, thanks for the report. Yeah, as it currently stands, pylint-protobuf does rely on implementation details of google.protobuf. I'll see if the pure-Python definitions work for all cases, but I don't have access to a Windows environment at the moment so I'll need a hand testing that.

nelfin commented 3 years ago

Give that fix a try with pip install git+https://github.com/nelfin/pylint-protobuf@8273133719b86731f28f3c0879d7739377affc92

dsandbrink commented 3 years ago

Hi @nelfin , thanks for the quick fix! I tested it on Windows with both Python 3.7 and Python 3.8 and on Ubuntu 20.04 with Python 3.8 successfully.

Note that when using Python 3.8 on Windows (we just switched our code base to Python 3.8) I get some strange false positive warnings like

E5903: Field "Project.create_time" is of type 'Timestamp' and value 'Timestamp()' will raise TypeError at runtime (protobuf-type-error)

I am pretty sure that this is unrelated to your fix, because these warnings do not show when using Linux or Python 3.7. I'll try to create a minimal example to check if I can reproduce this and will create a separate issue (if I should find one ;) ).

emmanuelajaero commented 1 year ago

for me I downgraded protobuf pip install protobuf==3.19.6