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

contextlib.suppress results in following code being marked as unreachable #494

Closed
daviskirk opened this issue Oct 15, 2020 · 13 comments
Closed
Labels
enhancement New feature or request fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@daviskirk
Copy link

Environment data

  • Language Server version: v2020.10.1
  • OS and version: Ubuntu Linux 20.04
  • Python version: tested with python 3.7 and 3.8

Expected behaviour

Using contextlib.suppress should not result in following code being marked as unreachable.

Actual behaviour

Code following the suppress context block is marked as unreachable if there is a return statement in the block.

Code Snippet / Additional information

image

from contextlib import suppress

def test():

    class A():
        b: str

    a = A()
    with suppress(AttributeError):
        return a.b
    return "I am reachable"

Logs

User belongs to experiment group 'AlwaysDisplayTestExplorer - control'
User belongs to experiment group 'ShowPlayIcon - start'
User belongs to experiment group 'DebugAdapterFactory - experiment'
User belongs to experiment group 'PtvsdWheels37 - experiment'
User belongs to experiment group 'UseTerminalToGetActivatedEnvVars - control'
User belongs to experiment group 'LocalZMQKernel - experiment'
User belongs to experiment group 'CollectLSRequestTiming - control'
User belongs to experiment group 'CollectNodeLSRequestTiming - experiment'
User belongs to experiment group 'EnableIPyWidgets - experiment'
User belongs to experiment group 'RunByLine - experiment'
User belongs to experiment group 'CustomEditorSupport - control'
User belongs to experiment group 'pythonaacf'
Error 2020-10-15 12:57:23: Exception while attempting zmq : [Error: /snap/core/current/usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by /home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/node_modules/zeromq/prebuilds/linux-x64/electron.napi.glibc.node)
	at process.func [as dlopen] (electron/js2c/asar.js:140:31)
	at Object.Module._extensions..node (internal/modules/cjs/loader.js:1081:18)
	at Object.func [as .node] (electron/js2c/asar.js:140:31)
	at Module.load (internal/modules/cjs/loader.js:862:32)
	at Module._load (internal/modules/cjs/loader.js:774:14)
	at Function.Module._load (electron/js2c/asar.js:769:28)
	at Function.t._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1057:776)
	at Function.i._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1027:486)
	at Function.n._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1023:767)
	at Module.require (internal/modules/cjs/loader.js:899:19)
	at r (/snap/code/47/usr/share/code/resources/app/out/vs/loader.js:17:346)
	at load (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/node_modules/node-gyp-build/index.js:21:10)
	at Object.<anonymous> (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/node_modules/zeromq/lib/native.js:6:43)
	at Module.i._compile (/snap/code/47/usr/share/code/resources/app/out/vs/loader.js:17:571)
	at Object.Module._extensions..js (internal/modules/cjs/loader.js:1051:10)
	at Module.load (internal/modules/cjs/loader.js:862:32)
	at Module._load (internal/modules/cjs/loader.js:774:14)
	at Function.Module._load (electron/js2c/asar.js:769:28)
	at Function.t._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1057:776)
	at Function.i._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1027:486)
	at Function.n._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1023:767)
	at Module.require (internal/modules/cjs/loader.js:899:19)
	at r (/snap/code/47/usr/share/code/resources/app/out/vs/loader.js:17:346)
	at Object.<anonymous> (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/node_modules/zeromq/lib/index.js:3:16)
	at Module.i._compile (/snap/code/47/usr/share/code/resources/app/out/vs/loader.js:17:571)
	at Object.Module._extensions..js (internal/modules/cjs/loader.js:1051:10)
	at Module.load (internal/modules/cjs/loader.js:862:32)
	at Module._load (internal/modules/cjs/loader.js:774:14)
	at Function.Module._load (electron/js2c/asar.js:769:28)
	at Function.t._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1057:776)
	at Function.i._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1027:486)
	at Function.n._load (/snap/code/47/usr/share/code/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:1023:767)
	at Module.require (internal/modules/cjs/loader.js:899:19)
	at r (/snap/code/47/usr/share/code/resources/app/out/vs/loader.js:17:346)
	at Object.<anonymous> (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/extension.js:24:302772)
	at n (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/extension.js:1:186)
	at /home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/extension.js:56:731654
	at processTicksAndRejections (internal/process/task_queues.js:94:5)
	at async d.zmqSupportedImpl (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/extension.js:56:731621)]
> conda --version
> pyenv root
> python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> python3.6 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> python3 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> python2 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> python ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import sys;print(sys.executable)"
> conda info --json
> conda env list
> conda env list
Starting Pylance language server.
Python interpreter path: /usr/bin/python3.7
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/run_adapter.py discover pytest -- --rootdir ~/Documents/Code/vscode-bugs -s --cache-clear
cwd: ~/Documents/Code/vscode-bugs
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/run_adapter.py discover pytest -- --rootdir ~/Documents/Code/vscode-bugs -s --cache-clear
cwd: ~/Documents/Code/vscode-bugs
Error 2020-10-15 12:57:25: Failed to parse discovered Test [r [Error]: Traceback (most recent call last):
  File "/home/user/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/run_adapter.py", line 17, in <module>
    from testing_tools.adapter.__main__ import parse_args, main
  File "/home/user/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/adapter/__main__.py", line 9, in <module>
    from . import pytest, report
  File "/home/user/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/adapter/pytest/__init__.py", line 7, in <module>
    from ._discovery import discover
  File "/home/user/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/testing_tools/adapter/pytest/_discovery.py", line 8, in <module>
    import pytest
ModuleNotFoundError: No module named 'pytest'

	at ChildProcess.<anonymous> (/home/user/.vscode/extensions/ms-python.python-2020.9.114305/out/client/extension.js:9:53541)
	at Object.onceWrapper (events.js:313:26)
	at ChildProcess.emit (events.js:223:5)
	at maybeClose (internal/child_process.js:1021:16)
	at Socket.<anonymous> (internal/child_process.js:430:11)
	at Socket.emit (events.js:223:5)
	at Pipe.<anonymous> (net.js:664:12)]
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import pytest"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import pytest"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers ~/Documents/Code/vscode-bugs/test.py
cwd: ~/Documents/Code/vscode-bugs
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers ~/Documents/Code/vscode-bugs/test.py
cwd: ~/Documents/Code/vscode-bugs
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import mypy"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import mypy"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import mypy"
> /usr/bin/python3.7 ~/.vscode/extensions/ms-python.python-2020.9.114305/pythonFiles/pyvsc-run-isolated.py -c "import mypy"

Linter 'mypy' is not installed. Please install it or select another linter".
Error: Module 'mypy' not installed.
@jakebailey
Copy link
Member

@erictraut I may be misremembering, but I had thought the code flow analysis had been modified to treat context managers with an __exit__ that returns bool as swallowing exceptions. Is that not the case? I know that's the assumption that typeshed makes.

@erictraut
Copy link
Contributor

Yeah, that's not the case. That's a very large change and will have impacts on perf and (potentially) correctness in some cases. It effectively means that every with statement needs to be treated as a try/catch/finally statement in the code flow graph, which is built prior to knowing any type information. We'd be trading off what is a relatively minor annoyance (grayed-out code in some rare cases) for false positive errors in some cases.

Since this convention was never ratified in a PEP — and because of the tradeoffs it entails, I haven't implemented it.

@erictraut
Copy link
Contributor

If the grayed-out code bothers users, there is an easy workaround — use a try/catch block rather than relying on a context manager to handle exceptions.

@jakebailey
Copy link
Member

We'd be trading off what is a relatively minor annoyance (grayed-out code in some rare cases) for false positive errors in some cases.

The catch here to me is that because the code flow is "proving" that the code below is unreachable, it's not just a visual problem but impacts the code below. It was my impression that LSP features, inference, additional flow, etc, inside grayed-out code is limited because the analysis believes the code to be dead.

@erictraut
Copy link
Contributor

Yeah, there are potentially false negatives — actual errors in that code that are not reported. In general, false positives are worse than false negatives, but I agree that both are undesirable.

@jakebailey jakebailey added the enhancement New feature or request label Oct 15, 2020
@github-actions github-actions bot removed the triage label Oct 15, 2020
@jakebailey
Copy link
Member

I'll mark it as an enhancement for now; I think there's some discussion across type checkers to be had here as to what is expected from them, especially if this isn't in any specification.

@A-UNDERSCORE-D
Copy link

Adding a "Me too" here. and yes using a try/except is a workaround, but just dropping exceptions with with suppress is far cleaner.

@erictraut erictraut added the fixed in next version (main) A fix has been implemented and will appear in an upcoming version label Dec 8, 2020
@erictraut
Copy link
Contributor

This will be addressed in the next release.

@jakebailey
Copy link
Member

This issue has been fixed in version 2020.12.1, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/master/CHANGELOG.md#2020121-9-december-2020

@Cielquan
Copy link

This issue just came back for me with version 2021.1.1.

I downloaded the VSIX file for the last 5 versions and from 2020.12.1 to 2021.1.0 everything was fine. Interestingly enough I also do not have the issue with 2020.12.0.

@tq-xyy
Copy link

tq-xyy commented Jan 16, 2021

@Cielquan, I agree with you. It reappeared in version 2021.1.1, but not in version 2021.1.0.

@erictraut
Copy link
Contributor

Thanks for the bug report. You are correct, I introduced a regression in this code when fixing another bug. The nature of the regression was such that it eluded our unit tests. I've fixed the regression and improved our unit tests so this won't happen again in the future. This will be fixed in the next release. Apologies for any inconvenience.

@jakebailey
Copy link
Member

This issue has been fixed in version 2021.1.2, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202112-20-january-2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fixed in next version (main) A fix has been implemented and will appear in an upcoming version
Projects
None yet
Development

No branches or pull requests

6 participants