diff --git a/news/2 Fixes/10940.md b/news/2 Fixes/10940.md new file mode 100644 index 00000000000..fe686f05e70 --- /dev/null +++ b/news/2 Fixes/10940.md @@ -0,0 +1 @@ +Fixes problem with starting a kernel when ZMQ wasn't supported on Windows. diff --git a/src/kernels/raw/launcher/kernelEnvVarsService.node.ts b/src/kernels/raw/launcher/kernelEnvVarsService.node.ts index 17243adfb42..80de9720967 100644 --- a/src/kernels/raw/launcher/kernelEnvVarsService.node.ts +++ b/src/kernels/raw/launcher/kernelEnvVarsService.node.ts @@ -79,7 +79,16 @@ export class KernelEnvironmentVariablesService { } // Merge the env variables with that of the kernel env. interpreterEnv = interpreterEnv || {}; - const mergedVars = { ...process.env }; + let mergedVars = { ...process.env }; + + // On windows (see https://github.com/microsoft/vscode-jupyter/issues/10940) + // upper case all of the keys + if (process.platform === 'win32') { + mergedVars = {}; + Object.keys(process.env).forEach((k) => { + mergedVars[k.toUpperCase()] = process.env[k]; + }); + } kernelEnv = kernelEnv || {}; customEnvVars = customEnvVars || {}; this.envVarsService.mergeVariables(interpreterEnv, mergedVars); // interpreter vars win over proc. diff --git a/src/test/common/variables/kernelEnvVarsService.unit.test.ts b/src/test/common/variables/kernelEnvVarsService.unit.test.ts index f47c5c03137..18f2ee891a6 100644 --- a/src/test/common/variables/kernelEnvVarsService.unit.test.ts +++ b/src/test/common/variables/kernelEnvVarsService.unit.test.ts @@ -39,8 +39,9 @@ suite('Kernel Environment Variables Service', () => { sysPrefix: '0' }; let kernelSpec: IJupyterKernelSpec; + let processEnv: NodeJS.ProcessEnv; const originalEnvVars = Object.assign({}, process.env); - const processPath = Object.keys(process.env).find((k) => k.toLowerCase() == 'path'); + let processPath: string | undefined; setup(() => { kernelSpec = { name: 'kernel', @@ -64,6 +65,17 @@ suite('Kernel Environment Variables Service', () => { instance(customVariablesService), instance(configService) ); + if (process.platform === 'win32') { + // Win32 will generate upper case all the time + const entries = Object.entries(process.env); + processEnv = {}; + for (const [key, value] of entries) { + processEnv[key.toUpperCase()] = value; + } + } else { + processEnv = process.env; + } + processPath = Object.keys(processEnv).find((k) => k.toLowerCase() == 'path'); }); teardown(() => Object.assign(process.env, originalEnvVars)); @@ -91,7 +103,7 @@ suite('Kernel Environment Variables Service', () => { // Compare ignoring the PATH variable. assert.deepEqual( Object.assign(vars, { PATH: '', Path: '' }), - Object.assign({}, process.env, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) + Object.assign({}, processEnv, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) ); }); @@ -110,7 +122,7 @@ suite('Kernel Environment Variables Service', () => { // Compare ignoring the PATH variable. assert.deepEqual( Object.assign(vars, { PATH: '', Path: '' }), - Object.assign({}, process.env, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) + Object.assign({}, processEnv, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) ); }); @@ -128,7 +140,7 @@ suite('Kernel Environment Variables Service', () => { // Compare ignoring the PATH variable. assert.deepEqual( Object.assign(vars, { PATH: '', Path: '' }), - Object.assign({}, process.env, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) + Object.assign({}, processEnv, { HELLO_VAR: 'new' }, { PATH: '', Path: '' }) ); }); @@ -138,7 +150,7 @@ suite('Kernel Environment Variables Service', () => { const vars = await kernelVariablesService.getEnvironmentVariables(undefined, undefined, kernelSpec); - assert.deepEqual(vars, process.env); + assert.deepEqual(vars, processEnv); }); test('Returns process.env vars if unable to get activated vars for interpreter and no kernelspec.env', async () => { @@ -150,11 +162,11 @@ suite('Kernel Environment Variables Service', () => { // Compare ignoring the PATH variable. assert.deepEqual( Object.assign({}, vars, { PATH: '', Path: '' }), - Object.assign({}, process.env, { PATH: '', Path: '' }) + Object.assign({}, processEnv, { PATH: '', Path: '' }) ); assert.strictEqual( vars![processPath!], - `${path.dirname(interpreter.uri.fsPath)}${path.delimiter}${process.env[processPath!]}` + `${path.dirname(interpreter.uri.fsPath)}${path.delimiter}${processEnv[processPath!]}` ); }); @@ -174,6 +186,24 @@ suite('Kernel Environment Variables Service', () => { ); }); + test('Upper case is used on windows', async function () { + // See this issue as to what happens if it isn't. https://github.com/microsoft/vscode-jupyter/issues/10940 + if (process.platform !== 'win32') { + this.skip(); + } + when(envActivation.getActivatedEnvironmentVariables(anything(), anything(), anything())).thenResolve({ + path: 'foobar' + }); + when(customVariablesService.getCustomEnvironmentVariables(anything(), anything())).thenResolve({ + path: 'foobaz' + }); + + const vars = await kernelVariablesService.getEnvironmentVariables(undefined, interpreter, kernelSpec); + const keys = Object.keys(vars); + const upperCaseKeys = keys.map((key) => key.toUpperCase()); + assert.deepEqual(keys, upperCaseKeys); + }); + test('KernelSpec interpreterPath used if interpreter is undefined', async () => { when(interpreterService.getInterpreterDetails(anything())).thenResolve({ envType: EnvironmentType.Conda, diff --git a/src/test/datascience/jupyter/kernels/jupyterKernelService.unit.test.ts b/src/test/datascience/jupyter/kernels/jupyterKernelService.unit.test.ts index fa7ee077cd0..28246855c12 100644 --- a/src/test/datascience/jupyter/kernels/jupyterKernelService.unit.test.ts +++ b/src/test/datascience/jupyter/kernels/jupyterKernelService.unit.test.ts @@ -35,8 +35,10 @@ suite('DataScience - JupyterKernelService', () => { let settings: IWatchableJupyterSettings; let fs: IFileSystemNode; let testWorkspaceFolder: Uri; - // eslint-disable-next-line local-rules/dont-use-process - const pathVariable = Object.keys(process.env).find((k) => k.toLowerCase() == 'path')!; + // PATH variable is forced upper case on Windows + const pathVariable = + // eslint-disable-next-line local-rules/dont-use-process + process.platform === 'win32' ? 'PATH' : Object.keys(process.env).find((k) => k.toLowerCase() == 'path')!; // Set of kernels. Generated this by running the localKernelFinder unit test and stringifying // the results returned.