Skip to content

Commit a93ce84

Browse files
authored
Log env info when the existence of pipenv cannot be determined (#1962)
Fixes #1338
1 parent 749578a commit a93ce84

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

news/3 Code Health/1338.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Log relevant environment information when the existence of `pipenv` cannot be determined.

src/client/interpreter/locators/services/pipEnvService.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify';
55
import * as path from 'path';
66
import { Uri } from 'vscode';
77
import { IApplicationShell, IWorkspaceService } from '../../../common/application/types';
8-
import { IFileSystem } from '../../../common/platform/types';
8+
import { IFileSystem, IPlatformService } from '../../../common/platform/types';
99
import { IProcessServiceFactory } from '../../../common/process/types';
1010
import { ICurrentProcess, ILogger } from '../../../common/types';
1111
import { IServiceContainer } from '../../../ioc/types';
@@ -126,7 +126,16 @@ export class PipEnvService extends CacheableLocatorService implements IPipEnvSer
126126
}
127127
// tslint:disable-next-line:no-empty
128128
} catch (error) {
129+
const platformService = this.serviceContainer.get<IPlatformService>(IPlatformService);
130+
const currentProc = this.serviceContainer.get<ICurrentProcess>(ICurrentProcess);
131+
const enviromentVariableValues = {
132+
LC_ALL: currentProc.env.LC_ALL,
133+
LANG: currentProc.env.LANG
134+
};
135+
enviromentVariableValues[platformService.pathVariableName] = currentProc.env[platformService.pathVariableName];
136+
129137
this.logger.logWarning('Error in invoking PipEnv', error);
138+
this.logger.logWarning(`Relevant Environment Variables ${JSON.stringify(enviromentVariableValues, undefined, 4)}`);
130139
const errorMessage = error.message || error;
131140
const appShell = this.serviceContainer.get<IApplicationShell>(IApplicationShell);
132141
appShell.showWarningMessage(`Workspace contains pipfile but attempt to run 'pipenv --venv' failed with '${errorMessage}'. Make sure pipenv is on the PATH.`);

src/test/interpreters/pipEnvService.test.ts renamed to src/test/interpreters/pipEnvService.unit.test.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as TypeMoq from 'typemoq';
1111
import { Uri, WorkspaceFolder } from 'vscode';
1212
import { IApplicationShell, IWorkspaceService } from '../../client/common/application/types';
1313
import { EnumEx } from '../../client/common/enumUtils';
14-
import { IFileSystem } from '../../client/common/platform/types';
14+
import { IFileSystem, IPlatformService } from '../../client/common/platform/types';
1515
import { IProcessService, IProcessServiceFactory } from '../../client/common/process/types';
1616
import { ICurrentProcess, ILogger, IPersistentState, IPersistentStateFactory } from '../../client/common/types';
1717
import { IEnvironmentVariablesProvider } from '../../client/common/variables/types';
@@ -40,6 +40,7 @@ suite('Interpreters - PipEnv', () => {
4040
let envVarsProvider: TypeMoq.IMock<IEnvironmentVariablesProvider>;
4141
let procServiceFactory: TypeMoq.IMock<IProcessServiceFactory>;
4242
let logger: TypeMoq.IMock<ILogger>;
43+
let platformService: TypeMoq.IMock<IPlatformService>;
4344
setup(() => {
4445
serviceContainer = TypeMoq.Mock.ofType<IServiceContainer>();
4546
const workspaceService = TypeMoq.Mock.ofType<IWorkspaceService>();
@@ -52,6 +53,7 @@ suite('Interpreters - PipEnv', () => {
5253
envVarsProvider = TypeMoq.Mock.ofType<IEnvironmentVariablesProvider>();
5354
procServiceFactory = TypeMoq.Mock.ofType<IProcessServiceFactory>();
5455
logger = TypeMoq.Mock.ofType<ILogger>();
56+
platformService = TypeMoq.Mock.ofType<IPlatformService>();
5557
processService.setup((x: any) => x.then).returns(() => undefined);
5658
procServiceFactory.setup(p => p.create(TypeMoq.It.isAny())).returns(() => Promise.resolve(processService.object));
5759

@@ -76,6 +78,7 @@ suite('Interpreters - PipEnv', () => {
7678
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IPersistentStateFactory))).returns(() => persistentStateFactory.object);
7779
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IEnvironmentVariablesProvider))).returns(() => envVarsProvider.object);
7880
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(ILogger))).returns(() => logger.object);
81+
serviceContainer.setup(c => c.get(TypeMoq.It.isValue(IPlatformService))).returns(() => platformService.object);
7982

8083
pipEnvService = new PipEnvService(serviceContainer.object);
8184
});
@@ -84,7 +87,7 @@ suite('Interpreters - PipEnv', () => {
8487
const environments = pipEnvService.getInterpreters(resource);
8588
expect(environments).to.be.eventually.deep.equal([]);
8689
});
87-
test(`Should return an empty list if there is a \'PipFile\'${testSuffix}`, async () => {
90+
test(`Should return an empty list if there is no \'PipFile\'${testSuffix}`, async () => {
8891
const env = {};
8992
envVarsProvider.setup(e => e.getEnvironmentVariables(TypeMoq.It.isAny())).returns(() => Promise.resolve({})).verifiable(TypeMoq.Times.once());
9093
currentProcess.setup(c => c.env).returns(() => env);
@@ -97,10 +100,10 @@ suite('Interpreters - PipEnv', () => {
97100
test(`Should display warning message if there is a \'PipFile\' but \'pipenv --venv\' failes ${testSuffix}`, async () => {
98101
const env = {};
99102
currentProcess.setup(c => c.env).returns(() => env);
100-
processService.setup(p => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.reject(''));
103+
processService.setup(p => p.exec(TypeMoq.It.isValue('pipenv'), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.reject(''));
101104
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(path.join(rootWorkspace, 'Pipfile')))).returns(() => Promise.resolve(true));
102105
appShell.setup(a => a.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve('')).verifiable(TypeMoq.Times.once());
103-
logger.setup(l => l.logWarning(TypeMoq.It.isAny(), TypeMoq.It.isAny())).verifiable(TypeMoq.Times.once());
106+
logger.setup(l => l.logWarning(TypeMoq.It.isAny(), TypeMoq.It.isAny())).verifiable(TypeMoq.Times.exactly(2));
104107
const environments = await pipEnvService.getInterpreters(resource);
105108

106109
expect(environments).to.be.deep.equal([]);
@@ -110,10 +113,10 @@ suite('Interpreters - PipEnv', () => {
110113
test(`Should display warning message if there is a \'PipFile\' but \'pipenv --venv\' failes with stderr ${testSuffix}`, async () => {
111114
const env = {};
112115
currentProcess.setup(c => c.env).returns(() => env);
113-
processService.setup(p => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stderr: 'PipEnv Failed', stdout: '' }));
116+
processService.setup(p => p.exec(TypeMoq.It.isValue('pipenv'), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stderr: 'PipEnv Failed', stdout: '' }));
114117
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(path.join(rootWorkspace, 'Pipfile')))).returns(() => Promise.resolve(true));
115118
appShell.setup(a => a.showWarningMessage(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve('')).verifiable(TypeMoq.Times.once());
116-
logger.setup(l => l.logWarning(TypeMoq.It.isAny(), TypeMoq.It.isAny())).verifiable(TypeMoq.Times.once());
119+
logger.setup(l => l.logWarning(TypeMoq.It.isAny(), TypeMoq.It.isAny())).verifiable(TypeMoq.Times.exactly(2));
117120
const environments = await pipEnvService.getInterpreters(resource);
118121

119122
expect(environments).to.be.deep.equal([]);
@@ -125,7 +128,7 @@ suite('Interpreters - PipEnv', () => {
125128
const pythonPath = 'one';
126129
envVarsProvider.setup(e => e.getEnvironmentVariables(TypeMoq.It.isAny())).returns(() => Promise.resolve({})).verifiable(TypeMoq.Times.once());
127130
currentProcess.setup(c => c.env).returns(() => env);
128-
processService.setup(p => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stdout: pythonPath }));
131+
processService.setup(p => p.exec(TypeMoq.It.isValue('pipenv'), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stdout: pythonPath }));
129132
interpreterHelper.setup(v => v.getInterpreterInformation(TypeMoq.It.isAny())).returns(() => Promise.resolve({ version: 'xyz' }));
130133
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(path.join(rootWorkspace, 'Pipfile')))).returns(() => Promise.resolve(true)).verifiable();
131134
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(pythonPath))).returns(() => Promise.resolve(true)).verifiable();
@@ -142,7 +145,7 @@ suite('Interpreters - PipEnv', () => {
142145
const pythonPath = 'one';
143146
envVarsProvider.setup(e => e.getEnvironmentVariables(TypeMoq.It.isAny())).returns(() => Promise.resolve({})).verifiable(TypeMoq.Times.once());
144147
currentProcess.setup(c => c.env).returns(() => env);
145-
processService.setup(p => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stdout: pythonPath }));
148+
processService.setup(p => p.exec(TypeMoq.It.isValue('pipenv'), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ stdout: pythonPath }));
146149
interpreterHelper.setup(v => v.getInterpreterInformation(TypeMoq.It.isAny())).returns(() => Promise.resolve({ version: 'xyz' }));
147150
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(path.join(rootWorkspace, 'Pipfile')))).returns(() => Promise.resolve(false)).verifiable(TypeMoq.Times.never());
148151
fileSystem.setup(fs => fs.fileExists(TypeMoq.It.isValue(path.join(rootWorkspace, envPipFile)))).returns(() => Promise.resolve(true)).verifiable(TypeMoq.Times.once());

0 commit comments

Comments
 (0)