diff --git a/lib/pip.js b/lib/pip.js index 7d1777a4..32cb9a83 100644 --- a/lib/pip.js +++ b/lib/pip.js @@ -69,7 +69,8 @@ function generateRequirementsFile( filterRequirementsFile( path.join(servicePath, '.serverless/requirements.txt'), targetFile, - options + options, + serverless ); serverless.cli.log( `Parsed requirements.txt from pyproject.toml in ${targetFile}...` @@ -81,13 +82,14 @@ function generateRequirementsFile( filterRequirementsFile( path.join(servicePath, '.serverless/requirements.txt'), targetFile, - options + options, + serverless ); serverless.cli.log( `Parsed requirements.txt from Pipfile in ${targetFile}...` ); } else { - filterRequirementsFile(requirementsPath, targetFile, options); + filterRequirementsFile(requirementsPath, targetFile, options, serverless); serverless.cli.log( `Generated requirements from ${requirementsPath} in ${targetFile}...` ); @@ -372,13 +374,13 @@ function getRequirements(source) { * assist with matching the static cache. The sorting will skip any * lines starting with -- as those are typically ordered at the * start of a file ( eg: --index-url / --extra-index-url ) or any - * lines that start with -f or -i, Please see: + * lines that start with -c, -e, -f, -i or -r, Please see: * https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format * @param {string} source requirements * @param {string} target requirements where results are written * @param {Object} options */ -function filterRequirementsFile(source, target, options) { +function filterRequirementsFile(source, target, options, serverless) { const noDeploy = new Set(options.noDeploy || []); const requirements = getRequirements(source); var prepend = []; @@ -389,10 +391,23 @@ function filterRequirementsFile(source, target, options) { return false; } else if ( req.startsWith('--') || + req.startsWith('-c') || + req.startsWith('-e') || req.startsWith('-f') || - req.startsWith('-i') + req.startsWith('-i') || + req.startsWith('-r') ) { - // If we have options (prefixed with --) keep them for later + if (req.startsWith('-e')) { + // strip out editable flags + // not required inside final archive and avoids pip bugs + // see https://github.com/UnitedIncome/serverless-python-requirements/issues/240 + req = req.split('-e')[1].trim(); + serverless.cli.log( + `Warning: Stripping -e flag from requirement ${req}` + ); + } + + // Keep options for later prepend.push(req); return false; } else if (req === '') { diff --git a/test.js b/test.js index e5af10c6..e35b521c 100644 --- a/test.js +++ b/test.js @@ -376,6 +376,28 @@ test( { skip: !hasPython(3) } ); +test( + 'py3.6 can package boto3 with editable', + async t => { + process.chdir('tests/base'); + const path = npm(['pack', '../..']); + npm(['i', path]); + sls([ + `--pythonBin=${getPythonBin(3)}`, + '--fileName=requirements-w-editable.txt', + 'package' + ]); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.true( + zipfiles.includes(`botocore${sep}__init__.py`), + 'botocore is packaged' + ); + t.end(); + }, + { skip: !hasPython(3) } +); + test( 'py3.6 can package flask with dockerizePip option', async t => { diff --git a/tests/base/requirements-w-editable.txt b/tests/base/requirements-w-editable.txt new file mode 100644 index 00000000..a7c63986 --- /dev/null +++ b/tests/base/requirements-w-editable.txt @@ -0,0 +1 @@ +-e git+https://github.com/boto/boto3.git#egg=boto3