forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhelpers.ts
More file actions
74 lines (71 loc) · 3.65 KB
/
helpers.ts
File metadata and controls
74 lines (71 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { inject, injectable } from 'inversify';
import * as path from 'path';
import { traceError } from '../../common/logger';
import { IS_WINDOWS } from '../../common/platform/constants';
import { IFileSystem } from '../../common/platform/types';
import { fsReaddirAsync } from '../../common/utils/fs';
import { IInterpreterLocatorHelper, InterpreterType, PythonInterpreter } from '../contracts';
import { IPipEnvServiceHelper } from './types';
const CheckPythonInterpreterRegEx = IS_WINDOWS ? /^python(\d+(.\d+)?)?\.exe$/ : /^python(\d+(.\d+)?)?$/;
export function lookForInterpretersInDirectory(pathToCheck: string): Promise<string[]> {
return fsReaddirAsync(pathToCheck)
.then(subDirs => subDirs.filter(fileName => CheckPythonInterpreterRegEx.test(path.basename(fileName))))
.catch(err => {
traceError('Python Extension (lookForInterpretersInDirectory.fsReaddirAsync):', err);
return [] as string[];
});
}
@injectable()
export class InterpreterLocatorHelper implements IInterpreterLocatorHelper {
constructor(
@inject(IFileSystem) private readonly fs: IFileSystem,
@inject(IPipEnvServiceHelper) private readonly pipEnvServiceHelper: IPipEnvServiceHelper
) {
}
public async mergeInterpreters(interpreters: PythonInterpreter[]): Promise<PythonInterpreter[]> {
const items = interpreters
.map(item => { return { ...item }; })
.map(item => { item.path = path.normalize(item.path); return item; })
.reduce<PythonInterpreter[]>((accumulator, current) => {
const currentVersion = current && current.version ? current.version.raw : undefined;
const existingItem = accumulator.find(item => {
// If same version and same base path, then ignore.
// Could be Python 3.6 with path = python.exe, and Python 3.6 and path = python3.exe.
if (item.version && item.version.raw === currentVersion &&
item.path && current.path &&
this.fs.arePathsSame(path.dirname(item.path), path.dirname(current.path))) {
return true;
}
return false;
});
if (!existingItem) {
accumulator.push(current);
} else {
// Preserve type information.
// Possible we identified environment as unknown, but a later provider has identified env type.
if (existingItem.type === InterpreterType.Unknown && current.type !== InterpreterType.Unknown) {
existingItem.type = current.type;
}
const props: (keyof PythonInterpreter)[] = ['envName', 'envPath', 'path', 'sysPrefix',
'architecture', 'sysVersion', 'version'];
for (const prop of props) {
if (!existingItem[prop] && current[prop]) {
// tslint:disable-next-line: no-any
(existingItem as any)[prop] = current[prop];
}
}
}
return accumulator;
}, []);
// This stuff needs to be fast.
await Promise.all(items.map(async item => {
const info = await this.pipEnvServiceHelper.getPipEnvInfo(item.path);
if (info) {
item.type = InterpreterType.Pipenv;
item.pipEnvWorkspaceFolder = info.workspaceFolder.fsPath;
item.envName = info.envName || item.envName;
}
}));
return items;
}
}