Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Traceback analysing asyncio "item = yield from queue.get()" #836

Closed
gjcarneiro opened this issue Aug 20, 2015 · 4 comments · Fixed by #1137
Closed

Traceback analysing asyncio "item = yield from queue.get()" #836

gjcarneiro opened this issue Aug 20, 2015 · 4 comments · Fixed by #1137
Labels
bug mypy got something wrong

Comments

@gjcarneiro
Copy link

Analysing:

import asyncio

@asyncio.coroutine
def test(self):
    queue = asyncio.Queue(16384)
    sample = yield from queue.get()

Result:

  File "/home/gjc/projects/mollytest/env/lib/python3.4/site-packages/mypy/checker.py", line 1693, in visit_yield_from_expr
    if result_instance.type.fullname() == "asyncio.futures.Future":
AttributeError: 'AnyType' object has no attribute 'type'
@rockneurotiko
Copy link
Contributor

That's probably because queue.get() should return a Future[T] or Future[Any], not Any.

@JukkaL JukkaL added the bug mypy got something wrong label Aug 20, 2015
@JukkaL
Copy link
Collaborator

JukkaL commented Aug 20, 2015

Thanks for reporting this! I was able to reproduce the issue.

@vitawasalreadytaken
Copy link
Contributor

I'm not familiar with mypy internals but I stepped through the analysis of this in pdb and found a couple of things:

  1. The function is dynamically typed (there's a flag in TypeChecker.dynamic_funcs) so local variables apparently default to type Any. Fix: def test_get(self) -> None:
  2. My Queue.get stub indeed has an incorrect return type as pointed out by @rockneurotiko. Fix: def get(self) -> Future[T]: ... in queues.pyi.
  3. Mypy does not infer that queue is of type asyncio.Queue from this line: queue = asyncio.Queue(16384) (it is just Any). No idea why, but this fixes it: queue = asyncio.Queue(16384) # type: asyncio.Queue.

Only after all three fixes are applied the attribute error goes away.

I'm submitting a PR with fixed Queue stubs (Queue.put also needs to return Future instead of None). By the way, analyzing

@asyncio.coroutine
def test_put(self) -> None:
    queue = asyncio.Queue(16384)
    yield from queue.put(123)

does tell me that I need a type annotation for queue, unlike the get test which fails with the above AttributeError.

q.py: note: In function "test_put":
q.py:11: error: Need type annotation for variable
q.py:12: error: Iterable function return type expected for "yield from"

Again, it works if I explicitly add # type: asyncio.Queue. This baffles me because I expected mypy to detect the type automatically.

@nierob
Copy link

nierob commented Sep 10, 2015

I think the problem is more generic:

import asyncio
import typing

@asyncio.coroutine
def foo(a):
   b = yield from a
   return b

gives me:

Traceback (most recent call last):
  File "/usr/local/bin/mypy", line 169, in <module>
    main()
  File "/usr/local/bin/mypy", line 34, in main
    type_check_only(path, module, bin_dir, options)
  File "/usr/local/bin/mypy", line 78, in type_check_only
    python_path=options.python_path)
  File "/usr/local/lib/python3.4/dist-packages/mypy/build.py", line 164, in build
    result = manager.process(UnprocessedFile(info, program_text))
  File "/usr/local/lib/python3.4/dist-packages/mypy/build.py", line 341, in process
    next.process()
  File "/usr/local/lib/python3.4/dist-packages/mypy/build.py", line 814, in process
    self.type_checker().visit_file(self.tree, self.tree.path)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 349, in visit_file
    self.accept(d)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 356, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/nodes.py", line 363, in accept
    return visitor.visit_decorator(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 1661, in visit_decorator
    e.func.accept(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/nodes.py", line 332, in accept
    return visitor.visit_func_def(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 445, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 477, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 545, in check_func_def
    self.accept_in_frame(item.body)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 369, in accept_in_frame
    answer = self.accept(node, type_context)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 356, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/nodes.py", line 504, in accept
    return visitor.visit_block(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 934, in visit_block
    self.accept(s)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 356, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/nodes.py", line 543, in accept
    return visitor.visit_assignment_stmt(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 943, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type == None)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 971, in check_assignment
    self.infer_variable_type(inferred, lvalue, self.accept(rvalue),
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 356, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/nodes.py", line 947, in accept
    return visitor.visit_yield_from_expr(self)
  File "/usr/local/lib/python3.4/dist-packages/mypy/checker.py", line 1708, in visit_yield_from_expr
    if result_instance.type.fullname() == "asyncio.futures.Future":
AttributeError: 'AnyType' object has no attribute 'type'

rockneurotiko added a commit to rockneurotiko/mypy that referenced this issue Sep 10, 2015
…xample

that @nierob reported in python#836)

Now don't crash in:

```
import asyncio

@asyncio.coroutine
def example_coro():
    q = asyncio.Queue()
    msg = yield from q.get()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(example_coro())
```

But that example is because don't infer asyncio.Queue type properly as
is appointed in python#836, so q is AnyType

and

```
import asyncio
import typing

@asyncio.coroutine
def foo(a):
   b = yield from a
   return b
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants