diff --git a/docs/configuration.md b/docs/configuration.md index 310e7e9a2..2562b7379 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -18,9 +18,9 @@ Relative paths specified within the config file are relative to the config file **stubPath** [path, optional]: Path to a directory that contains custom type stubs. Each package's type stub file(s) are expected to be in its own subdirectory. The default value of this setting is "./typings". (typingsPath is now deprecated) -**venvPath** [path, optional]: Path to a directory containing one or more subdirectories, each of which contains a virtual environment. Each execution environment (see below for details) can refer to a different virtual environment. When used in conjunction with a **venv** setting (see below), pyright will search for imports in the virtual environment’s site-packages directory rather than the paths specified by the default Python interpreter. +**venvPath** [path, optional]: Path to a directory containing one or more subdirectories, each of which contains a virtual environment. When used in conjunction with a **venv** setting (see below), pyright will search for imports in the virtual environment’s site-packages directory rather than the paths specified by the default Python interpreter. If you are working on a project with other developers, it is best not to specify this setting in the config file, since this path will typically differ for each developer. Instead, it can be specified on the command line or in a per-user setting. -**venv** [string, optional]: Used in conjunction with the venvPath, specifies the virtual environment to use. Individual execution environments may override this setting. +**venv** [string, optional]: Used in conjunction with the venvPath, specifies the virtual environment to use. **verboseOutput** [boolean]: Specifies whether output logs should be verbose. This is useful when diagnosing certain problems like import resolution issues. @@ -150,9 +150,7 @@ The following settings can be specified for each execution environment. **root** [string, required]: Root path for the code that will execute within this execution environment. -**extraPaths** [array of strings, optional]: Additional search paths (in addition to the root path) that will be used when searching for packages. At runtime, these will be specified in the PYTHONPATH environment variable. - -**venv** [string, optional]: The virtual environment to use for this execution environment. If not specified, the global `venv` setting is used instead. +**extraPaths** [array of strings, optional]: Additional search paths (in addition to the root path) that will be used when searching for modules imported by files within this execution environment. Note that each file’s execution environment mapping is independent, so if file A is in one execution environment ane imports a second file B within a second execution environment, any imports from B will use the extraPaths in the second execution environment. **pythonVersion** [string, optional]: The version of Python used for this execution environment. If not specified, the global `pythonVersion` setting is used instead. @@ -201,8 +199,7 @@ The following is an example of a pyright config file: "pythonVersion": "3.0", "extraPaths": [ "src/backend" - ], - "venv": "venv_bar" + ] }, { "root": "src/tests", diff --git a/docs/import-resolution.md b/docs/import-resolution.md index fd3fdaf15..d65014cd0 100644 --- a/docs/import-resolution.md +++ b/docs/import-resolution.md @@ -34,13 +34,11 @@ Pyright does not require a Python environment to be configured if all imports ca Pyright uses the following mechanisms (in priority order) to determine which Python environment to use: -1. If a `venv` name is specified for the execution environment along with a `python.venvPath` setting (or a `--venv-path` command-line argument), it appends the venv name to the specified venv path. +1. If a `venv` name is specified along with a `python.venvPath` setting (or a `--venv-path` command-line argument), it appends the venv name to the specified venv path. -2. If no `venv` name is specified for the execution environment but a `defaultVenv` name is specified at the top level of the config file, use that venv name instead. +2. If no `venv` is specified in the config file, use the `python.pythonPath` setting. This setting is defined by the VS Code Python extension and can be configured using the Python extension’s environment picker interface. More recent versions of the Python extension no longer store the selected Python environment in the `python.pythonPath` setting and instead use a storage mechanism that is private to the extension. Pyright is able to access this through an API exposed by the Python extension. -3. If no `venv` or `defaultVenv` is specified in the config file, use the `python.pythonPath` setting. This setting is defined by the VS Code Python extension and can be configured using the Python extension’s environment picker interface. More recent versions of the Python extension no longer store the selected Python environment in the `python.pythonPath` setting and instead use a storage mechanism that is private to the extension. Pyright is able to access this through an API exposed by the Python extension. - -4. As a fallback, use the default Python environment (i.e. the one that is invoked when typing `python` in the shell). +3. As a fallback, use the default Python environment (i.e. the one that is invoked when typing `python` in the shell). ## Debugging Import Resolution Problems The import resolution mechanisms in Python are complicated, and Pyright offers many configuration options. If you are encountering problems with import resolution, Pyright provides additional logging that may help you identify the cause. To enable verbose logging, pass `--verbose` as a command-line argument or add the following entry to the config file `"verboseOutput": true`. If you are using the Pyright VS Code extension, the additional logging will appear in the Output tab (select “Pyright” from the menu). Please include this verbose logging when reporting import resolution bugs. diff --git a/packages/pyright-internal/src/analyzer/importResolver.ts b/packages/pyright-internal/src/analyzer/importResolver.ts index b5adc4bfb..37bea03c0 100644 --- a/packages/pyright-internal/src/analyzer/importResolver.ts +++ b/packages/pyright-internal/src/analyzer/importResolver.ts @@ -1178,17 +1178,12 @@ export class ImportResolver { } private _getPythonSearchPaths(execEnv: ExecutionEnvironment, importFailureInfo: string[]) { - const cacheKey = execEnv.venv ? execEnv.venv : ''; + const cacheKey = ''; // Find the site packages for the configured virtual environment. if (!this._cachedPythonSearchPaths.has(cacheKey)) { let paths = - PythonPathUtils.findPythonSearchPaths( - this.fileSystem, - this._configOptions, - execEnv.venv, - importFailureInfo - ) || []; + PythonPathUtils.findPythonSearchPaths(this.fileSystem, this._configOptions, importFailureInfo) || []; // Remove duplicates (yes, it happens). paths = [...new Set(paths)]; diff --git a/packages/pyright-internal/src/analyzer/pythonPathUtils.ts b/packages/pyright-internal/src/analyzer/pythonPathUtils.ts index 7ab062f00..ed385a3b2 100644 --- a/packages/pyright-internal/src/analyzer/pythonPathUtils.ts +++ b/packages/pyright-internal/src/analyzer/pythonPathUtils.ts @@ -72,15 +72,14 @@ export function getTypeshedSubdirectory(typeshedPath: string, isStdLib: boolean) export function findPythonSearchPaths( fs: FileSystem, configOptions: ConfigOptions, - venv: string | undefined, importFailureInfo: string[], includeWatchPathsOnly?: boolean | undefined, workspaceRoot?: string | undefined ): string[] | undefined { importFailureInfo.push('Finding python search paths'); - if (configOptions.venvPath !== undefined && (venv !== undefined || configOptions.defaultVenv)) { - const venvDir = venv !== undefined ? venv : configOptions.defaultVenv; + if (configOptions.venvPath !== undefined && configOptions.venv) { + const venvDir = configOptions.venv; const venvPath = combinePaths(configOptions.venvPath, venvDir); const foundPaths: string[] = []; diff --git a/packages/pyright-internal/src/analyzer/service.ts b/packages/pyright-internal/src/analyzer/service.ts index 334246683..30ed7fa0e 100644 --- a/packages/pyright-internal/src/analyzer/service.ts +++ b/packages/pyright-internal/src/analyzer/service.ts @@ -606,24 +606,23 @@ export class AnalyzerService { this._console.error(`venvPath ${configOptions.venvPath} is not a valid directory.`); } - // venvPath without defaultVenv means it won't do anything while resolveImport. - // so first, try to set defaultVenv from existing configOption if it is null. if both are null, + // venvPath without venv means it won't do anything while resolveImport. + // so first, try to set venv from existing configOption if it is null. if both are null, // then, resolveImport won't consider venv - configOptions.defaultVenv = configOptions.defaultVenv ?? this._configOptions.defaultVenv; - if (configOptions.defaultVenv) { - const fullVenvPath = combinePaths(configOptions.venvPath, configOptions.defaultVenv); + configOptions.venv = configOptions.venv ?? this._configOptions.venv; + if (configOptions.venv) { + const fullVenvPath = combinePaths(configOptions.venvPath, configOptions.venv); if (!this._fs.existsSync(fullVenvPath) || !isDirectory(this._fs, fullVenvPath)) { this._console.error( - `venv ${configOptions.defaultVenv} subdirectory not found ` + - `in venv path ${configOptions.venvPath}.` + `venv ${configOptions.venv} subdirectory not found in venv path ${configOptions.venvPath}.` ); } else { const importFailureInfo: string[] = []; - if (findPythonSearchPaths(this._fs, configOptions, undefined, importFailureInfo) === undefined) { + if (findPythonSearchPaths(this._fs, configOptions, importFailureInfo) === undefined) { this._console.error( `site-packages directory cannot be located for venvPath ` + - `${configOptions.venvPath} and venv ${configOptions.defaultVenv}.` + `${configOptions.venvPath} and venv ${configOptions.venv}.` ); if (configOptions.verboseOutput) { @@ -667,7 +666,7 @@ export class AnalyzerService { } // Is there a reference to a venv? If so, there needs to be a valid venvPath. - if (configOptions.defaultVenv || configOptions.executionEnvironments.find((e) => !!e.venv)) { + if (configOptions.venv) { if (!configOptions.venvPath) { this._console.warn(`venvPath not specified, so venv settings will be ignored.`); } @@ -1137,7 +1136,6 @@ export class AnalyzerService { const watchList = findPythonSearchPaths( this._fs, this._backgroundAnalysisProgram.configOptions, - undefined, importFailureInfo, true, this._executionRootPath diff --git a/packages/pyright-internal/src/backgroundThreadBase.ts b/packages/pyright-internal/src/backgroundThreadBase.ts index f3bd0f1c6..26da5d820 100644 --- a/packages/pyright-internal/src/backgroundThreadBase.ts +++ b/packages/pyright-internal/src/backgroundThreadBase.ts @@ -68,7 +68,7 @@ export function createConfigOptionsFrom(jsonObject: any): ConfigOptions { configOptions.useLibraryCodeForTypes = jsonObject.useLibraryCodeForTypes; configOptions.internalTestMode = jsonObject.internalTestMode; configOptions.venvPath = jsonObject.venvPath; - configOptions.defaultVenv = jsonObject.defaultVenv; + configOptions.venv = jsonObject.venv; configOptions.defaultPythonVersion = jsonObject.defaultPythonVersion; configOptions.defaultPythonPlatform = jsonObject.defaultPythonPlatform; configOptions.diagnosticRuleSet = jsonObject.diagnosticRuleSet; diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index 2fc848f01..cd7f3750d 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -57,9 +57,6 @@ export class ExecutionEnvironment { // Default to no extra paths. extraPaths: string[] = []; - - // Name of virtual environment to use. - venv?: string; } export type DiagnosticLevel = 'none' | 'information' | 'warning' | 'error'; @@ -610,8 +607,8 @@ export class ConfigOptions { // third-party modules. venvPath?: string; - // Default venv environment. Can be overridden by executionEnvironment. - defaultVenv?: string; + // Default venv environment. + venv?: string; // Default pythonVersion. Can be overridden by executionEnvironment. defaultPythonVersion?: PythonVersion; @@ -1188,13 +1185,13 @@ export class ConfigOptions { } } - // Read the default "venv". - this.defaultVenv = undefined; + // Read the "venv" name. + this.venv = undefined; if (configObj.venv !== undefined) { if (typeof configObj.venv !== 'string') { console.error(`Config "venv" field must contain a string.`); } else { - this.defaultVenv = configObj.venv; + this.venv = configObj.venv; } } @@ -1464,15 +1461,6 @@ export class ConfigOptions { } } - // Validate the venv. - if (envObj.venv) { - if (typeof envObj.venv === 'string') { - newExecEnv.venv = envObj.venv; - } else { - console.error(`Config executionEnvironments index ${index} venv must be a string.`); - } - } - return newExecEnv; } catch { console.error(`Config executionEnvironments index ${index} is not accessible.`); diff --git a/packages/pyright-internal/src/tests/harness/fourslash/testState.ts b/packages/pyright-internal/src/tests/harness/fourslash/testState.ts index d4bd6e3a9..f825cbf42 100644 --- a/packages/pyright-internal/src/tests/harness/fourslash/testState.ts +++ b/packages/pyright-internal/src/tests/harness/fourslash/testState.ts @@ -1213,7 +1213,7 @@ export class TestState { // run test in venv mode under root so that // under test we can point to local lib folder configOptions.venvPath = vfs.MODULE_PATH; - configOptions.defaultVenv = vfs.MODULE_PATH; + configOptions.venv = vfs.MODULE_PATH; // make sure we set typing path if (configOptions.stubPath === undefined) { diff --git a/packages/pyright-internal/src/tests/importResolver.test.ts b/packages/pyright-internal/src/tests/importResolver.test.ts index 7930cf911..98748540b 100644 --- a/packages/pyright-internal/src/tests/importResolver.test.ts +++ b/packages/pyright-internal/src/tests/importResolver.test.ts @@ -325,7 +325,7 @@ function getImportResult( function getConfigOption(fs: PyrightFileSystem) { const configOptions = new ConfigOptions(normalizeSlashes('/')); configOptions.venvPath = fs.getModulePath(); - configOptions.defaultVenv = fs.getModulePath(); + configOptions.venv = fs.getModulePath(); return configOptions; }