Skip to content

Commit 1c8b1a5

Browse files
authored
Incorrect interpreter displayed in status bar in with multiple workspace folders (#785)
Fixes #690
1 parent 6389ad3 commit 1c8b1a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1081
-743
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"theme": "dark"
3535
},
3636
"engines": {
37-
"vscode": "^1.17.0"
37+
"vscode": "^1.18.0"
3838
},
3939
"recommendations": [
4040
"donjayamanne.jupyter"
@@ -1748,6 +1748,7 @@
17481748
"inversify": "^4.5.2",
17491749
"line-by-line": "^0.1.5",
17501750
"lodash": "^4.17.4",
1751+
"md5": "^2.2.1",
17511752
"minimatch": "^3.0.3",
17521753
"named-js-regexp": "^1.3.1",
17531754
"opn": "^5.1.0",
@@ -1781,11 +1782,13 @@
17811782
"@types/iconv-lite": "0.0.1",
17821783
"@types/istanbul": "^0.4.29",
17831784
"@types/lodash": "^4.14.74",
1785+
"@types/md5": "^2.1.32",
17841786
"@types/mocha": "^2.2.43",
17851787
"@types/node": "^6.0.40",
17861788
"@types/semver": "^5.4.0",
17871789
"@types/shortid": "0.0.29",
17881790
"@types/sinon": "^2.3.2",
1791+
"@types/untildify": "^3.0.0",
17891792
"@types/uuid": "^3.3.27",
17901793
"@types/winreg": "^1.2.30",
17911794
"@types/xml2js": "^0.4.0",

src/client/common/application/applicationShell.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,28 @@
22
// Licensed under the MIT License.
33
'use strict';
44

5-
// tslint:disable-next-line:no-require-imports no-var-requires
5+
// tslint:disable:no-require-imports no-var-requires no-any unified-signatures
66
const opn = require('opn');
77

88
import { injectable } from 'inversify';
99
import * as vscode from 'vscode';
10+
import { Disposable, StatusBarAlignment, StatusBarItem, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
1011
import { IApplicationShell } from './types';
1112

1213
@injectable()
1314
export class ApplicationShell implements IApplicationShell {
14-
public showInformationMessage(message: string, ...items: string[]): Thenable<string> ;
15-
public showInformationMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable<string> ;
16-
public showInformationMessage<T extends vscode.MessageItem>(message: string, ...items: T[]): Thenable<T> ;
17-
public showInformationMessage<T extends vscode.MessageItem>(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable<T> ;
18-
// tslint:disable-next-line:no-any
19-
public showInformationMessage(message: string, options?: any, ...items: any[]): Thenable<any> {
15+
public showInformationMessage(message: string, ...items: string[]): Thenable<string>;
16+
public showInformationMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable<string>;
17+
public showInformationMessage<T extends vscode.MessageItem>(message: string, ...items: T[]): Thenable<T>;
18+
public showInformationMessage<T extends vscode.MessageItem>(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable<T>;
19+
public showInformationMessage(message: string, options?: any, ...items: any[]): Thenable<any> {
2020
return vscode.window.showInformationMessage(message, options, ...items);
2121
}
2222

2323
public showWarningMessage(message: string, ...items: string[]): Thenable<string>;
2424
public showWarningMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable<string>;
2525
public showWarningMessage<T extends vscode.MessageItem>(message: string, ...items: T[]): Thenable<T>;
2626
public showWarningMessage<T extends vscode.MessageItem>(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable<T>;
27-
// tslint:disable-next-line:no-any
2827
public showWarningMessage(message: any, options?: any, ...items: any[]) {
2928
return vscode.window.showWarningMessage(message, options, ...items);
3029
}
@@ -33,28 +32,41 @@ export class ApplicationShell implements IApplicationShell {
3332
public showErrorMessage(message: string, options: vscode.MessageOptions, ...items: string[]): Thenable<string>;
3433
public showErrorMessage<T extends vscode.MessageItem>(message: string, ...items: T[]): Thenable<T>;
3534
public showErrorMessage<T extends vscode.MessageItem>(message: string, options: vscode.MessageOptions, ...items: T[]): Thenable<T>;
36-
// tslint:disable-next-line:no-any
3735
public showErrorMessage(message: any, options?: any, ...items: any[]) {
3836
return vscode.window.showErrorMessage(message, options, ...items);
3937
}
4038

4139
public showQuickPick(items: string[] | Thenable<string[]>, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable<string>;
4240
public showQuickPick<T extends vscode.QuickPickItem>(items: T[] | Thenable<T[]>, options?: vscode.QuickPickOptions, token?: vscode.CancellationToken): Thenable<T>;
43-
// tslint:disable-next-line:no-any
4441
public showQuickPick(items: any, options?: any, token?: any) {
4542
return vscode.window.showQuickPick(items, options, token);
4643
}
4744

48-
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[]> {
45+
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
4946
return vscode.window.showOpenDialog(options);
5047
}
51-
public showSaveDialog(options: vscode.SaveDialogOptions): Thenable<vscode.Uri> {
48+
public showSaveDialog(options: vscode.SaveDialogOptions): Thenable<vscode.Uri | undefined> {
5249
return vscode.window.showSaveDialog(options);
5350
}
54-
public showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken): Thenable<string> {
51+
public showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken): Thenable<string | undefined> {
5552
return vscode.window.showInputBox(options, token);
5653
}
5754
public openUrl(url: string): void {
5855
opn(url);
5956
}
57+
58+
public setStatusBarMessage(text: string, hideAfterTimeout: number): Disposable;
59+
public setStatusBarMessage(text: string, hideWhenDone: Thenable<any>): Disposable;
60+
public setStatusBarMessage(text: string): Disposable;
61+
public setStatusBarMessage(text: string, arg?: any): Disposable {
62+
return vscode.window.setStatusBarMessage(text, arg);
63+
}
64+
65+
public createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem {
66+
return vscode.window.createStatusBarItem(alignment, priority);
67+
}
68+
public showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions): Thenable<WorkspaceFolder | undefined> {
69+
return vscode.window.showWorkspaceFolderPick(options);
70+
}
71+
6072
}

src/client/common/application/types.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
// tslint:disable:no-any unified-signatures
66

77
import * as vscode from 'vscode';
8-
import { CancellationToken, Disposable, Event, FileSystemWatcher, GlobPattern, TextDocument, TextDocumentShowOptions, WorkspaceConfiguration } from 'vscode';
8+
import { CancellationToken, ConfigurationChangeEvent, Disposable, Event, FileSystemWatcher, GlobPattern, TextDocument, TextDocumentShowOptions, WorkspaceConfiguration, WorkspaceFolderPickOptions } from 'vscode';
99
import { TextEditor, TextEditorEdit, TextEditorOptionsChangeEvent, TextEditorSelectionChangeEvent, TextEditorViewColumnChangeEvent } from 'vscode';
10+
import { StatusBarAlignment, StatusBarItem } from 'vscode';
1011
import { Uri, ViewColumn, WorkspaceFolder, WorkspaceFoldersChangeEvent } from 'vscode';
1112
import { Terminal, TerminalOptions } from 'vscode';
1213

@@ -197,6 +198,55 @@ export interface IApplicationShell {
197198
* @param url Url to open.
198199
*/
199200
openUrl(url: string): void;
201+
202+
/**
203+
* Set a message to the status bar. This is a short hand for the more powerful
204+
* status bar [items](#window.createStatusBarItem).
205+
*
206+
* @param text The message to show, supports icon substitution as in status bar [items](#StatusBarItem.text).
207+
* @param hideAfterTimeout Timeout in milliseconds after which the message will be disposed.
208+
* @return A disposable which hides the status bar message.
209+
*/
210+
setStatusBarMessage(text: string, hideAfterTimeout: number): Disposable;
211+
212+
/**
213+
* Set a message to the status bar. This is a short hand for the more powerful
214+
* status bar [items](#window.createStatusBarItem).
215+
*
216+
* @param text The message to show, supports icon substitution as in status bar [items](#StatusBarItem.text).
217+
* @param hideWhenDone Thenable on which completion (resolve or reject) the message will be disposed.
218+
* @return A disposable which hides the status bar message.
219+
*/
220+
setStatusBarMessage(text: string, hideWhenDone: Thenable<any>): Disposable;
221+
222+
/**
223+
* Set a message to the status bar. This is a short hand for the more powerful
224+
* status bar [items](#window.createStatusBarItem).
225+
*
226+
* *Note* that status bar messages stack and that they must be disposed when no
227+
* longer used.
228+
*
229+
* @param text The message to show, supports icon substitution as in status bar [items](#StatusBarItem.text).
230+
* @return A disposable which hides the status bar message.
231+
*/
232+
setStatusBarMessage(text: string): Disposable;
233+
234+
/**
235+
* Creates a status bar [item](#StatusBarItem).
236+
*
237+
* @param alignment The alignment of the item.
238+
* @param priority The priority of the item. Higher values mean the item should be shown more to the left.
239+
* @return A new status bar item.
240+
*/
241+
createStatusBarItem(alignment?: StatusBarAlignment, priority?: number): StatusBarItem;
242+
/**
243+
* Shows a selection list of [workspace folders](#workspace.workspaceFolders) to pick from.
244+
* Returns `undefined` if no folder is open.
245+
*
246+
* @param options Configures the behavior of the workspace folder list.
247+
* @return A promise that resolves to the workspace folder or `undefined`.
248+
*/
249+
showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions): Thenable<WorkspaceFolder | undefined>;
200250
}
201251

202252
export const ICommandManager = Symbol('ICommandManager');
@@ -371,7 +421,7 @@ export interface IWorkspaceService {
371421
/**
372422
* An event that is emitted when the [configuration](#WorkspaceConfiguration) changed.
373423
*/
374-
readonly onDidChangeConfiguration: Event<void>;
424+
readonly onDidChangeConfiguration: Event<ConfigurationChangeEvent>;
375425

376426
/**
377427
* Returns the [workspace folder](#WorkspaceFolder) that contains a given uri.

src/client/common/application/workspace.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
import { injectable } from 'inversify';
55
import * as vscode from 'vscode';
6+
import { ConfigurationChangeEvent } from 'vscode';
67
import { IWorkspaceService } from './types';
78

89
@injectable()
910
export class WorkspaceService implements IWorkspaceService {
10-
public get onDidChangeConfiguration(): vscode.Event<void> {
11+
public get onDidChangeConfiguration(): vscode.Event<ConfigurationChangeEvent> {
1112
return vscode.workspace.onDidChangeConfiguration;
1213
}
1314
public get rootPath(): string | undefined {

src/client/common/process/pythonExecutionFactory.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import { IPythonExecutionFactory, IPythonExecutionService } from './types';
1111
@injectable()
1212
export class PythonExecutionFactory implements IPythonExecutionFactory {
1313
private envVarsService: IEnvironmentVariablesProvider;
14-
constructor( @inject(IServiceContainer) private serviceContainer: IServiceContainer) {
15-
this.envVarsService = serviceContainer.get<IEnvironmentVariablesProvider>(IEnvironmentVariablesProvider);
16-
}
14+
constructor(@inject(IServiceContainer) private serviceContainer: IServiceContainer) {
15+
this.envVarsService = serviceContainer.get<IEnvironmentVariablesProvider>(IEnvironmentVariablesProvider);
16+
}
1717
public async create(resource?: Uri): Promise<IPythonExecutionService> {
1818
return this.envVarsService.getEnvironmentVariables(resource)
1919
.then(customEnvVars => {
20-
return new PythonExecutionService(this.serviceContainer, customEnvVars);
20+
return new PythonExecutionService(this.serviceContainer, customEnvVars, resource);
2121
});
2222
}
2323
}

src/client/common/process/pythonProcess.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// Licensed under the MIT License.
33

44
import { injectable } from 'inversify';
5+
import { Uri } from 'vscode';
56
import { IServiceContainer } from '../../ioc/types';
67
import { ErrorUtils } from '../errors/errorUtils';
78
import { ModuleNotInstalledError } from '../errors/moduleNotInstalledError';
9+
import { IFileSystem } from '../platform/types';
810
import { IConfigurationService } from '../types';
911
import { EnvironmentVariables } from '../variables/types';
1012
import { ExecutionResult, IProcessService, IPythonExecutionService, ObservableExecutionResult, SpawnOptions } from './types';
@@ -13,17 +15,24 @@ import { ExecutionResult, IProcessService, IPythonExecutionService, ObservableEx
1315
export class PythonExecutionService implements IPythonExecutionService {
1416
private procService: IProcessService;
1517
private configService: IConfigurationService;
18+
private fileSystem: IFileSystem;
1619

17-
constructor(serviceContainer: IServiceContainer, private envVars: EnvironmentVariables | undefined) {
20+
constructor(serviceContainer: IServiceContainer, private envVars: EnvironmentVariables | undefined, private resource?: Uri) {
1821
this.procService = serviceContainer.get<IProcessService>(IProcessService);
1922
this.configService = serviceContainer.get<IConfigurationService>(IConfigurationService);
23+
this.fileSystem = serviceContainer.get<IFileSystem>(IFileSystem);
2024
}
2125

2226
public async getVersion(): Promise<string> {
2327
return this.procService.exec(this.pythonPath, ['--version'], { env: this.envVars, mergeStdOutErr: true })
2428
.then(output => output.stdout.trim());
2529
}
2630
public async getExecutablePath(): Promise<string> {
31+
// If we've passed the python file, then return the file.
32+
// This is because on mac if using the interpreter /usr/bin/python2.7 we can get a different value for the path
33+
if (await this.fileSystem.fileExistsAsync(this.pythonPath)){
34+
return this.pythonPath;
35+
}
2736
return this.procService.exec(this.pythonPath, ['-c', 'import sys;print(sys.executable)'], { env: this.envVars, throwOnStdErr: true })
2837
.then(output => output.stdout.trim());
2938
}
@@ -71,6 +80,6 @@ export class PythonExecutionService implements IPythonExecutionService {
7180
return result;
7281
}
7382
private get pythonPath(): string {
74-
return this.configService.getSettings().pythonPath;
83+
return this.configService.getSettings(this.resource).pythonPath;
7584
}
7685
}

src/client/debugger/Common/Utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import * as child_process from 'child_process';
55
import * as fs from 'fs';
66
import * as path from 'path';
7-
import * as untildify from 'untildify';
7+
import untildify = require('untildify');
88
import { IPythonModule, IPythonProcess, IPythonThread } from './Contracts';
99

1010
export const IS_WINDOWS = /^win/.test(process.platform);

src/client/extension.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,15 @@ import { PythonInstaller } from './common/installer/pythonInstallation';
1818
import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry';
1919
import { registerTypes as platformRegisterTypes } from './common/platform/serviceRegistry';
2020
import { registerTypes as processRegisterTypes } from './common/process/serviceRegistry';
21-
import { IProcessService } from './common/process/types';
2221
import { registerTypes as commonRegisterTypes } from './common/serviceRegistry';
2322
import { GLOBAL_MEMENTO, IDisposableRegistry, ILogger, IMemento, IOutputChannel, IPersistentStateFactory, WORKSPACE_MEMENTO } from './common/types';
2423
import { registerTypes as variableRegisterTypes } from './common/variables/serviceRegistry';
2524
import { BaseConfigurationProvider } from './debugger/configProviders/baseProvider';
2625
import { registerTypes as debugConfigurationRegisterTypes } from './debugger/configProviders/serviceRegistry';
2726
import { IDebugConfigurationProvider } from './debugger/types';
2827
import { registerTypes as formattersRegisterTypes } from './formatters/serviceRegistry';
29-
import { InterpreterSelector } from './interpreter/configuration/interpreterSelector';
30-
import { ICondaService, IInterpreterService, IInterpreterVersionService } from './interpreter/contracts';
31-
import { ShebangCodeLensProvider } from './interpreter/display/shebangCodeLensProvider';
28+
import { IInterpreterSelector } from './interpreter/configuration/types';
29+
import { ICondaService, IInterpreterService, IShebangCodeLensProvider } from './interpreter/contracts';
3230
import { registerTypes as interpretersRegisterTypes } from './interpreter/serviceRegistry';
3331
import { ServiceContainer } from './ioc/container';
3432
import { ServiceManager } from './ioc/serviceManager';
@@ -116,9 +114,7 @@ export async function activate(context: vscode.ExtensionContext) {
116114
interpreterManager.refresh()
117115
.catch(ex => console.error('Python Extension: interpreterManager.refresh', ex));
118116

119-
const processService = serviceContainer.get<IProcessService>(IProcessService);
120-
const interpreterVersionService = serviceContainer.get<IInterpreterVersionService>(IInterpreterVersionService);
121-
context.subscriptions.push(new InterpreterSelector(interpreterManager, interpreterVersionService, processService));
117+
context.subscriptions.push(serviceContainer.get<IInterpreterSelector>(IInterpreterSelector));
122118
context.subscriptions.push(activateUpdateSparkLibraryProvider());
123119
activateSimplePythonRefactorProvider(context, standardOutputChannel, serviceContainer);
124120
const jediFactory = new JediFactory(context.asAbsolutePath('.'), serviceContainer);
@@ -156,7 +152,7 @@ export async function activate(context: vscode.ExtensionContext) {
156152
context.subscriptions.push(vscode.languages.registerHoverProvider(PYTHON, new PythonHoverProvider(jediFactory)));
157153
context.subscriptions.push(vscode.languages.registerReferenceProvider(PYTHON, new PythonReferenceProvider(jediFactory)));
158154
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(PYTHON, new PythonCompletionItemProvider(jediFactory, serviceContainer), '.'));
159-
context.subscriptions.push(vscode.languages.registerCodeLensProvider(PYTHON, new ShebangCodeLensProvider(processService)));
155+
context.subscriptions.push(vscode.languages.registerCodeLensProvider(PYTHON, serviceContainer.get<IShebangCodeLensProvider>(IShebangCodeLensProvider)));
160156

161157
const symbolProvider = new PythonSymbolProvider(jediFactory);
162158
context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(PYTHON, symbolProvider));

0 commit comments

Comments
 (0)