Skip to content

Commit 64631a5

Browse files
Translate Pipfiles to Requirements in modules
The plugin does not properly handle Pipfiles that sit in submodules since the pipenv integration does not anticipate submodules. This commit reworks the pipenv integration such that submodules are supported. This changes will convert Pipfiles into requirements as they are parsed by `pip.js` instead of doing it as a pre-processing step. This is done since the submodule discovery logic sits in pip.js.
1 parent 1c14588 commit 64631a5

File tree

4 files changed

+37
-25
lines changed

4 files changed

+37
-25
lines changed

index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const {
1212
const { injectAllRequirements } = require('./lib/inject');
1313
const { layerRequirements } = require('./lib/layer');
1414
const { installAllRequirements } = require('./lib/pip');
15-
const { pipfileToRequirements } = require('./lib/pipenv');
1615
const { pyprojectTomlToRequirements } = require('./lib/poetry');
1716
const { cleanup, cleanupCache } = require('./lib/clean');
1817

@@ -165,7 +164,6 @@ class ServerlessPythonRequirements {
165164
return;
166165
}
167166
return BbPromise.bind(this)
168-
.then(pipfileToRequirements)
169167
.then(pyprojectTomlToRequirements)
170168
.then(addVendorHelper)
171169
.then(installAllRequirements)

lib/pip.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
getRequirementsWorkingPath,
1414
getUserCachePath
1515
} = require('./shared');
16+
const { pipfileToRequirements } = require('./pipenv');
1617

1718
/**
1819
* Omit empty commands.
@@ -55,6 +56,7 @@ function mergeCommands(commands) {
5556
*/
5657
function generateRequirementsFile(
5758
requirementsPath,
59+
modulePath,
5860
targetFile,
5961
serverless,
6062
servicePath,
@@ -74,13 +76,10 @@ function generateRequirementsFile(
7476
);
7577
} else if (
7678
options.usePipenv &&
77-
fse.existsSync(path.join(servicePath, 'Pipfile'))
79+
fse.existsSync(path.join(servicePath, modulePath, 'Pipfile'))
7880
) {
79-
filterRequirementsFile(
80-
path.join(servicePath, '.serverless/requirements.txt'),
81-
targetFile,
82-
options
83-
);
81+
pipfileToRequirements(modulePath, targetFile, serverless, options);
82+
filterRequirementsFile(targetFile, targetFile, options);
8483
serverless.cli.log(
8584
`Parsed requirements.txt from Pipfile in ${targetFile}...`
8685
);
@@ -398,19 +397,22 @@ function copyVendors(vendorFolder, targetFolder, serverless) {
398397
* @param {Object} options
399398
* @param {string} fileName
400399
*/
401-
function requirementsFileExists(servicePath, options, fileName) {
400+
function requirementsFileExists(servicePath, modulePath, options) {
402401
if (
403402
options.usePoetry &&
404403
fse.existsSync(path.join(servicePath, 'pyproject.toml'))
405404
) {
406405
return true;
407406
}
408407

409-
if (options.usePipenv && fse.existsSync(path.join(servicePath, 'Pipfile'))) {
408+
if (
409+
options.usePipenv &&
410+
fse.existsSync(path.join(servicePath, modulePath, 'Pipfile'))
411+
) {
410412
return true;
411413
}
412414

413-
if (fse.existsSync(fileName)) {
415+
if (fse.existsSync(path.join(servicePath, modulePath, options.fileName))) {
414416
return true;
415417
}
416418

@@ -439,7 +441,7 @@ function installRequirementsIfNeeded(
439441
const fileName = path.join(servicePath, modulePath, options.fileName);
440442

441443
// Skip requirements generation, if requirements file doesn't exist
442-
if (!requirementsFileExists(servicePath, options, fileName)) {
444+
if (!requirementsFileExists(servicePath, modulePath, options)) {
443445
return false;
444446
}
445447

@@ -459,6 +461,7 @@ function installRequirementsIfNeeded(
459461

460462
generateRequirementsFile(
461463
fileName,
464+
modulePath,
462465
slsReqsTxt,
463466
serverless,
464467
servicePath,

lib/pipenv.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,29 @@ const { EOL } = require('os');
66
/**
77
* pipenv install
88
*/
9-
function pipfileToRequirements() {
10-
if (
11-
!this.options.usePipenv ||
12-
!fse.existsSync(path.join(this.servicePath, 'Pipfile'))
13-
) {
9+
function pipfileToRequirements(
10+
modulePath,
11+
outputRequirements,
12+
serverless,
13+
options
14+
) {
15+
const pipenvPath = path.join(modulePath, 'Pipfile');
16+
17+
// Stop if Pipfile file does not exist
18+
if (!options.usePipenv || !fse.existsSync(pipenvPath)) {
1419
return;
1520
}
1621

17-
this.serverless.cli.log('Generating requirements.txt from Pipfile...');
22+
serverless.cli.log('Generating requirements.txt from Pipfile...');
1823

1924
const res = spawnSync(
2025
'pipenv',
2126
['lock', '--requirements', '--keep-outdated'],
2227
{
23-
cwd: this.servicePath
28+
cwd: modulePath
2429
}
2530
);
31+
2632
if (res.error) {
2733
if (res.error.code === 'ENOENT') {
2834
throw new Error(
@@ -34,9 +40,8 @@ function pipfileToRequirements() {
3440
if (res.status !== 0) {
3541
throw new Error(res.stderr);
3642
}
37-
fse.ensureDirSync(path.join(this.servicePath, '.serverless'));
3843
fse.writeFileSync(
39-
path.join(this.servicePath, '.serverless/requirements.txt'),
44+
outputRequirements,
4045
removeEditableFlagFromRequirementsString(res.stdout)
4146
);
4247
}

test.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,8 +1582,11 @@ test(
15821582
'foobar has retained its executable file permissions'
15831583
);
15841584

1585-
const zipfiles_hello2 = listZipFilesWithMetaData('.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip');
1586-
const flaskPerm = statSync('.serverless/module2/requirements/bin/flask').mode;
1585+
const zipfiles_hello2 = listZipFilesWithMetaData(
1586+
'.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip'
1587+
);
1588+
const flaskPerm = statSync('.serverless/module2/requirements/bin/flask')
1589+
.mode;
15871590

15881591
t.true(
15891592
zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm,
@@ -1616,8 +1619,11 @@ test(
16161619
'foobar has retained its executable file permissions'
16171620
);
16181621

1619-
const zipfiles_hello2 = listZipFilesWithMetaData('.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip');
1620-
const flaskPerm = statSync('.serverless/module2/requirements/bin/flask').mode;
1622+
const zipfiles_hello2 = listZipFilesWithMetaData(
1623+
'.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip'
1624+
);
1625+
const flaskPerm = statSync('.serverless/module2/requirements/bin/flask')
1626+
.mode;
16211627

16221628
t.true(
16231629
zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm,

0 commit comments

Comments
 (0)