-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathenvironment.ts
More file actions
81 lines (68 loc) · 2.63 KB
/
environment.ts
File metadata and controls
81 lines (68 loc) · 2.63 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
75
76
77
78
79
80
81
import * as fs from 'fs';
import * as child_process from 'child_process';
import PythonPackage from './PythonPackage';
import PythonEnvironment from './PythonEnvironment';
import { withStatus } from 'src/status';
import { sync as commandExistsSync } from 'command-exists';
// Some future improvements:
// - Could use `importlib` and execute some stuff from Python
interface PipInformation {
name: string;
version: string;
}
let pipCommand: string | undefined;
let getPipCommand = () => {
if (pipCommand === undefined) {
if (commandExistsSync('pip3')) {
pipCommand = 'pip3';
} else if (commandExistsSync('pip')) {
pipCommand = 'pip';
} else {
throw new Error('Could not find valid pip command');
}
}
return pipCommand;
};
function pipList(): PipInformation[] {
console.log(`Executing pip list.`);
return JSON.parse(
child_process.execSync(`${getPipCommand()} list --format=json`, { maxBuffer: 1024 * 1024 * 100 }).toString()
) as PipInformation[];
}
function pipBulkShow(names: string[]): string[] {
const BATCH_SIZE = 10;
const results: string[] = [];
console.log(names.length + ' packages to show');
for (let i = 0; i < names.length; i += BATCH_SIZE) {
const batch = names.slice(i, i + BATCH_SIZE);
console.log(`Executing pip show for the following packages: ${batch.join(', ')}`);
console.log(`${getPipCommand()} show -f ${batch.join(' ')}`);t
const output = child_process
.execSync(`${getPipCommand()} show -f ${batch.join(' ')}`, { maxBuffer: 1024 * 1024 * 5 })
.toString()
results.push(...output.split('\n---'));
}
return results;
}
export default function getEnvironment(
projectFiles: Set<string>,
projectVersion: string,
cachedEnvFile: string | undefined
): PythonEnvironment {
if (cachedEnvFile) {
let f = JSON.parse(fs.readFileSync(cachedEnvFile).toString()).map((entry: any) => {
return new PythonPackage(entry.name, entry.version, entry.files);
});
return new PythonEnvironment(projectFiles, projectVersion, f);
}
return withStatus('Evaluating python environment dependencies', (progress) => {
const listed = pipList();
progress.message('Gathering environment information from `pip`');
const bulk = pipBulkShow(listed.map((item) => item.name));
progress.message('Analyzing dependencies');
const info = bulk.map((shown) => {
return PythonPackage.fromPipShow(shown);
});
return new PythonEnvironment(projectFiles, projectVersion, info);
});
}