Pylint: Running pylint on class with duplicate bases raises `DuplicateBasesError` exception in astroid

Created on 15 Nov 2019  路  2Comments  路  Source: PyCQA/pylint

Steps to reproduce

Minimal code to reproduce the error (running pylint on a file with this contents will error out):

import asyncio
from typing import AsyncContextManager, Awaitable


class _ReproCtxManager(Awaitable[None], AsyncContextManager[None]):
    def __init__(self):
        pass

    def __await__(self):
        return self.__aenter__().__await__()

    async def __aenter__(self):
        return "test"

    async def __aexit__(self, exc_type, exc, tb):
        return None


async def main():
    async with _ReproCtxManager() as x:
        print(x)
    print(await _ReproCtxManager())

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Current behavior

I get this traceback when running pylint min_bug.py


Traceback

************* Module min_bug
min_bug.py:1:0: C0114: Missing module docstring (missing-module-docstring)
min_bug.py:5:0: E0241: Duplicate bases for class '_ReproCtxManager' (duplicate-b
ases)
min_bug.py:10:15: E1101: Instance of 'str' has no '__await__' member (no-member)

min_bug.py:15:4: C0103: Argument name "tb" doesn't conform to snake_case naming 
style (invalid-name)
min_bug.py:19:0: C0116: Missing function or method docstring (missing-function-d
ocstring)
Traceback (most recent call last):
  File "c:\python37\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python37\Scripts\pylint.exe\__main__.py", line 7, in <module>        
  File "c:\python37\lib\site-packages\pylint\__init__.py", line 23, in run_pylin
t
    PylintRun(sys.argv[1:])
  File "c:\python37\lib\site-packages\pylint\lint.py", line 1731, in __init__   
    linter.check(args)
  File "c:\python37\lib\site-packages\pylint\lint.py", line 1004, in check      
    self._do_check(files_or_modules)
  File "c:\python37\lib\site-packages\pylint\lint.py", line 1165, in _do_check  
    self.check_astroid_module(ast_node, walker, rawcheckers, tokencheckers)     
  File "c:\python37\lib\site-packages\pylint\lint.py", line 1252, in check_astro
id_module
    walker.walk(ast_node)
  File "c:\python37\lib\site-packages\pylint\utils\ast_walker.py", line 77, in w
alk
    self.walk(child)
  File "c:\python37\lib\site-packages\pylint\utils\ast_walker.py", line 77, in w
alk
    self.walk(child)
  File "c:\python37\lib\site-packages\pylint\utils\ast_walker.py", line 74, in w
alk
    callback(astroid)
  File "c:\python37\lib\site-packages\pylint\checkers\async.py", line 56, in vis
it_asyncwith
    inferred = checker_utils.safe_infer(ctx_mgr)
  File "c:\python37\lib\site-packages\pylint\checkers\utils.py", line 1084, in s
afe_infer
    value = next(inferit)
  File "c:\python37\lib\site-packages\astroid\decorators.py", line 131, in raise
_if_nothing_inferred
    yield next(generator)
  File "c:\python37\lib\site-packages\astroid\decorators.py", line 95, in wrappe
d
    res = next(generator)
  File "c:\python37\lib\site-packages\astroid\inference.py", line 227, in infer_
call
    yield from callee.infer_call_result(caller=self, context=callcontext)       
  File "c:\python37\lib\site-packages\astroid\scoped_nodes.py", line 2136, in in
fer_call_result
    if any(cls.name in EXCEPTION_BASE_CLASSES for cls in self.mro()):
  File "c:\python37\lib\site-packages\astroid\scoped_nodes.py", line 2813, in mr
o
    return self._compute_mro(context=context)
  File "c:\python37\lib\site-packages\astroid\scoped_nodes.py", line 2802, in _c
ompute_mro
    unmerged_mro = list(clean_duplicates_mro(unmerged_mro, self, context))      
  File "c:\python37\lib\site-packages\astroid\scoped_nodes.py", line 104, in cle
an_duplicates_mro
    context=context,
astroid.exceptions.DuplicateBasesError: Duplicates found in MROs (_ReproCtxManag
er), (_GenericAlias, object), (_GenericAlias, object), (_GenericAlias, _GenericA
lias) for <ClassDef._ReproCtxManager l.5 at 0x2554c696988>.

Expected behavior

I would expect no exception raised and just have the E0241/duplicate-bases warning shown without the exception. I wasn't sure if I should put this issue here on astroid repo so I'm going with this one first.

pylint --version output

pylint 2.4.4
astroid 2.3.3
Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit 
(AMD64)]

This issue also happens on latest commit of master.

bug crash

Most helpful comment

Thanks for the report!

All 2 comments

Thanks for the report!

Also let me add one thing, I am not sure if this was reported before so I'm not making issue for that as well, but I don't think this kind of code should generate duplicate-bases at all as it's valid to derive from 2 types to indicate it's both awaitable and async ctx manager.
In original code, we've just put ignore comment there (until this release which made it crash pylint) but ideally we shouldn't need to.

Was this page helpful?
0 / 5 - 0 ratings