From e6f8dbf4fa56c17e391db054550828718973a5ee Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 23 Feb 2021 17:05:13 -0700 Subject: [PATCH] Implemented command-line switches for pythonplatform and pythonversion. These are overridden by pyrightconfig.json settings. (#1529) Co-authored-by: Eric Traut --- docs/command-line.md | 3 ++ .../pyright-internal/src/analyzer/service.ts | 5 +++ .../src/common/commandLineOptions.ts | 8 ++++ .../src/common/configOptions.ts | 2 - packages/pyright-internal/src/pyright.ts | 41 +++++++++++++++---- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/docs/command-line.md b/docs/command-line.md index a972f1d0f..69ca5dfe5 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -12,6 +12,8 @@ Pyright can be run as either a VS Code extension or as a node-based command-line | --lib | Use library code for types when stubs are missing | | --outputjson | Output results in JSON format | | -p, --project FILE OR DIRECTORY | Use the configuration file at this location | +| --pythonplatform PLATFORM | Analyze for platform (Darwin, Linux, Windows) | +| --pythonversion VERSION | Analyze for version (3.3, 3.4, etc.) | | --stats | Print detailed performance stats | | -t, --typeshed-path DIRECTORY | Use typeshed type stubs at this location (2) | | -v, --venv-path DIRECTORY | Directory that contains virtual environments (3) | @@ -37,6 +39,7 @@ Pyright can be run as either a VS Code extension or as a node-based command-line | 1 | One or more errors reported | | 2 | Fatal error occurred with no errors or warnings reported | | 3 | Config file could not be read or parsed | +| 4 | Illegal command-line parameters specified | # JSON Output diff --git a/packages/pyright-internal/src/analyzer/service.ts b/packages/pyright-internal/src/analyzer/service.ts index 3aad00d4b..05aa59fe0 100644 --- a/packages/pyright-internal/src/analyzer/service.ts +++ b/packages/pyright-internal/src/analyzer/service.ts @@ -451,6 +451,11 @@ export class AnalyzerService { const configOptions = new ConfigOptions(projectRoot, this._typeCheckingMode); const defaultExcludes = ['**/node_modules', '**/__pycache__', '.git']; + // The pythonPlatform and pythonVersion from the command-line can be overridden + // by the config file, so initialize them upfront. + configOptions.defaultPythonPlatform = commandLineOptions.pythonPlatform; + configOptions.defaultPythonVersion = commandLineOptions.pythonVersion; + if (commandLineOptions.fileSpecs.length > 0) { commandLineOptions.fileSpecs.forEach((fileSpec) => { configOptions.include.push(getFileSpec(projectRoot, fileSpec)); diff --git a/packages/pyright-internal/src/common/commandLineOptions.ts b/packages/pyright-internal/src/common/commandLineOptions.ts index 9648ef182..030de53e4 100644 --- a/packages/pyright-internal/src/common/commandLineOptions.ts +++ b/packages/pyright-internal/src/common/commandLineOptions.ts @@ -9,6 +9,8 @@ * of the analyzer). */ +import { PythonVersion } from './pythonVersion'; + export const enum DiagnosticSeverityOverrides { Error = 'error', Warning = 'warning', @@ -58,6 +60,12 @@ export class CommandLineOptions { // Path to python interpreter. pythonPath?: string; + // Python platform indicator (darwin, linux, win32) + pythonPlatform?: 'Darwin' | 'Linux' | 'Windows'; + + // Python version string (3.3, 3.4, etc.) + pythonVersion?: PythonVersion; + // Path of typeshed stubs. typeshedPath?: string; diff --git a/packages/pyright-internal/src/common/configOptions.ts b/packages/pyright-internal/src/common/configOptions.ts index e2d6c3650..6a5ad7642 100644 --- a/packages/pyright-internal/src/common/configOptions.ts +++ b/packages/pyright-internal/src/common/configOptions.ts @@ -1199,7 +1199,6 @@ export class ConfigOptions { } // Read the default "pythonVersion". - this.defaultPythonVersion = undefined; if (configObj.pythonVersion !== undefined) { if (typeof configObj.pythonVersion === 'string') { const version = versionFromString(configObj.pythonVersion); @@ -1216,7 +1215,6 @@ export class ConfigOptions { this.ensureDefaultPythonVersion(pythonPath, console); // Read the default "pythonPlatform". - this.defaultPythonPlatform = undefined; if (configObj.pythonPlatform !== undefined) { if (typeof configObj.pythonPlatform !== 'string') { console.error(`Config "pythonPlatform" field must contain a string.`); diff --git a/packages/pyright-internal/src/pyright.ts b/packages/pyright-internal/src/pyright.ts index 0bfa74ebc..f119789a8 100644 --- a/packages/pyright-internal/src/pyright.ts +++ b/packages/pyright-internal/src/pyright.ts @@ -27,6 +27,7 @@ import { FileDiagnostics } from './common/diagnosticSink'; import { combinePaths, normalizePath } from './common/pathUtils'; import { createFromRealFileSystem, FileSystem } from './common/fileSystem'; import { isEmptyRange, Range } from './common/textRange'; +import { versionFromString } from './common/pythonVersion'; const toolName = 'pyright'; @@ -35,6 +36,7 @@ enum ExitStatus { ErrorsReported = 1, FatalError = 2, ConfigFileParseError = 3, + ParameterError = 4, } interface PyrightJsonResults { @@ -114,6 +116,8 @@ function processArgs() { { name: 'lib', type: Boolean }, { name: 'outputjson', type: Boolean }, { name: 'project', alias: 'p', type: String }, + { name: 'pythonplatform', type: String }, + { name: 'pythonversion', type: String }, { name: 'stats' }, { name: 'typeshed-path', alias: 't', type: String }, { name: 'venv-path', alias: 'v', type: String }, @@ -131,21 +135,21 @@ function processArgs() { const argErr: { name: string; optionName: string } = err; if (argErr && argErr.optionName) { console.error(`Unexpected option ${argErr.optionName}.\n${toolName} --help for usage`); - return; + process.exit(ExitStatus.ParameterError); } console.error(`Unexpected error\n${toolName} --help for usage`); - return; + process.exit(ExitStatus.ParameterError); } if (args.help !== undefined) { printUsage(); - return; + process.exit(ExitStatus.NoErrors); } if (args.version !== undefined) { printVersion(); - return; + process.exit(ExitStatus.NoErrors); } if (args.outputjson) { @@ -153,7 +157,7 @@ function processArgs() { for (const arg of incompatibleArgs) { if (args[arg] !== undefined) { console.error(`'outputjson' option cannot be used with '${arg}' option`); - return; + process.exit(ExitStatus.ParameterError); } } } @@ -163,7 +167,7 @@ function processArgs() { for (const arg of incompatibleArgs) { if (args[arg] !== undefined) { console.error(`'verifytypes' option cannot be used with '${arg}' option`); - return; + process.exit(ExitStatus.ParameterError); } } } @@ -173,7 +177,7 @@ function processArgs() { for (const arg of incompatibleArgs) { if (args[arg] !== undefined) { console.error(`'createstub' option cannot be used with '${arg}' option`); - return; + process.exit(ExitStatus.ParameterError); } } } @@ -192,6 +196,27 @@ function processArgs() { options.configFilePath = combinePaths(process.cwd(), normalizePath(args.project)); } + if (args.pythonplatform) { + if (args.pythonplatform === 'Darwin' || args.pythonplatform === 'Linux' || args.pythonplatform === 'Windows') { + options.pythonPlatform = args.pythonplatform; + } else { + console.error( + `'${args.pythonplatform}' is not a supported Python platform; specify Darwin, Linux, or Windows` + ); + process.exit(ExitStatus.ParameterError); + } + } + + if (args.pythonversion) { + const version = versionFromString(args.pythonversion); + if (version) { + options.pythonVersion = version; + } else { + console.error(`'${args.pythonversion}' is not a supported Python version; specify 3.3, 3.4, etc.`); + process.exit(ExitStatus.ParameterError); + } + } + if (args['venv-path']) { options.venvPath = combinePaths(process.cwd(), normalizePath(args['venv-path'])); } @@ -485,6 +510,8 @@ function printUsage() { ' --lib Use library code to infer types when stubs are missing\n' + ' --outputjson Output results in JSON format\n' + ' -p,--project FILE OR DIRECTORY Use the configuration file at this location\n' + + ' --pythonplatform PLATFORM Analyze for a specific platform (Darwin, Linux, Windows)\n' + + ' --pythonversion VERSION Analyze for a specific version (3.3, 3.4, etc.)\n' + ' --stats Print detailed performance stats\n' + ' -t,--typeshed-path DIRECTORY Use typeshed type stubs at this location\n' + ' -v,--venv-path DIRECTORY Directory that contains virtual environments\n' +