forked from serverless/serverless-python-requirements
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpipenv.js
147 lines (133 loc) · 4.17 KB
/
pipenv.js
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
const fse = require('fs-extra');
const path = require('path');
const spawn = require('child-process-ext/spawn');
const { EOL } = require('os');
const semver = require('semver');
const LEGACY_PIPENV_VERSION = '2022.8.5';
async function getPipenvVersion() {
try {
const res = await spawn('pipenv', ['--version'], {
cwd: this.servicePath,
});
const stdoutBuffer =
(res.stdoutBuffer && res.stdoutBuffer.toString().trim()) || '';
const version = stdoutBuffer.split(' ')[2];
if (semver.valid(version)) {
return version;
} else {
throw new this.serverless.classes.Error(
`Unable to parse pipenv version!`,
'PYTHON_REQUIREMENTS_PIPENV_VERSION_ERROR'
);
}
} catch (e) {
const stderrBufferContent =
(e.stderrBuffer && e.stderrBuffer.toString()) || '';
if (stderrBufferContent.includes('command not found')) {
throw new this.serverless.classes.Error(
`pipenv not found! Install it according to the pipenv docs.`,
'PYTHON_REQUIREMENTS_PIPENV_NOT_FOUND'
);
} else {
throw e;
}
}
}
/**
* pipenv install
*/
async function pipfileToRequirements() {
if (
!this.options.usePipenv ||
!fse.existsSync(path.join(this.servicePath, 'Pipfile'))
) {
return;
}
let generateRequirementsProgress;
if (this.progress && this.log) {
generateRequirementsProgress = this.progress.get(
'python-generate-requirements-pipfile'
);
generateRequirementsProgress.update(
'Generating requirements.txt from Pipfile'
);
this.log.info('Generating requirements.txt from Pipfile');
} else {
this.serverless.cli.log('Generating requirements.txt from Pipfile...');
}
try {
// Get and validate pipenv version
if (this.log) {
this.log.info('Getting pipenv version');
} else {
this.serverless.cli.log('Getting pipenv version');
}
const pipenvVersion = await getPipenvVersion();
let res;
if (semver.gt(pipenvVersion, LEGACY_PIPENV_VERSION)) {
// Using new pipenv syntax ( >= 2022.8.13)
// Generate requirements from existing lock file.
// See: https://pipenv.pypa.io/en/latest/advanced/#generating-a-requirements-txt
try {
res = await spawn('pipenv', ['requirements'], {
cwd: this.servicePath,
});
} catch (e) {
const stderrBufferContent =
(e.stderrBuffer && e.stderrBuffer.toString()) || '';
if (stderrBufferContent.includes('FileNotFoundError')) {
// No previous Pipfile.lock, we will try to generate it here
if (this.log) {
this.log.warning(
'No Pipfile.lock found! Review https://pipenv.pypa.io/en/latest/pipfile/ for recommendations.'
);
} else {
this.serverless.cli.log(
'WARNING: No Pipfile.lock found! Review https://pipenv.pypa.io/en/latest/pipfile/ for recommendations.'
);
}
await spawn('pipenv', ['lock'], {
cwd: this.servicePath,
});
res = await spawn('pipenv', ['requirements'], {
cwd: this.servicePath,
});
} else {
throw e;
}
}
} else {
// Falling back to legacy pipenv syntax
res = await spawn(
'pipenv',
['lock', '--requirements', '--keep-outdated'],
{
cwd: this.servicePath,
}
);
}
fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
fse.writeFileSync(
path.join(this.servicePath, '.serverless/requirements.txt'),
removeEditableFlagFromRequirementsString(res.stdoutBuffer)
);
} finally {
generateRequirementsProgress && generateRequirementsProgress.remove();
}
}
/**
*
* @param requirementBuffer
* @returns Buffer with editable flags remove
*/
function removeEditableFlagFromRequirementsString(requirementBuffer) {
const flagStr = '-e ';
const lines = requirementBuffer.toString('utf8').split(EOL);
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith(flagStr)) {
lines[i] = lines[i].substring(flagStr.length);
}
}
return Buffer.from(lines.join(EOL));
}
module.exports = { pipfileToRequirements };