Skip to content

languages: Fix Pyright ignoring toolchain when LSP settings are configured - #59990

Merged
Veykril merged 2 commits into
zed-industries:mainfrom
lingyaochu:basedpyright
Jul 15, 2026
Merged

languages: Fix Pyright ignoring toolchain when LSP settings are configured#59990
Veykril merged 2 commits into
zed-industries:mainfrom
lingyaochu:basedpyright

Conversation

@lingyaochu

@lingyaochu lingyaochu commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Objective

Closes #55936
Helps #57288

There is a strange behavior for Python users when using basedpyright or pyright as the language server. As reported in #55936, when no settings are configured in lsp.basedpyright.settings, the language server correctly receives toolchain information discovered by Zed:

{
  "venvPath": ".",
  "venv": ".venv",
  "python": {
    "pythonPath": "/home/xin/works/test/test_python/.venv/bin/python",
    "defaultInterpreterPath": "/home/xin/works/test/test_python/.venv/bin/python"
  },
  "basedpyright.analysis": {
    "typeCheckingMode": "standard"
  },
  "basedpyright.disableOrganizeImports": true
}

However, when the user configures any other settings in lsp.basedpyright.settings, the toolchain information is silently lost. For example, with the following settings.json:

{
  "lsp": {
    "basedpyright": {
      "settings": {
        "analysis": {
          "diagnosticMode": "workspace",
          "typeCheckingMode": "standard",
          "inlayHints.callArgumentNames": true,
          "inlayHints.variableTypes": true,
        },
      },
    }
  }
}

The final configuration sent to the language server becomes:

{
  "analysis": {
    "diagnosticMode": "workspace",
    "typeCheckingMode": "standard",
    "inlayHints.callArgumentNames": true,
    "inlayHints.variableTypes": true
  }
}

No toolchain information is passed, so the language server ignores the user's selected Python environment and falls back to whatever virtual environment it discovers on its own. To make toolchain selection work, users currently have to manually configure virtual environment settings themselves (as noted in #57288 (comment)).

This issue was introduced in #48262, which aimed to make the virtual environment used by basedpyright/pyright configurable. The core logic is the should_insert_toolchain closure, originally designed to check whether Zed should inject the detected toolchain into the language server configuration. The intent was: if the user has already configured a virtual environment in the language server settings, skip the injection.

// If we have a detected toolchain, configure Pyright to use it
let should_insert_toolchain = || {
user_settings.as_object().is_none_or(|object| {
[
"venvPath",
"venv",
"python",
"pythonPath",
"defaultInterpreterPath",
]
.into_iter()
.any(|known_key| object.contains_key(known_key))
})
};

However, the original logic was inverted — it injected the toolchain when the user had no settings at all or when they had configured virtual environment keys. This meant that when the user had LSP settings but no virtual environment configuration, toolchain injection was skipped, as reported in #55936.

Solution

Change the logic defined in should_insert_toolchain closure, instead of insert toolchain when detected virtual environment settings, now we insert toolchain when no virtual environment settings is detected.

Testing

Tested locally. The logic change is simple, should be easy for review.

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content adheres to Zed's UI standards (UX/UI and icon guidelines)
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • Fixed toolchain selection being ignored when Pyright or Basedpyright settings are configured without specifying a Python interpreter path

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jun 27, 2026
@zed-community-bot zed-community-bot Bot added community champion Issues filed by our amazing community champions! 🫶 guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions labels Jun 27, 2026
@smitbarmase smitbarmase added the area:languages/python Python programming language support label Jun 29, 2026
@zed-industries-bot

Copy link
Copy Markdown
Contributor
Messages
📖

This PR includes links to the following GitHub Issues: #57288
If this PR aims to close an issue, please include a Closes #ISSUE line at the top of the PR body.

Generated by 🚫 dangerJS against dafcaa3

@Veykril Veykril left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@Veykril
Veykril added this pull request to the merge queue Jul 15, 2026
@Veykril Veykril self-assigned this Jul 15, 2026
Merged via the queue into zed-industries:main with commit c28e376 Jul 15, 2026
35 checks passed
@lingyaochu
lingyaochu deleted the basedpyright branch July 15, 2026 10:12
jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
…gured (zed-industries#59990)

# Objective

Closes zed-industries#55936
Helps zed-industries#57288

There is a strange behavior for Python users when using basedpyright or
pyright as the language server. As reported in zed-industries#55936, when no settings
are configured in `lsp.basedpyright.settings`, the language server
correctly receives toolchain information discovered by Zed:
```json
{
  "venvPath": ".",
  "venv": ".venv",
  "python": {
    "pythonPath": "/home/xin/works/test/test_python/.venv/bin/python",
    "defaultInterpreterPath": "/home/xin/works/test/test_python/.venv/bin/python"
  },
  "basedpyright.analysis": {
    "typeCheckingMode": "standard"
  },
  "basedpyright.disableOrganizeImports": true
}
```
However, when the user configures any other settings in
`lsp.basedpyright.settings`, the toolchain information is silently lost.
For example, with the following `settings.json`:
```jsonc
{
  "lsp": {
    "basedpyright": {
      "settings": {
        "analysis": {
          "diagnosticMode": "workspace",
          "typeCheckingMode": "standard",
          "inlayHints.callArgumentNames": true,
          "inlayHints.variableTypes": true,
        },
      },
    }
  }
}
```
The final configuration sent to the language server becomes:
```json
{
  "analysis": {
    "diagnosticMode": "workspace",
    "typeCheckingMode": "standard",
    "inlayHints.callArgumentNames": true,
    "inlayHints.variableTypes": true
  }
}
```
No toolchain information is passed, so the language server ignores the
user's selected Python environment and falls back to whatever virtual
environment it discovers on its own. To make toolchain selection work,
users currently have to manually configure virtual environment settings
themselves (as noted in
zed-industries#57288 (comment)).


This issue was introduced in zed-industries#48262, which aimed to make the virtual
environment used by basedpyright/pyright configurable. The core logic is
the `should_insert_toolchain` closure, originally designed to check
whether Zed should inject the detected toolchain into the language
server configuration. The intent was: if the user has already configured
a virtual environment in the language server settings, skip the
injection.


https://github.com/zed-industries/zed/blob/3034ad945ae10a6a61758eb07dc1b0b1ef295270/crates/languages/src/python.rs#L2115-L2128

However, the original logic was inverted — it injected the toolchain
when the user had no settings at all or when they had configured virtual
environment keys. This meant that when the user had LSP settings but no
virtual environment configuration, toolchain injection was skipped, as
reported in zed-industries#55936.


## Solution

Change the logic defined in `should_insert_toolchain` closure, instead
of insert toolchain when detected virtual environment settings, now we
insert toolchain when no virtual environment settings is detected.

## Testing

Tested locally. The logic change is simple, should be easy for review.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed toolchain selection being ignored when Pyright or Basedpyright
settings are configured without specifying a Python interpreter path
@zelenenka zelenenka removed the guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions label Aug 12, 2026
playdohface pushed a commit to playdohface/zed that referenced this pull request Aug 29, 2026
…gured (zed-industries#59990)

# Objective

Closes zed-industries#55936
Helps zed-industries#57288

There is a strange behavior for Python users when using basedpyright or
pyright as the language server. As reported in zed-industries#55936, when no settings
are configured in `lsp.basedpyright.settings`, the language server
correctly receives toolchain information discovered by Zed:
```json
{
  "venvPath": ".",
  "venv": ".venv",
  "python": {
    "pythonPath": "/home/xin/works/test/test_python/.venv/bin/python",
    "defaultInterpreterPath": "/home/xin/works/test/test_python/.venv/bin/python"
  },
  "basedpyright.analysis": {
    "typeCheckingMode": "standard"
  },
  "basedpyright.disableOrganizeImports": true
}
```
However, when the user configures any other settings in
`lsp.basedpyright.settings`, the toolchain information is silently lost.
For example, with the following `settings.json`:
```jsonc
{
  "lsp": {
    "basedpyright": {
      "settings": {
        "analysis": {
          "diagnosticMode": "workspace",
          "typeCheckingMode": "standard",
          "inlayHints.callArgumentNames": true,
          "inlayHints.variableTypes": true,
        },
      },
    }
  }
}
```
The final configuration sent to the language server becomes:
```json
{
  "analysis": {
    "diagnosticMode": "workspace",
    "typeCheckingMode": "standard",
    "inlayHints.callArgumentNames": true,
    "inlayHints.variableTypes": true
  }
}
```
No toolchain information is passed, so the language server ignores the
user's selected Python environment and falls back to whatever virtual
environment it discovers on its own. To make toolchain selection work,
users currently have to manually configure virtual environment settings
themselves (as noted in
zed-industries#57288 (comment)).


This issue was introduced in zed-industries#48262, which aimed to make the virtual
environment used by basedpyright/pyright configurable. The core logic is
the `should_insert_toolchain` closure, originally designed to check
whether Zed should inject the detected toolchain into the language
server configuration. The intent was: if the user has already configured
a virtual environment in the language server settings, skip the
injection.


https://github.com/zed-industries/zed/blob/2c346f60a76fe3f0367ef924927f50a6efdf5718/crates/languages/src/python.rs#L2115-L2128

However, the original logic was inverted — it injected the toolchain
when the user had no settings at all or when they had configured virtual
environment keys. This meant that when the user had LSP settings but no
virtual environment configuration, toolchain injection was skipped, as
reported in zed-industries#55936.


## Solution

Change the logic defined in `should_insert_toolchain` closure, instead
of insert toolchain when detected virtual environment settings, now we
insert toolchain when no virtual environment settings is detected.

## Testing

Tested locally. The logic change is simple, should be easy for review.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed toolchain selection being ignored when Pyright or Basedpyright
settings are configured without specifying a Python interpreter path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:languages/python Python programming language support cla-signed The user has signed the Contributor License Agreement community champion Issues filed by our amazing community champions! 🫶

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Basedpyright doesn't respect toolchain when experimental features are enabled

5 participants