diff --git a/news/2 Fixes/4306.md b/news/2 Fixes/4306.md new file mode 100644 index 000000000000..9fcd5439f8bb --- /dev/null +++ b/news/2 Fixes/4306.md @@ -0,0 +1 @@ +Allow Interactive Window to run commands as both `-m jupyter command` and as `-m command` \ No newline at end of file diff --git a/src/client/datascience/jupyter/jupyterExecution.ts b/src/client/datascience/jupyter/jupyterExecution.ts index f46dcc2356e8..5f32620f7d4c 100644 --- a/src/client/datascience/jupyter/jupyterExecution.ts +++ b/src/client/datascience/jupyter/jupyterExecution.ts @@ -35,6 +35,12 @@ import { import { JupyterConnection, JupyterServerInfo } from './jupyterConnection'; import { JupyterKernelSpec } from './jupyterKernelSpec'; +enum ModuleExistsResult { + NotFound, + FoundJupyter, + Found +} + export class JupyterExecutionBase implements IJupyterExecution { private processServicePromise: Promise; @@ -619,11 +625,14 @@ export class JupyterExecutionBase implements IJupyterExecution { private findInterpreterCommand = async (command: string, interpreter: PythonInterpreter, cancelToken?: CancellationToken): Promise => { // If the module is found on this interpreter, then we found it. - if (interpreter && await this.doesModuleExist(command, interpreter, cancelToken) && !Cancellation.isCanceled(cancelToken)) { + if (interpreter && !Cancellation.isCanceled(cancelToken)) { + const exists = await this.doesModuleExist(command, interpreter, cancelToken); - // Our command args are different based on the command. ipykernel is not a jupyter command - const args = command === JupyterCommands.KernelCreateCommand ? ['-m', command] : ['-m', 'jupyter', command]; - return this.commandFactory.createInterpreterCommand(args, interpreter); + if (exists === ModuleExistsResult.FoundJupyter) { + return this.commandFactory.createInterpreterCommand(['-m', 'jupyter', command], interpreter); + } else if (exists === ModuleExistsResult.Found) { + return this.commandFactory.createInterpreterCommand(['-m', command], interpreter); + } } return undefined; @@ -742,23 +751,41 @@ export class JupyterExecutionBase implements IJupyterExecution { return this.commands.hasOwnProperty(command) ? this.commands[command] : undefined; } - private doesModuleExist = async (module: string, interpreter: PythonInterpreter, cancelToken?: CancellationToken): Promise => { + private doesModuleExist = async (moduleName: string, interpreter: PythonInterpreter, cancelToken?: CancellationToken): Promise => { if (interpreter && interpreter !== null) { const newOptions: SpawnOptions = { throwOnStdErr: true, encoding: 'utf8', token: cancelToken }; const pythonService = await this.executionFactory.createActivatedEnvironment({ resource: undefined, interpreter, allowEnvironmentFetchExceptions: true }); - try { - // Special case for ipykernel - const actualModule = module === JupyterCommands.KernelCreateCommand ? module : 'jupyter'; - const args = module === JupyterCommands.KernelCreateCommand ? ['--version'] : [module, '--version']; - const result = await pythonService.execModule(actualModule, args, newOptions); - return !result.stderr; + // For commands not 'ipykernel' first try them as jupyter commands + if (moduleName !== JupyterCommands.KernelCreateCommand) { + try { + const result = await pythonService.execModule('jupyter', [moduleName, '--version'], newOptions); + if (!result.stderr) { + return ModuleExistsResult.FoundJupyter; + } else { + this.logger.logWarning(`${result.stderr} for ${interpreter.path}`); + } + } catch (err) { + this.logger.logWarning(`${err} for ${interpreter.path}`); + } + } + + // After trying first as "-m jupyter --version" then try "-m --version" as this works in some cases + // for example if not running in an activated environment without script on the path + try { + const result = await pythonService.execModule(moduleName, ['--version'], newOptions); + if (!result.stderr) { + return ModuleExistsResult.Found; + } else { + this.logger.logWarning(`${result.stderr} for ${interpreter.path}`); + return ModuleExistsResult.NotFound; + } } catch (err) { this.logger.logWarning(`${err} for ${interpreter.path}`); - return false; + return ModuleExistsResult.NotFound; } } else { - return false; + return ModuleExistsResult.NotFound; } }