microsoft / python-language-server

Microsoft Language Server for Python
Apache License 2.0
914 stars 133 forks source link

with-as should defer type to __enter__ #340

Open jakebailey opened 6 years ago

jakebailey commented 6 years ago

Take this example:

@contextlib.contextmanager
def noop(x):
    yield x

with noop("foobar") as s:
    print(type(s))  # prints <class 'str'>

The type of s is str, because noop yields x, which is str.

Another example (this one will raise AttributeError, but that's not important):

with contextlib.closing("foobar") as s:
    print(type(s))  # also prints <class 'str'>

In both examples, we say that s is of type ContextManager, which isn't the case. It would be better to determine the type of what comes after as via checking the context manager's __enter__ function return type: https://docs.python.org/3/reference/datamodel.html#object.__enter__

brettcannon commented 5 years ago

Is this blocking any with ... as ... block working?

with open('file.txt') as file:
    file.
jakebailey commented 5 years ago

Not from what I can tell:

image

But my original example with the contextmanager decorator doesn't work (probably because we don't handle how the decorator operates for some reason).

jakebailey commented 5 years ago

Okay, maybe open isn't the best example, because we could be "cheating" and copy from the left to the right without looking at __enter__, which would work for anything open returns, but the code should have been written and working: https://github.com/microsoft/python-language-server/blob/master/src/Analysis/Ast/Impl/Analyzer/Handlers/WithHandler.cs

brettcannon commented 5 years ago

Ah, stops working with this full snippet:

import contextlib
import typing

@contextlib.contextmanager
def cxt_manager() -> typing.Generator[str, None, None]:
    yield "hello"

# with cxt_manager() as ob:
#     ob

with open('a') as file:
    file.
MikhailArkhipov commented 5 years ago

B/c we don't specialize Generator in typing. Typing specializations are not complete, #535.