pylance-release icon indicating copy to clipboard operation
pylance-release copied to clipboard

pyright behavior changes after adding even an empty pyrightconfig.json

Open fireattack opened this issue 1 year ago • 10 comments

Environment data

  • Pylance version: v2024.9.2
  • OS and version: Windows 10
  • Python version: 3.12.1 x64 Official

Repro Steps

  1. create a temp.py file with
import re

def test(s):
    number = re.search(r'(\d+)', s)[1]
  1. Observe there is no warning or whatsoever from pyright.
  2. Create a pyrightconfig.json file with {}.
  3. Switch back to temp.py again.

Expected behavior

The pyright checker behavior should not change (i.e. no warning).

Actual behavior

pyright now shows an error level warning of reportOptionalSubscript.

Logs

log.log


Above is just an example; when local pyrightconfig.json is enabled, it reports a lot more errors than default Pylance would (I tested with VS Code Insider with empty user settings.json).

My gut feeling is this issue is caused by that Pylance by default uses some non-standard settings which got entirely overwritten by the local pyrightconfig.json even if it's empty (instead of merging the two).

The problem is I cannot find where these settings are located.

The only thing I found is C:\Users\ikena\.vscode-insiders\extensions\ms-python.vscode-pylance-2024.9.2\dist\schemas\pyrightconfig.schema.json but it does not have anything different from pyright default (e.g. it says reportOptionalSubscript is default to error:

    "reportOptionalSubscript": {
      "$ref": "#/definitions/diagnostic",
      "title": "Controls reporting of attempts to subscript (index) a variable with Optional type",
      "default": "error"
    },

).

This makes reduplicating Pylance's default behavior (which I WANT) in a workspace where a pyrightconfig.json was introduced for other reasons (like adding exclude) very difficult.

Thanks.

fireattack avatar Sep 25 '24 04:09 fireattack

Thanks for the issue. Settings for pylance and pyright are really confusing.

Defaults for pylance are described here:

https://github.com/microsoft/pylance-release?tab=readme-ov-file#settings-and-customization

You're correct, specifying an empty pyrightconfig.json actually sets a number of settings to their default for a pyrightconfig.json. Those are described here: https://microsoft.github.io/pyright/#/configuration?id=pyright-configuration

The reason why an empty pyrightconfig.json overrides everything is described here: https://github.com/microsoft/pylance-release/wiki/Settings.json-overridden-by-Pyrightconfig.json-or-Pyproject.toml

If you want to duplicate the defaults for pylance in your pyrightconfig.json, you'd have something like so:

{
    "typeCheckingMode": "off",
    "reportShadowedImports": "warning",
}

While also leaving your settings.json blank. The pyrightconfig.json only overrides pyright settable settings in the settings.json so most of the defaults would still apply. typeCheckingMode and reportShadowedImports are I believe the only settings that are defaulted differently.

I think we need to have a better explanation for all of this somewhere.

rchiodo avatar Sep 25 '24 16:09 rchiodo

ya, we should write that pyright and pylance have different defaults for some settings and having pyrightconfig.json/pyproject.toml (even empty one) will change which default we will use and links to each defaults.

heejaechang avatar Sep 25 '24 17:09 heejaechang

(just wanted to note that this was also discussed in https://github.com/microsoft/pylance-release/issues/6373) Since this behavior seems to be confusing lots of people, it would be great to consider reverting the behavior rather than just relying on documentation of this footgun.

Hnasar avatar Sep 25 '24 17:09 Hnasar

Strong 👍 to making the behavior more predictable and consistent with the way that configuration files usually work. I wasted nearly an hour tracking down what was happening because it is so unexpected and because it is embedded in VS code (introducing some uncertainty in where the problem lies).

My use case is that I want to exclude certain files from Pylance analysis on a per-project basis. That seems like very common thing to do, using something like:

{
    "ignore": [
        "**/*.ipynb",
    ]
}

It is COMPLETELY UNEXPECTED that this innocuous configuration would override any unrelated python.analysis settings I have in VS code. In particular it seems to be enabling basic or strict type checking, which is not what I want.

taldcroft avatar Sep 26 '24 13:09 taldcroft

Thanks for all the valuable discussion. Especially the default values pylance uses: which solves my immediate problem by adding them to my pyrightconfig.json. I think this probably should be surfaced more prominently somewhere in the official doc.

I don't mind pyrightconfig.json having highest priority by default in principle from a project collaboration perspective.

But some options around it, and even better, providing a way to merge the two at option-level (instead of overwriting entirely) would be great.

fireattack avatar Sep 26 '24 13:09 fireattack

I don't mind pyrightconfig.json having highest priority by default in principle from a project collaboration perspective.

I do mind. In monorepo environments we prefer having project-level overrides of global defaults. Having pyrightconfig.json override workspace (project-level) configured settings is a pretty severe regression for us in terms of development environment.

BaconPancakes avatar Oct 10 '24 02:10 BaconPancakes

The fundamental problem for me is that the overrides are not explicit and do not behave like typical configuration precedence.

Think about defaults, pyrightconfig and vscode as Python dictionaries, where pyrightconfig is the dict representation of pyrightconfig.json if it exists. The following would be fine and predictable for me:

# pyrightconfig.json exists:
options = defaults | vscode (user) | vscode (workspace) | pyrightconfig

# pyrightconfig.json does not exist
options = defaults | vscode (user) | vscode (workspace)

The problem is that for the case where pyrightconfig.json exists, it actually does this:

options = defaults | vscode (user) | vscode (workspace) | nonobvious_defaults | pyrightconfig

This change in the precedence is what is confusing to users. Documentation is not really the answer.

For my own work, I have been forced to stop using pyrightconfig.json entirely because of this behavior. This is unfortunate.

taldcroft avatar Oct 10 '24 14:10 taldcroft

One remark is that we often use pre-commit to reduce inconsistency between checks at the developer level and what happens in CI.

For me this is preferable to the current situation where pyrightconfig.json is essentially not usable because it imposes nonobvious_defaults that are unacceptable in my dev environment.

taldcroft avatar Oct 10 '24 14:10 taldcroft

Defaults for pyrightconfig.json are documented here: https://microsoft.github.io/pyright/#/configuration?id=environment-options, although the default are not very clearly stated.

rchiodo avatar Oct 10 '24 16:10 rchiodo

Defaults for pyrightconfig.json are documented here: https://microsoft.github.io/pyright/#/configuration?id=environment-options, although the default are not very clearly stated.

Apologies for the imprecise wording, I've updated the both comments with nonobvious_defaults.

taldcroft avatar Oct 10 '24 18:10 taldcroft

(just wanted to note that this was also discussed in #6373) Since this behavior seems to be confusing lots of people, it would be great to consider reverting the behavior rather than just relying on documentation of this footgun.

is there any movement on switching back to the old behavior? I'd like to point to the discussion in https://github.com/microsoft/pylance-release/issues/6373#issuecomment-2344982380 with @Hnasar. quoting myself:

we configure black, ruff, mypy, pylint, flake8 and non-python tools (eslint, tsc, etc.) globally and then the editor picks up the settings and layers any editor-specific changes on top. we can turn off black formatting in vsc and turn on ruff formatting without deleting the black config; we can turn off flake8 in vsc and use ruff lint without removing the flake8 config; but the only way to turn off pyright in vsc is to remove the pyright config

raylu avatar Jan 30 '25 20:01 raylu

could you point me at the commit/version pylance fixed this in?

raylu avatar Mar 29 '25 06:03 raylu