microsoft / vscode-python

Python extension for Visual Studio Code
https://aka.ms/pvsc-marketplace
MIT License
4.3k stars 1.18k forks source link

pythonREPLSmartSend does not fully close a code block with a dict or set at the end #22469

Open GriceTurrble opened 11 months ago

GriceTurrble commented 11 months ago

Type: Bug

  1. Opt into the Python experiment pythonREPLSmartSend.

  2. Define a small class with one method that returns a dict:

    class Something:
       def method():
           return {"something": "abc"}
  3. Place the cursor at the end of the first line, class Something:

  4. Press Shift-Enter

The result sent to the REPL is the full definition, but it is missing the last trailing newline:

>>> class Something:
...     def method():
...         return {"something": "abc"}
... # cursor is here!

This means chaining the next line of code can result in an indentation error, because the REPL has not fully closed this multiline entry:

>>> class Something:
...     def method():
...         return {"something": "abc"}
... a = {"something_else": "abc"}
  File "<stdin>", line 4
    a = {"something_else": "abc"}
    ^
SyntaxError: invalid syntax
>>> 

Notably, I've reproduced this when the return statement returns a dict. The issue is not reproduced in the case of return "abc" or return 123.

Multiline dicts also cause the issue:

>>> class Something:
...     def method():
...         return {
...             "abc": "def",
...             "cdf": "what",
...         }
... # cursor is here

Parentheses used for multiine strings do not:

>>> class Something:
...     def method():
...         return (
...             "abc"
...             "cdf"
...         )
... 
>>> # cursor is here

VS Code version: Code 1.84.0 (Universal) (d037ac076cee195194f93ce6fe2bdfe2969cc82d, 2023-11-01T11:30:19.406Z) OS version: Darwin arm64 22.1.0 Modes:

System Info |Item|Value| |---|---| |CPUs|Apple M1 Pro (10 x 24)| |GPU Status|2d_canvas: enabled
canvas_oop_rasterization: enabled_on
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
video_decode: enabled
video_encode: enabled
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: enabled| |Load (avg)|9, 8, 7| |Memory (System)|16.00GB (0.12GB free)| |Process Argv|| |Screen Reader|no| |VM|0%|
Extensions (53) Extension|Author (truncated)|Version ---|---|--- vscode-sqlite|ale|0.14.1 vscode-django|bat|1.14.0 markdown-mermaid|bie|1.20.0 markdown-preview-github-styles|bie|2.0.3 prettier-toml|bod|0.1.0 ruff|cha|2023.44.0 npm-intellisense|chr|1.4.5 csharpier-vscode|csh|1.3.6 vscode-eslint|dba|2.4.2 gitlens|eam|14.4.1 vsc-material-theme|Equ|33.10.5 vsc-material-theme-icons|equ|3.1.4 prettier-vscode|esb|10.1.0 vscode-reveal|evi|4.3.3 codespaces|Git|1.16.2 vscode-github-actions|git|0.26.2 vscode-pull-request-github|Git|0.76.0 cloudcode|goo|2.1.1 gc-excelviewer|Gra|4.2.58 terraform|has|2.28.2 prettier-sql-vscode|inf|1.6.0 git-graph|mhu|1.30.0 vscode-docker|ms-|1.27.0 csdevkit|ms-|1.0.14 csharp|ms-|2.9.20 dotnet-interactive-vscode|ms-|1.0.4517010 vscode-dotnet-runtime|ms-|2.0.0 vscode-kubernetes-tools|ms-|1.3.15 black-formatter|ms-|2023.4.1 isort|ms-|2023.10.1 mypy-type-checker|ms-|2023.4.0 python|ms-|2023.20.0 vscode-pylance|ms-|2023.10.50 jupyter|ms-|2023.10.1003070148 jupyter-keymap|ms-|1.1.2 jupyter-renderers|ms-|1.0.17 vscode-jupyter-cell-tags|ms-|0.1.8 vscode-jupyter-slideshow|ms-|0.1.5 remote-containers|ms-|0.321.0 remote-wsl|ms-|0.81.8 powershell|ms-|2023.8.0 vscode-github-issue-notebooks|ms-|0.0.130 vsliveshare|ms-|1.0.5892 vsliveshare-pack|ms-|0.4.0 jekyll|ost|0.1.1 postman-for-vscode|Pos|0.13.1 vscode-commons|red|0.0.6 vscode-yaml|red|1.14.0 svelte-vscode|sve|107.12.0 even-better-toml|tam|0.19.2 tilt|Tch|1.0.9 tiltfile|til|0.0.3 markdown-all-in-one|yzh|3.5.1 (5 theme extensions excluded)
GriceTurrble commented 11 months ago

Update, this is a little more universal to code blocks with some object ending with }:

>>> def method():
...     return {
...         "abc": "def",
...         "cdf": "what",
...     }
... # cursor
>>> if True:
...     a = {
...         "abc": "def",
...         "cdf": "what",
...     }
... # cursor
>>> if True:
...     a = {"abc": "def"}
... # cursor

Also works with a set:

>>> if True:
...     a = {"abc"}
... # cursor
martj42 commented 5 months ago

Seems like the same thing happens when a code block ends with a ].

For example:

def cool_numbers():
    return [42, 99]

or

def cool_numbers():
    numbers = [42, 99]
    return numbers[1]