pylint-dev / pylint

It's not just a linter that annoys you!
https://pylint.readthedocs.io/en/latest/
GNU General Public License v2.0
5.32k stars 1.14k forks source link

Assigning futures from coroutines produces "assignment-from-no-return" #1715

Closed butla closed 6 years ago

butla commented 7 years ago

Steps to reproduce

  1. Save the file below as bla.py
    
    """
    This is a test showing Pylint falsely detecting assignment-from-no-return.
    """

import asyncio

async def bla1(): """I'm just the first sample couroutine.""" print("I'm the first coroutine")

async def bla2(): """I'm just the second sample couroutine.""" print("I'm the second coroutine")

async def combining_coroutine1(): """I'm using coroutines by immediately awaiting for the futures they return and Pylint doesn't complain.""" await bla1() await bla2()

async def combining_coroutine2(): """I'm using coroutines by first creating futures from them, and then awaiting for them all at once. That way I can run the coroutines concurrently, not sequentially. Running them sequentially prevents any possible speedup when doing IO.""" future1 = bla1() future2 = bla2() print("I have the futures, now I'll run them") await asyncio.gather(future1, future2)

def do_stuff(): """I'm running the whole test.""" loop = asyncio.get_event_loop() loop.run_until_complete(combining_coroutine1()) loop.run_until_complete(combining_coroutine2())

if name == 'main': do_stuff()

2. Run `$ pylint bla.py`

### Current behavior
Lines `future1 = bla1()` and `future2 = bla2()` raise `assignment-from-no-return` error.

### Expected behavior
Those lines should pass just fine.

### pylint --version output

No config file found, using default configuration pylint 1.7.4, astroid 1.5.3 Python 3.6.2 (default, Jul 17 2017, 23:14:31) [GCC 5.4.0 20160609]

pzelnip commented 6 years ago

I also get this with a simpler example:

async def simple_coro():
    await asyncio.sleep(0.1)
    print("awake!")

loop.asyncio.get_event_loop()
coro1 = simple_coro()
coro2 = simple_coro()
loop.run_until_complete(asyncio.gather(coro1, coro2))
loop.close()

the assignment to coro1 and coro2 both trigger E1111 "Assigning to function call which doesn't return". If we modify simple_coro to explicitly return None, then we get E1128: Assigning to function call which only returns None