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

Aggressive import "fixing" creates syntactically invalid code #3181

Closed
luzader opened this issue Aug 11, 2022 · 9 comments
Closed

Aggressive import "fixing" creates syntactically invalid code #3181

luzader opened this issue Aug 11, 2022 · 9 comments
Assignees
Labels
bug Something isn't working fixed in next version (main) A fix has been implemented and will appear in an upcoming version

Comments

@luzader
Copy link

luzader commented Aug 11, 2022

Environment data

  • Language Server version: 2022.8.20 (pyright 888eb243)
  • OS and version: ubuntu 20.04.4
  • Python version (& distribution if applicable, e.g. Anaconda): python3.7

Code Snippet

try:
    import smbus2
except ImportError:
    # Allow smbus2 to be missing in order
    # to generate documentation
    smbus2 = None

Repro Steps

  1. Ensure 'smbus' does not exist, it is not very useful on desktop PCs and you develop embedded python, but this file needs to be importable for generating documentation with Sphinx
  2. Save the file

Expected behavior

  1. pylance should not create a syntax error where one did not exist previously
  2. pylance should not alter import statements which are inside a control structure (it doesn't "know" why the structure is there, so it should be preserved by default)
  3. pylance should not alter code in new and surprising ways (Principle of Least Astonishment)

Actual behavior

  1. pylance saves the following syntactically invalid string of text:
try:
    except ImportError:
    # Allow smbus2 to be missing in order
    # to generate documentation
    smbus2 = None
@bschnurr
Copy link
Member

bschnurr commented Aug 11, 2022

for 3 I'm assuming you have codeActionsOnSave ?

"editor.codeActionsOnSave": [
    "source.fixAll"
]

@luzader
Copy link
Author

luzader commented Aug 11, 2022

Yes which used to be safe. But the definition of 'all' seems to have changed. So I'm turning that off.

@heejaechang
Copy link
Contributor

heejaechang commented Aug 11, 2022

We recently added 2 new fix all code actions in the extension and unfortunately,

"editor.codeActionsOnSave": [
    "source.fixAll": true
]

will automatically pick up any fix all existing.

while we taking a look at how to improve our behavior, you can use this to turn it off

"source.fixAll.unusedImports": false

for other fix all, you can take a look at this

@heejaechang
Copy link
Contributor

heejaechang commented Aug 11, 2022

There is also this issue - microsoft/vscode#82718 - in vscode that is tracking editor.codeActionsOnSave intellisense issue.

Basically, editor.codeActionsOnSave currently only shows 2 predefined entries; source.fixAll and source.organizeImports. problem is source.fixAll is a catch all option. but it doesn't show all individual fixAlls exposed by all extensions. so a lot of people end up just put "source.fixAll" and hope when extensions are updated, new fix all code action added won't cause a problem.

the issue above will let each extensions expose fixAlls they provide so users can enable only ones they want rather than enable all blindly and hope for best.

For now, people need to reference documentations of all extensions they use to find out specific names of each fix all code actions and use them to configure or use catch all - "source.fixAll"

@judej judej added the bug Something isn't working label Aug 11, 2022
@graham8
Copy link

graham8 commented Aug 24, 2022

IMHO the real problem here is the syntax try; import foo; except ImportError should not be flagged for fixing if foo doesn't exist. It's perfectly valid code and very useful, in particular when remote debugging via ssh when code on the local machine can't see the modules installed on the target.

@bschnurr
Copy link
Member

the feature of removing unused imports is going to remove unused imports.

Instead of the On/Off coarse behaviour of source.fixAll.unusedImports maybe we could add a way to tag certain imports as expected to be unused.

@graham8
Copy link

graham8 commented Aug 24, 2022

add a way to tag

The tag is already there, if it's possible to have pylance recognise the import (and subsequent calls to it) is in a try clause, ie have a look around for the context.

@heejaechang heejaechang self-assigned this Aug 31, 2022
@heejaechang heejaechang added the fixed in next version (main) A fix has been implemented and will appear in an upcoming version label Sep 2, 2022
@heejaechang
Copy link
Contributor

"remove all unused imports" will only remove top level imports now. we still allow users invoking "remove unused imports" for nested imports but now we will remove leading whitespaces correctly.

thank you for reporting the issue.

@debonte
Copy link
Contributor

debonte commented Sep 8, 2022

This issue has been fixed in prerelease version 2022.9.11, which we've just released. You can find the changelog here: CHANGELOG.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working 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