From ee613153ab7f5a41c3ea5e210786cd67c4ecd80e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 15 May 2018 17:27:33 -0400 Subject: [PATCH 1/2] Ensure resource is passed into getTerminalService method --- news/2 Fixes/1476.md | 1 + .../common/installer/moduleInstaller.ts | 2 +- .../common/installer/pipEnvInstaller.ts | 4 +- .../common/installer/productInstaller.ts | 2 +- src/test/common/moduleInstaller.test.ts | 444 +++++++++--------- 5 files changed, 235 insertions(+), 218 deletions(-) create mode 100644 news/2 Fixes/1476.md diff --git a/news/2 Fixes/1476.md b/news/2 Fixes/1476.md new file mode 100644 index 000000000000..071cddec5a2f --- /dev/null +++ b/news/2 Fixes/1476.md @@ -0,0 +1 @@ +Ensure python environment activation works as expected within a multi-root workspace. diff --git a/src/client/common/installer/moduleInstaller.ts b/src/client/common/installer/moduleInstaller.ts index f69401faa9ff..5fe19952bba9 100644 --- a/src/client/common/installer/moduleInstaller.ts +++ b/src/client/common/installer/moduleInstaller.ts @@ -21,7 +21,7 @@ export abstract class ModuleInstaller { constructor(protected serviceContainer: IServiceContainer) { } public async installModule(name: string, resource?: vscode.Uri): Promise { const executionInfo = await this.getExecutionInfo(name, resource); - const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(); + const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(resource); if (executionInfo.moduleName) { const settings = PythonSettings.getInstance(resource); diff --git a/src/client/common/installer/pipEnvInstaller.ts b/src/client/common/installer/pipEnvInstaller.ts index 23ac3e52ab95..4b01df9fd3e2 100644 --- a/src/client/common/installer/pipEnvInstaller.ts +++ b/src/client/common/installer/pipEnvInstaller.ts @@ -25,8 +25,8 @@ export class PipEnvInstaller implements IModuleInstaller { this.pipenv = this.serviceContainer.get(IInterpreterLocatorService, PIPENV_SERVICE); } - public installModule(name: string): Promise { - const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(); + public installModule(name: string, resource?: Uri): Promise { + const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(resource); return terminalService.sendCommand(pipenvName, ['install', name, '--dev']); } diff --git a/src/client/common/installer/productInstaller.ts b/src/client/common/installer/productInstaller.ts index 6c56fdc4da7d..9659ef0debad 100644 --- a/src/client/common/installer/productInstaller.ts +++ b/src/client/common/installer/productInstaller.ts @@ -108,7 +108,7 @@ class CTagsInstaller extends BaseInstaller { this.outputChannel.appendLine('Option 3: Extract to any folder and define that path in the python.workspaceSymbols.ctagsPath setting of your user settings file (settings.json).'); this.outputChannel.show(); } else { - const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(); + const terminalService = this.serviceContainer.get(ITerminalServiceFactory).getTerminalService(resource); const logger = this.serviceContainer.get(ILogger); terminalService.sendCommand(CTagsInsllationScript, []) .catch(logger.logError.bind(logger, `Failed to install ctags. Script sent '${CTagsInsllationScript}'.`)); diff --git a/src/test/common/moduleInstaller.test.ts b/src/test/common/moduleInstaller.test.ts index 3ee2379fcc7e..27b57e2ed519 100644 --- a/src/test/common/moduleInstaller.test.ts +++ b/src/test/common/moduleInstaller.test.ts @@ -1,3 +1,5 @@ +// tslint:disable:max-func-body-length + import { expect } from 'chai'; import * as path from 'path'; import * as TypeMoq from 'typemoq'; @@ -40,244 +42,258 @@ const info: PythonInterpreter = { sysVersion: '' }; -// tslint:disable-next-line:max-func-body-length -suite('Module Installer', () => { - let ioc: UnitTestIocContainer; - let mockTerminalService: TypeMoq.IMock; - let condaService: TypeMoq.IMock; - let interpreterService: TypeMoq.IMock; - - const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test')); - suiteSetup(initializeTest); - setup(async () => { - initializeDI(); - await initializeTest(); - await resetSettings(); - }); - suiteTeardown(async () => { - await closeActiveWindows(); - await resetSettings(); - }); - teardown(async () => { - ioc.dispose(); - await closeActiveWindows(); - }); +suite('Module Installerx', () => { + [undefined, Uri.file(__filename)].forEach(resource => { + let ioc: UnitTestIocContainer; + let mockTerminalService: TypeMoq.IMock; + let condaService: TypeMoq.IMock; + let interpreterService: TypeMoq.IMock; + let mockTerminalFactory: TypeMoq.IMock; + + const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test')); + suiteSetup(initializeTest); + setup(async () => { + initializeDI(); + await initializeTest(); + await resetSettings(); + }); + suiteTeardown(async () => { + await closeActiveWindows(); + await resetSettings(); + }); + teardown(async () => { + ioc.dispose(); + await closeActiveWindows(); + }); - function initializeDI() { - ioc = new UnitTestIocContainer(); - ioc.registerUnitTestTypes(); - ioc.registerVariableTypes(); - ioc.registerLinterTypes(); - ioc.registerFormatterTypes(); - - ioc.serviceManager.addSingleton(IPersistentStateFactory, PersistentStateFactory); - ioc.serviceManager.addSingleton(ILogger, Logger); - ioc.serviceManager.addSingleton(IInstaller, ProductInstaller); - - mockTerminalService = TypeMoq.Mock.ofType(); - const mockTerminalFactory = TypeMoq.Mock.ofType(); - mockTerminalFactory.setup(t => t.getTerminalService(TypeMoq.It.isAny())).returns(() => mockTerminalService.object); - ioc.serviceManager.addSingletonInstance(ITerminalServiceFactory, mockTerminalFactory.object); - - ioc.serviceManager.addSingleton(IModuleInstaller, PipInstaller); - ioc.serviceManager.addSingleton(IModuleInstaller, CondaInstaller); - ioc.serviceManager.addSingleton(IModuleInstaller, PipEnvInstaller); - condaService = TypeMoq.Mock.ofType(); - ioc.serviceManager.addSingletonInstance(ICondaService, condaService.object); - - interpreterService = TypeMoq.Mock.ofType(); - ioc.serviceManager.addSingletonInstance(IInterpreterService, interpreterService.object); - - ioc.serviceManager.addSingleton(IPathUtils, PathUtils); - ioc.serviceManager.addSingleton(ICurrentProcess, CurrentProcess); - ioc.serviceManager.addSingleton(IFileSystem, FileSystem); - ioc.serviceManager.addSingleton(IPlatformService, PlatformService); - ioc.serviceManager.addSingleton(IConfigurationService, ConfigurationService); - - ioc.registerMockProcessTypes(); - ioc.serviceManager.addSingletonInstance(IsWindows, false); - } - async function resetSettings(): Promise { - const configService = ioc.serviceManager.get(IConfigurationService); - await configService.updateSettingAsync('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); - } - async function getCurrentPythonPath(): Promise { - const pythonPath = PythonSettings.getInstance(workspaceUri).pythonPath; - if (path.basename(pythonPath) === pythonPath) { - const pythonProc = await ioc.serviceContainer.get(IPythonExecutionFactory).create({ resource: workspaceUri }); - return pythonProc.getExecutablePath().catch(() => pythonPath); - } else { - return pythonPath; + function initializeDI() { + ioc = new UnitTestIocContainer(); + ioc.registerUnitTestTypes(); + ioc.registerVariableTypes(); + ioc.registerLinterTypes(); + ioc.registerFormatterTypes(); + + ioc.serviceManager.addSingleton(IPersistentStateFactory, PersistentStateFactory); + ioc.serviceManager.addSingleton(ILogger, Logger); + ioc.serviceManager.addSingleton(IInstaller, ProductInstaller); + + mockTerminalService = TypeMoq.Mock.ofType(); + mockTerminalFactory = TypeMoq.Mock.ofType(); + mockTerminalFactory.setup(t => t.getTerminalService(TypeMoq.It.isValue(resource))) + .returns(() => mockTerminalService.object) + .verifiable(TypeMoq.Times.atLeastOnce()); + // If resource is provided, then ensure we do not invoke without the resource. + mockTerminalFactory.setup(t => t.getTerminalService(TypeMoq.It.isAny())) + .callback(passedInResource => expect(passedInResource).to.be.equal(resource)) + .returns(() => mockTerminalService.object); + ioc.serviceManager.addSingletonInstance(ITerminalServiceFactory, mockTerminalFactory.object); + + ioc.serviceManager.addSingleton(IModuleInstaller, PipInstaller); + ioc.serviceManager.addSingleton(IModuleInstaller, CondaInstaller); + ioc.serviceManager.addSingleton(IModuleInstaller, PipEnvInstaller); + condaService = TypeMoq.Mock.ofType(); + ioc.serviceManager.addSingletonInstance(ICondaService, condaService.object); + + interpreterService = TypeMoq.Mock.ofType(); + ioc.serviceManager.addSingletonInstance(IInterpreterService, interpreterService.object); + + ioc.serviceManager.addSingleton(IPathUtils, PathUtils); + ioc.serviceManager.addSingleton(ICurrentProcess, CurrentProcess); + ioc.serviceManager.addSingleton(IFileSystem, FileSystem); + ioc.serviceManager.addSingleton(IPlatformService, PlatformService); + ioc.serviceManager.addSingleton(IConfigurationService, ConfigurationService); + + ioc.registerMockProcessTypes(); + ioc.serviceManager.addSingletonInstance(IsWindows, false); } - } - test('Ensure pip is supported and conda is not', async () => { - ioc.serviceManager.addSingletonInstance(IModuleInstaller, new MockModuleInstaller('mock', true)); - const mockInterpreterLocator = TypeMoq.Mock.ofType(); - mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([])); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); - - const processService = await ioc.serviceContainer.get(IProcessServiceFactory).create() as MockProcessService; - processService.onExec((file, args, options, callback) => { - if (args.length > 1 && args[0] === '-c' && args[1] === 'import pip') { - callback({ stdout: '' }); - } - if (args.length > 0 && args[0] === '--version' && file === 'conda') { - callback({ stdout: '', stderr: 'not available' }); + async function resetSettings(): Promise { + const configService = ioc.serviceManager.get(IConfigurationService); + await configService.updateSettingAsync('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace); + } + async function getCurrentPythonPath(): Promise { + const pythonPath = PythonSettings.getInstance(workspaceUri).pythonPath; + if (path.basename(pythonPath) === pythonPath) { + const pythonProc = await ioc.serviceContainer.get(IPythonExecutionFactory).create({ resource: workspaceUri }); + return pythonProc.getExecutablePath().catch(() => pythonPath); + } else { + return pythonPath; } - }); - const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); - expect(moduleInstallers).length(4, 'Incorrect number of installers'); + } + test('Ensure pip is supported and conda is not', async () => { + ioc.serviceManager.addSingletonInstance(IModuleInstaller, new MockModuleInstaller('mock', true)); + const mockInterpreterLocator = TypeMoq.Mock.ofType(); + mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([])); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); + + const processService = await ioc.serviceContainer.get(IProcessServiceFactory).create() as MockProcessService; + processService.onExec((file, args, options, callback) => { + if (args.length > 1 && args[0] === '-c' && args[1] === 'import pip') { + callback({ stdout: '' }); + } + if (args.length > 0 && args[0] === '--version' && file === 'conda') { + callback({ stdout: '', stderr: 'not available' }); + } + }); + const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); + expect(moduleInstallers).length(4, 'Incorrect number of installers'); - const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; - expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); - await expect(pipInstaller.isSupported()).to.eventually.equal(true, 'Pip is not supported'); + const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; + expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); + await expect(pipInstaller.isSupported()).to.eventually.equal(true, 'Pip is not supported'); - const condaInstaller = moduleInstallers.find(item => item.displayName === 'Conda')!; - expect(condaInstaller).not.to.be.an('undefined', 'Conda installer not found'); - await expect(condaInstaller.isSupported()).to.eventually.equal(false, 'Conda is supported'); + const condaInstaller = moduleInstallers.find(item => item.displayName === 'Conda')!; + expect(condaInstaller).not.to.be.an('undefined', 'Conda installer not found'); + await expect(condaInstaller.isSupported()).to.eventually.equal(false, 'Conda is supported'); - const mockInstaller = moduleInstallers.find(item => item.displayName === 'mock')!; - expect(mockInstaller).not.to.be.an('undefined', 'mock installer not found'); - await expect(mockInstaller.isSupported()).to.eventually.equal(true, 'mock is not supported'); - }); + const mockInstaller = moduleInstallers.find(item => item.displayName === 'mock')!; + expect(mockInstaller).not.to.be.an('undefined', 'mock installer not found'); + await expect(mockInstaller.isSupported()).to.eventually.equal(true, 'mock is not supported'); + }); - test('Ensure pip is supported', async () => { - ioc.serviceManager.addSingletonInstance(IModuleInstaller, new MockModuleInstaller('mock', true)); - const pythonPath = await getCurrentPythonPath(); - const mockInterpreterLocator = TypeMoq.Mock.ofType(); - mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, architecture: Architecture.Unknown, companyDisplayName: '', displayName: '', envName: '', path: pythonPath, type: InterpreterType.Conda, version: '' }])); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); - - const processService = await ioc.serviceContainer.get(IProcessServiceFactory).create() as MockProcessService; - processService.onExec((file, args, options, callback) => { - if (args.length > 1 && args[0] === '-c' && args[1] === 'import pip') { - callback({ stdout: '' }); - } - if (args.length > 0 && args[0] === '--version' && file === 'conda') { - callback({ stdout: '' }); - } + test('Ensure pip is supported', async () => { + ioc.serviceManager.addSingletonInstance(IModuleInstaller, new MockModuleInstaller('mock', true)); + const pythonPath = await getCurrentPythonPath(); + const mockInterpreterLocator = TypeMoq.Mock.ofType(); + mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, architecture: Architecture.Unknown, companyDisplayName: '', displayName: '', envName: '', path: pythonPath, type: InterpreterType.Conda, version: '' }])); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); + + const processService = await ioc.serviceContainer.get(IProcessServiceFactory).create() as MockProcessService; + processService.onExec((file, args, options, callback) => { + if (args.length > 1 && args[0] === '-c' && args[1] === 'import pip') { + callback({ stdout: '' }); + } + if (args.length > 0 && args[0] === '--version' && file === 'conda') { + callback({ stdout: '' }); + } + }); + const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); + expect(moduleInstallers).length(4, 'Incorrect number of installers'); + + const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; + expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); + await expect(pipInstaller.isSupported()).to.eventually.equal(true, 'Pip is not supported'); + }); + test('Ensure conda is supported', async () => { + const serviceContainer = TypeMoq.Mock.ofType(); + + const configService = TypeMoq.Mock.ofType(); + serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IConfigurationService))).returns(() => configService.object); + const settings = TypeMoq.Mock.ofType(); + const pythonPath = 'pythonABC'; + settings.setup(s => s.pythonPath).returns(() => pythonPath); + configService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => settings.object); + serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ICondaService))).returns(() => condaService.object); + condaService.setup(c => c.isCondaAvailable()).returns(() => Promise.resolve(true)); + condaService.setup(c => c.isCondaEnvironment(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(true)); + + const condaInstaller = new CondaInstaller(serviceContainer.object); + await expect(condaInstaller.isSupported()).to.eventually.equal(true, 'Conda is not supported'); + }); + test('Ensure conda is not supported even if conda is available', async () => { + const serviceContainer = TypeMoq.Mock.ofType(); + + const configService = TypeMoq.Mock.ofType(); + serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IConfigurationService))).returns(() => configService.object); + const settings = TypeMoq.Mock.ofType(); + const pythonPath = 'pythonABC'; + settings.setup(s => s.pythonPath).returns(() => pythonPath); + configService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => settings.object); + serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ICondaService))).returns(() => condaService.object); + condaService.setup(c => c.isCondaAvailable()).returns(() => Promise.resolve(true)); + condaService.setup(c => c.isCondaEnvironment(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(false)); + + const condaInstaller = new CondaInstaller(serviceContainer.object); + await expect(condaInstaller.isSupported()).to.eventually.equal(false, 'Conda should not be supported'); }); - const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); - expect(moduleInstallers).length(4, 'Incorrect number of installers'); - const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; - expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); - await expect(pipInstaller.isSupported()).to.eventually.equal(true, 'Pip is not supported'); - }); - test('Ensure conda is supported', async () => { - const serviceContainer = TypeMoq.Mock.ofType(); - - const configService = TypeMoq.Mock.ofType(); - serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IConfigurationService))).returns(() => configService.object); - const settings = TypeMoq.Mock.ofType(); - const pythonPath = 'pythonABC'; - settings.setup(s => s.pythonPath).returns(() => pythonPath); - configService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => settings.object); - serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ICondaService))).returns(() => condaService.object); - condaService.setup(c => c.isCondaAvailable()).returns(() => Promise.resolve(true)); - condaService.setup(c => c.isCondaEnvironment(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(true)); - - const condaInstaller = new CondaInstaller(serviceContainer.object); - await expect(condaInstaller.isSupported()).to.eventually.equal(true, 'Conda is not supported'); - }); - test('Ensure conda is not supported even if conda is available', async () => { - const serviceContainer = TypeMoq.Mock.ofType(); - - const configService = TypeMoq.Mock.ofType(); - serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IConfigurationService))).returns(() => configService.object); - const settings = TypeMoq.Mock.ofType(); - const pythonPath = 'pythonABC'; - settings.setup(s => s.pythonPath).returns(() => pythonPath); - configService.setup(c => c.getSettings(TypeMoq.It.isAny())).returns(() => settings.object); - serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ICondaService))).returns(() => condaService.object); - condaService.setup(c => c.isCondaAvailable()).returns(() => Promise.resolve(true)); - condaService.setup(c => c.isCondaEnvironment(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(false)); - - const condaInstaller = new CondaInstaller(serviceContainer.object); - await expect(condaInstaller.isSupported()).to.eventually.equal(false, 'Conda should not be supported'); - }); + const resourceTestNameSuffix = resource ? ' with a resource' : ' without a resource'; + test(`Validate pip install arguments ${resourceTestNameSuffix}`, async () => { + const interpreterPath = await getCurrentPythonPath(); + const mockInterpreterLocator = TypeMoq.Mock.ofType(); + mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: interpreterPath, type: InterpreterType.Unknown }])); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); - test('Validate pip install arguments', async () => { - const interpreterPath = await getCurrentPythonPath(); - const mockInterpreterLocator = TypeMoq.Mock.ofType(); - mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: interpreterPath, type: InterpreterType.Unknown }])); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); + const interpreter: PythonInterpreter = { + ...info, + type: InterpreterType.Unknown, + path: PYTHON_PATH + }; + interpreterService.setup(x => x.getActiveInterpreter(TypeMoq.It.isAny())).returns(() => Promise.resolve(interpreter)); - const interpreter: PythonInterpreter = { - ...info, - type: InterpreterType.Unknown, - path: PYTHON_PATH - }; - interpreterService.setup(x => x.getActiveInterpreter(TypeMoq.It.isAny())).returns(() => Promise.resolve(interpreter)); + const moduleName = 'xyz'; - const moduleName = 'xyz'; + const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); + const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; - const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); - const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; + expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); - expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); + let argsSent: string[] = []; + mockTerminalService + .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) + .returns((cmd: string, args: string[]) => { argsSent = args; return Promise.resolve(void 0); }); + // tslint:disable-next-line:no-any + interpreterService.setup(i => i.getActiveInterpreter(TypeMoq.It.isAny())).returns(() => Promise.resolve({ type: InterpreterType.Unknown } as any)); - let argsSent: string[] = []; - mockTerminalService - .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) - .returns((cmd: string, args: string[]) => { argsSent = args; return Promise.resolve(void 0); }); - // tslint:disable-next-line:no-any - interpreterService.setup(i => i.getActiveInterpreter(TypeMoq.It.isAny())).returns(() => Promise.resolve({ type: InterpreterType.Unknown } as any)); - await pipInstaller.installModule(moduleName); + await pipInstaller.installModule(moduleName, resource); - expect(argsSent.join(' ')).equal(`-m pip install -U ${moduleName} --user`, 'Invalid command sent to terminal for installation.'); - }); + mockTerminalFactory.verifyAll(); + expect(argsSent.join(' ')).equal(`-m pip install -U ${moduleName} --user`, 'Invalid command sent to terminal for installation.'); + }); - test('Validate Conda install arguments', async () => { - const interpreterPath = await getCurrentPythonPath(); - const mockInterpreterLocator = TypeMoq.Mock.ofType(); - mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: interpreterPath, type: InterpreterType.Conda }])); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); + test(`Validate Conda install arguments ${resourceTestNameSuffix}`, async () => { + const interpreterPath = await getCurrentPythonPath(); + const mockInterpreterLocator = TypeMoq.Mock.ofType(); + mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: interpreterPath, type: InterpreterType.Conda }])); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, INTERPRETER_LOCATOR_SERVICE); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, TypeMoq.Mock.ofType().object, PIPENV_SERVICE); - const moduleName = 'xyz'; + const moduleName = 'xyz'; - const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); - const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; + const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); + const pipInstaller = moduleInstallers.find(item => item.displayName === 'Pip')!; - expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); + expect(pipInstaller).not.to.be.an('undefined', 'Pip installer not found'); - let argsSent: string[] = []; - mockTerminalService - .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) - .returns((cmd: string, args: string[]) => { argsSent = args; return Promise.resolve(void 0); }); - await pipInstaller.installModule(moduleName); + let argsSent: string[] = []; + mockTerminalService + .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) + .returns((cmd: string, args: string[]) => { argsSent = args; return Promise.resolve(void 0); }); - expect(argsSent.join(' ')).equal(`-m pip install -U ${moduleName}`, 'Invalid command sent to terminal for installation.'); - }); + await pipInstaller.installModule(moduleName, resource); - test('Validate pipenv install arguments', async () => { - const mockInterpreterLocator = TypeMoq.Mock.ofType(); - mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: 'interpreterPath', type: InterpreterType.VirtualEnv }])); - ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, PIPENV_SERVICE); - - const moduleName = 'xyz'; - const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); - const pipInstaller = moduleInstallers.find(item => item.displayName === 'pipenv')!; - - expect(pipInstaller).not.to.be.an('undefined', 'pipenv installer not found'); - - let argsSent: string[] = []; - let command: string | undefined; - mockTerminalService - .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) - .returns((cmd: string, args: string[]) => { - argsSent = args; - command = cmd; - return Promise.resolve(void 0); - }); + mockTerminalFactory.verifyAll(); + expect(argsSent.join(' ')).equal(`-m pip install -U ${moduleName}`, 'Invalid command sent to terminal for installation.'); + }); + + test(`Validate pipenv install arguments ${resourceTestNameSuffix}`, async () => { + const mockInterpreterLocator = TypeMoq.Mock.ofType(); + mockInterpreterLocator.setup(p => p.getInterpreters(TypeMoq.It.isAny())).returns(() => Promise.resolve([{ ...info, path: 'interpreterPath', type: InterpreterType.VirtualEnv }])); + ioc.serviceManager.addSingletonInstance(IInterpreterLocatorService, mockInterpreterLocator.object, PIPENV_SERVICE); - await pipInstaller.installModule(moduleName); + const moduleName = 'xyz'; + const moduleInstallers = ioc.serviceContainer.getAll(IModuleInstaller); + const pipInstaller = moduleInstallers.find(item => item.displayName === 'pipenv')!; - expect(command!).equal('pipenv', 'Invalid command sent to terminal for installation.'); - expect(argsSent.join(' ')).equal(`install ${moduleName} --dev`, 'Invalid command arguments sent to terminal for installation.'); + expect(pipInstaller).not.to.be.an('undefined', 'pipenv installer not found'); + + let argsSent: string[] = []; + let command: string | undefined; + mockTerminalService + .setup(t => t.sendCommand(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())) + .returns((cmd: string, args: string[]) => { + argsSent = args; + command = cmd; + return Promise.resolve(void 0); + }); + + await pipInstaller.installModule(moduleName, resource); + + mockTerminalFactory.verifyAll(); + expect(command!).equal('pipenv', 'Invalid command sent to terminal for installation.'); + expect(argsSent.join(' ')).equal(`install ${moduleName} --dev`, 'Invalid command arguments sent to terminal for installation.'); + }); }); }); From a7cd7858adcdc73f049897038c67eee945ab3ccf Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 15 May 2018 17:59:25 -0400 Subject: [PATCH 2/2] Use relative paths for prospector --- src/client/linters/prospector.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client/linters/prospector.ts b/src/client/linters/prospector.ts index 5642c5433848..0bd9873d5b8a 100644 --- a/src/client/linters/prospector.ts +++ b/src/client/linters/prospector.ts @@ -1,3 +1,4 @@ +import * as path from 'path'; import { CancellationToken, OutputChannel, TextDocument } from 'vscode'; import '../common/extensions'; import { Product } from '../common/types'; @@ -28,7 +29,9 @@ export class Prospector extends BaseLinter { } protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { - return this.run(['--absolute-paths', '--output-format=json', document.uri.fsPath], document, cancellation); + const cwd = this.getWorkspaceRootPath(document); + const relativePath = path.relative(cwd, document.uri.fsPath); + return this.run(['--absolute-paths', '--output-format=json', relativePath], document, cancellation); } protected async parseMessages(output: string, document: TextDocument, token: CancellationToken, regEx: string) { let parsedData: IProspectorResponse;