Removed support for "venv" entry in execution environments since this never really worked. Clarified in documentation that import resolution within an execution environment is not transitive.

This commit is contained in:
Eric Traut 2021-03-09 18:19:36 -08:00
parent 4bd1c58ee5
commit 09cb091fe9
9 changed files with 28 additions and 53 deletions

View File

@ -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 environments 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 environments 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 files 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",

View File

@ -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 extensions 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 extensions 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.

View File

@ -1178,17 +1178,12 @@ export class ImportResolver {
}
private _getPythonSearchPaths(execEnv: ExecutionEnvironment, importFailureInfo: string[]) {
const cacheKey = execEnv.venv ? execEnv.venv : '<default>';
const cacheKey = '<default>';
// 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)];

View File

@ -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[] = [];

View File

@ -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

View File

@ -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;

View File

@ -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.`);

View File

@ -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) {

View File

@ -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;
}