Skip to content

Commit ca93798

Browse files
bsamuel-uiTwista
authored andcommitted
Merge pull request serverless#507 from jacksgt/pr-editable
Handle all requirement flags properly and strip -e flags
2 parents b5cdf16 + 7726b2f commit ca93798

File tree

6 files changed

+89
-7
lines changed

6 files changed

+89
-7
lines changed

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,18 @@ except ImportError:
163163
pass
164164
```
165165

166+
## Dealing with Lambda's size limitations #2
167+
168+
If you don't want to zip your requirements, you can define a list of patterns in the serverless config using the `excluded`
169+
option and glob syntax
170+
171+
```yaml
172+
custom:
173+
pythonRequirements:
174+
excluded:
175+
- "Crypto/SelfTest"
176+
```
177+
166178
### Slim Package
167179

168180
_Works on non 'win32' environments: Docker, WSL are included_

index.js

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const { installAllRequirements } = require('./lib/pip');
1515
const { pipfileToRequirements } = require('./lib/pipenv');
1616
const { pyprojectTomlToRequirements } = require('./lib/poetry');
1717
const { cleanup, cleanupCache } = require('./lib/clean');
18+
const { removeExcluded } = require('./lib/exclude');
1819

1920
BbPromise.promisifyAll(fse);
2021

@@ -55,6 +56,7 @@ class ServerlessPythonRequirements {
5556
useDownloadCache: true,
5657
cacheLocation: false,
5758
staticCacheMaxVersions: 0,
59+
excluded: [],
5860
pipCmdExtraArgs: [],
5961
noDeploy: [],
6062
vendor: ''
@@ -173,6 +175,7 @@ class ServerlessPythonRequirements {
173175
.then(pyprojectTomlToRequirements)
174176
.then(addVendorHelper)
175177
.then(installAllRequirements)
178+
.then(removeExcluded)
176179
.then(packRequirements)
177180
.then(setupArtifactPathCapturing);
178181
};

lib/exclude.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const path = require('path');
2+
const glob = require('glob-all');
3+
const fse = require('fs-extra');
4+
5+
/**
6+
* remove all excluded patterns
7+
* @return {undefined}
8+
*/
9+
function removeExcluded() {
10+
if (Array.isArray(this.options.excluded) && this.options.excluded.length > 0) {
11+
const DEBUG = process.env.SLS_DEBUG;
12+
13+
const basePath = path.join(
14+
this.servicePath,
15+
'.serverless',
16+
`requirements`
17+
);
18+
if (DEBUG) this.serverless.cli.log(`Performing removal of excluded files`);
19+
for (const pattern of this.options.excluded) {
20+
if (DEBUG) this.serverless.cli.log(`Pattern: ${basePath}/${pattern}`);
21+
for (const file of glob.sync(`${basePath}/${pattern}`)) {
22+
if (DEBUG) this.serverless.cli(`Found, removing: ${file}`);
23+
fse.removeSync(file);
24+
}
25+
}
26+
}
27+
}
28+
29+
module.exports = { removeExcluded };

lib/pip.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ function generateRequirementsFile(
6969
filterRequirementsFile(
7070
path.join(servicePath, '.serverless/requirements.txt'),
7171
targetFile,
72-
options
72+
options,
73+
serverless
7374
);
7475
serverless.cli.log(
7576
`Parsed requirements.txt from pyproject.toml in ${targetFile}...`
@@ -81,13 +82,14 @@ function generateRequirementsFile(
8182
filterRequirementsFile(
8283
path.join(servicePath, '.serverless/requirements.txt'),
8384
targetFile,
84-
options
85+
options,
86+
serverless
8587
);
8688
serverless.cli.log(
8789
`Parsed requirements.txt from Pipfile in ${targetFile}...`
8890
);
8991
} else {
90-
filterRequirementsFile(requirementsPath, targetFile, options);
92+
filterRequirementsFile(requirementsPath, targetFile, options, serverless);
9193
serverless.cli.log(
9294
`Generated requirements from ${requirementsPath} in ${targetFile}...`
9395
);
@@ -372,13 +374,13 @@ function getRequirements(source) {
372374
* assist with matching the static cache. The sorting will skip any
373375
* lines starting with -- as those are typically ordered at the
374376
* start of a file ( eg: --index-url / --extra-index-url ) or any
375-
* lines that start with -f or -i, Please see:
377+
* lines that start with -c, -e, -f, -i or -r, Please see:
376378
* https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format
377379
* @param {string} source requirements
378380
* @param {string} target requirements where results are written
379381
* @param {Object} options
380382
*/
381-
function filterRequirementsFile(source, target, options) {
383+
function filterRequirementsFile(source, target, options, serverless) {
382384
const noDeploy = new Set(options.noDeploy || []);
383385
const requirements = getRequirements(source);
384386
var prepend = [];
@@ -389,10 +391,23 @@ function filterRequirementsFile(source, target, options) {
389391
return false;
390392
} else if (
391393
req.startsWith('--') ||
394+
req.startsWith('-c') ||
395+
req.startsWith('-e') ||
392396
req.startsWith('-f') ||
393-
req.startsWith('-i')
397+
req.startsWith('-i') ||
398+
req.startsWith('-r')
394399
) {
395-
// If we have options (prefixed with --) keep them for later
400+
if (req.startsWith('-e')) {
401+
// strip out editable flags
402+
// not required inside final archive and avoids pip bugs
403+
// see https://github.com/UnitedIncome/serverless-python-requirements/issues/240
404+
req = req.split('-e')[1].trim();
405+
serverless.cli.log(
406+
`Warning: Stripping -e flag from requirement ${req}`
407+
);
408+
}
409+
410+
// Keep options for later
396411
prepend.push(req);
397412
return false;
398413
} else if (req === '') {

test.js

+22
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,28 @@ test(
376376
{ skip: !hasPython(3) }
377377
);
378378

379+
test(
380+
'py3.6 can package boto3 with editable',
381+
async t => {
382+
process.chdir('tests/base');
383+
const path = npm(['pack', '../..']);
384+
npm(['i', path]);
385+
sls([
386+
`--pythonBin=${getPythonBin(3)}`,
387+
'--fileName=requirements-w-editable.txt',
388+
'package'
389+
]);
390+
const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip');
391+
t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged');
392+
t.true(
393+
zipfiles.includes(`botocore${sep}__init__.py`),
394+
'botocore is packaged'
395+
);
396+
t.end();
397+
},
398+
{ skip: !hasPython(3) }
399+
);
400+
379401
test(
380402
'py3.6 can package flask with dockerizePip option',
381403
async t => {
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-e git+https://github.com/boto/boto3.git#egg=boto3

0 commit comments

Comments
 (0)