diff --git a/index.js b/index.js index b444a9b6..90d945fe 100644 --- a/index.js +++ b/index.js @@ -55,6 +55,7 @@ class ServerlessPythonRequirements { useDownloadCache: true, cacheLocation: false, staticCacheMaxVersions: 0, + IndividuallyMoveUpModules: true, pipCmdExtraArgs: [], noDeploy: [], vendor: '' diff --git a/lib/inject.js b/lib/inject.js index e17800c4..b714b5e6 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -56,20 +56,17 @@ function injectRequirements(requirementsPath, packagePath, options) { * @param {string} module module to keep * @return {Promise} the JSZip object written out. */ -function moveModuleUp(source, target, module) { +function injectSourceCode(source, target, module) { const targetZip = new JSZip(); return fse .readFileAsync(source) .then(buffer => JSZip.loadAsync(buffer)) - .then(sourceZip => sourceZip.filter(file => file.startsWith(module + '/'))) - .map(srcZipObj => - zipFile( - targetZip, - srcZipObj.name.replace(module + '/', ''), - srcZipObj.async('nodebuffer') - ) - ) + .then(sourceZip => sourceZip.filter(() => true)) + .map(srcZipObj => { + let targetName = srcZipObj.name.replace(module + '/', ''); + return zipFile(targetZip, targetName, srcZipObj.async('nodebuffer')); + }) .then(() => writeZip(targetZip, target)); } @@ -99,14 +96,24 @@ function injectAllRequirements(funcArtifact) { return func; }) .map(func => { - if (func.module !== '.') { + if ( + this.options.IndividuallyMoveUpModules === true || + this.options.IndividuallyMoveUpModules === 'true' + ) { const artifact = func.package ? func.package.artifact : funcArtifact; - const newArtifact = path.join( - '.serverless', - `${func.module}-${func.name}.zip` - ); + + let newArtifact; + if (func.module === '.') { + newArtifact = path.join('.serverless', `root-${func.name}.zip`); + } else { + newArtifact = path.join( + '.serverless', + `${func.module}-${func.name}.zip` + ); + } + func.package.artifact = newArtifact; - return moveModuleUp(artifact, newArtifact, func.module).then( + return injectSourceCode(artifact, newArtifact, func.module).then( () => func ); } else { diff --git a/test.js b/test.js index 5ba46f2c..1a91bbf7 100644 --- a/test.js +++ b/test.js @@ -10,8 +10,9 @@ const { readFileSync, copySync, writeFileSync, - statSync, - pathExistsSync + pathExistsSync, + existsSync, + statSync } = require('fs-extra'); const { quote } = require('shell-quote'); const { sep } = require('path'); @@ -1156,7 +1157,9 @@ test('py3.6 can package flask with package individually option', t => { npm(['i', path]); sls(['--individually=true', 'package']); - const zipfiles_hello = listZipFiles('.serverless/hello.zip'); + const zipfiles_hello = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello.zip' + ); t.false( zipfiles_hello.includes(`fn2${sep}__init__.py`), 'fn2 is NOT packaged in function hello' @@ -1174,7 +1177,9 @@ test('py3.6 can package flask with package individually option', t => { 'flask is packaged in function hello' ); - const zipfiles_hello2 = listZipFiles('.serverless/hello2.zip'); + const zipfiles_hello2 = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello2.zip' + ); t.false( zipfiles_hello2.includes(`fn2${sep}__init__.py`), 'fn2 is NOT packaged in function hello2' @@ -1192,6 +1197,10 @@ test('py3.6 can package flask with package individually option', t => { 'flask is packaged in function hello2' ); + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); t.false( zipfiles_hello3.includes(`fn2${sep}__init__.py`), @@ -1229,6 +1238,139 @@ test('py3.6 can package flask with package individually option', t => { zipfiles_hello4.includes(`flask${sep}__init__.py`), 'flask is NOT packaged in function hello4' ); + t.false( + zipfiles_hello4.includes(`common${sep}__init__.py`), + 'folder common is NOT packaged in function hello5' + ); + + const zipfiles_hello5 = listZipFiles( + '.serverless/fn2-sls-py-req-test-dev-hello5.zip' + ); + t.true( + zipfiles_hello5.includes(`other.py`), + 'fn2 is packaged in the zip-root in function hello5' + ); + t.true( + zipfiles_hello5.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello5' + ); + t.false( + zipfiles_hello5.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello5' + ); + t.true( + zipfiles_hello5.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello5' + ); + + const zipfiles_hello6 = listZipFiles( + '.serverless/fn3-sls-py-req-test-dev-hello6.zip' + ); + t.true( + zipfiles_hello6.includes(`fn3_handler.py`), + 'fn3 is packaged in the zip-root in function hello6' + ); + t.false( + zipfiles_hello6.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello6' + ); + t.true( + zipfiles_hello6.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello6' + ); + + t.end(); +}); + +test('py3.6 can package individually without moving modules to root of zip-File', t => { + process.chdir('tests/base'); + const path = npm(['pack', '../..']); + npm(['i', path]); + sls(['--individually=true', '--moveup=false', 'package']); + + const zipfiles_hello = listZipFiles('.serverless/hello.zip'); + t.false( + zipfiles_hello.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello' + ); + t.true( + zipfiles_hello.includes('handler.py'), + 'handler.py is packaged in function hello' + ); + t.false( + zipfiles_hello.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello' + ); + t.true( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello' + ); + + const zipfiles_hello4 = listZipFiles('.serverless/hello4.zip'); + t.true( + zipfiles_hello4.includes(`fn2${sep}__init__.py`), + 'fn2 is packaged as module in function hello4' + ); + t.true( + zipfiles_hello4.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello4' + ); + t.false( + zipfiles_hello4.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello4' + ); + t.false( + zipfiles_hello4.includes(`common${sep}__init__.py`), + 'folder common is NOT packaged in function hello4' + ); + + const zipfiles_hello5 = listZipFiles('.serverless/hello5.zip'); + t.true( + zipfiles_hello5.includes(`fn2${sep}__init__.py`), + 'fn2 is packaged as module in function hello5' + ); + t.true( + zipfiles_hello5.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello5' + ); + t.false( + zipfiles_hello5.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello5' + ); + t.true( + zipfiles_hello5.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello5' + ); + + const zipfiles_hello6 = listZipFiles('.serverless/hello6.zip'); + t.true( + zipfiles_hello6.includes(`fn3${sep}__init__.py`), + 'fn3 is packaged as module in function hello6' + ); + t.false( + zipfiles_hello6.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello6' + ); + t.true( + zipfiles_hello6.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello6' + ); t.end(); }); @@ -1239,7 +1381,9 @@ test('py3.6 can package flask with package individually & slim option', t => { npm(['i', path]); sls(['--individually=true', '--slim=true', 'package']); - const zipfiles_hello = listZipFiles('.serverless/hello.zip'); + const zipfiles_hello = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello.zip' + ); t.true( zipfiles_hello.includes('handler.py'), 'handler.py is packaged in function hello' @@ -1258,7 +1402,9 @@ test('py3.6 can package flask with package individually & slim option', t => { 'dataclasses is NOT packaged in function hello' ); - const zipfiles_hello2 = listZipFiles('.serverless/hello2.zip'); + const zipfiles_hello2 = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello2.zip' + ); t.true( zipfiles_hello2.includes('handler.py'), 'handler.py is packaged in function hello2' @@ -1277,6 +1423,11 @@ test('py3.6 can package flask with package individually & slim option', t => { 'dataclasses is NOT packaged in function hello2' ); + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); + const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); t.true( zipfiles_hello3.includes('handler.py'), @@ -1316,17 +1467,22 @@ test('py3.6 can package flask with package individually & slim option', t => { t.end(); }); -test('py2.7 can package flask with package individually option', t => { +test('py3.6 can package individually without moving modules to root of zip-File with slim=true', t => { process.chdir('tests/base'); const path = npm(['pack', '../..']); npm(['i', path]); - sls(['--individually=true', '--runtime=python2.7', 'package']); + sls(['--individually=true', '--slim=true', '--moveup=false', 'package']); const zipfiles_hello = listZipFiles('.serverless/hello.zip'); t.true( zipfiles_hello.includes('handler.py'), 'handler.py is packaged in function hello' ); + t.deepEqual( + zipfiles_hello.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello' + ); t.true( zipfiles_hello.includes(`flask${sep}__init__.py`), 'flask is packaged in function hello' @@ -1341,6 +1497,11 @@ test('py2.7 can package flask with package individually option', t => { zipfiles_hello2.includes('handler.py'), 'handler.py is packaged in function hello2' ); + t.deepEqual( + zipfiles_hello2.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello2' + ); t.true( zipfiles_hello2.includes(`flask${sep}__init__.py`), 'flask is packaged in function hello2' @@ -1350,6 +1511,141 @@ test('py2.7 can package flask with package individually option', t => { 'dataclasses is NOT packaged in function hello2' ); + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); + + const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); + t.true( + zipfiles_hello3.includes('handler.py'), + 'handler.py is packaged in function hello3' + ); + t.deepEqual( + zipfiles_hello3.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello3' + ); + + const zipfiles_hello4 = listZipFiles('.serverless/hello4.zip'); + t.true( + zipfiles_hello4.includes(`fn2${sep}fn2_handler.py`) && + zipfiles_hello4.includes(`fn2${sep}__init__.py`), + 'fn2_handler is packaged as a module in function hello4' + ); + t.true( + zipfiles_hello4.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello4' + ); + t.false( + zipfiles_hello4.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello4' + ); + t.deepEqual( + zipfiles_hello4.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello4' + ); + + const zipfiles_hello5 = listZipFiles('.serverless/hello5.zip'); + t.true( + zipfiles_hello5.includes(`fn2${sep}__init__.py`), + 'fn2 is packaged as module in function hello5' + ); + t.true( + zipfiles_hello5.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello5' + ); + t.false( + zipfiles_hello5.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello5' + ); + t.true( + zipfiles_hello5.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello5' + ); + t.deepEqual( + zipfiles_hello5.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello5' + ); + + const zipfiles_hello6 = listZipFiles('.serverless/hello6.zip'); + t.true( + zipfiles_hello6.includes(`fn3${sep}__init__.py`), + 'fn3 is packaged as module in function hello6' + ); + t.false( + zipfiles_hello6.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`dataclasses.py`), + 'dataclasses is packaged in function hello6' + ); + t.false( + zipfiles_hello6.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello6' + ); + t.true( + zipfiles_hello6.includes(`common${sep}__init__.py`), + 'folder common is packaged in function hello6' + ); + t.deepEqual( + zipfiles_hello6.filter(filename => filename.endsWith('.pyc')), + [], + 'no pyc files packaged in function hello6' + ); + + t.end(); +}); + +test('py2.7 can package flask with package individually option', t => { + process.chdir('tests/base'); + const path = npm(['pack', '../..']); + npm(['i', path]); + sls(['--individually=true', '--runtime=python2.7', 'package']); + + const zipfiles_hello = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello.zip' + ); + t.true( + zipfiles_hello.includes('handler.py'), + 'handler.py is packaged in function hello' + ); + t.true( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello' + ); + t.false( + zipfiles_hello.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello' + ); + + const zipfiles_hello2 = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello2.zip' + ); + t.true( + zipfiles_hello2.includes('handler.py'), + 'handler.py is packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello2' + ); + + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); t.true( zipfiles_hello3.includes('handler.py'), @@ -1389,7 +1685,9 @@ test('py2.7 can package flask with package individually & slim option', t => { npm(['i', path]); sls(['--individually=true', '--runtime=python2.7', '--slim=true', 'package']); - const zipfiles_hello = listZipFiles('.serverless/hello.zip'); + const zipfiles_hello = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello.zip' + ); t.true( zipfiles_hello.includes('handler.py'), 'handler.py is packaged in function hello' @@ -1408,7 +1706,9 @@ test('py2.7 can package flask with package individually & slim option', t => { 'dataclasses is NOT packaged in function hello' ); - const zipfiles_hello2 = listZipFiles('.serverless/hello2.zip'); + const zipfiles_hello2 = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello2.zip' + ); t.true( zipfiles_hello2.includes('handler.py'), 'handler.py is packaged in function hello2' @@ -1427,6 +1727,10 @@ test('py2.7 can package flask with package individually & slim option', t => { 'dataclasses is NOT packaged in function hello2' ); + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); t.true( zipfiles_hello3.includes('handler.py'), @@ -1522,13 +1826,188 @@ test('py3.6 can package only requirements of module', t => { t.end(); }); +test('py3.6 can package different vendor libraries for each module', t => { + process.chdir('tests/individually'); + const path = npm(['pack', '../..']); + npm(['i', path]); + sls(['--vendor-hello1=lib_a', '--vendor-hello2=lib_b', 'package']); + + const zipfiles_hello = listZipFiles( + '.serverless/module1-sls-py-req-test-indiv-dev-hello1.zip' + ); + t.true( + zipfiles_hello.includes('handler1.py'), + 'handler1.py is packaged at root level in function hello1' + ); + t.false( + zipfiles_hello.includes('handler2.py'), + 'handler2.py is NOT packaged at root level in function hello1' + ); + t.true( + zipfiles_hello.includes(`pyaml${sep}__init__.py`), + 'pyaml is packaged in function hello1' + ); + t.false( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello1' + ); + t.true( + zipfiles_hello.includes(`vendor_library_a.py`), + 'vendor library lib_a is packaged in function hello1' + ); + t.false( + zipfiles_hello.includes(`vendor_library_b.py`), + 'vendor library lib_b is NOT packaged in function hello1' + ); + + const zipfiles_hello2 = listZipFiles( + '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' + ); + t.true( + zipfiles_hello2.includes('handler2.py'), + 'handler2.py is packaged at root level in function hello2' + ); + t.false( + zipfiles_hello2.includes('handler1.py'), + 'handler1.py is NOT packaged at root level in function hello2' + ); + t.false( + zipfiles_hello2.includes(`pyaml${sep}__init__.py`), + 'pyaml is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`vendor_library_a.py`), + 'vendor library lib_a is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`vendor_library_b.py`), + 'vendor library lib_b is packaged in function hello2' + ); + + const zipfiles_hello3 = listZipFiles( + '.serverless/module2-sls-py-req-test-indiv-dev-hello3.zip' + ); + t.true( + zipfiles_hello3.includes('handler2.py'), + 'handler2.py is packaged at root level in function hello3' + ); + t.false( + zipfiles_hello3.includes('handler1.py'), + 'handler1.py is NOT packaged at root level in function hello3' + ); + t.false( + zipfiles_hello3.includes(`pyaml${sep}__init__.py`), + 'pyaml is NOT packaged in function hello3' + ); + t.true( + zipfiles_hello3.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`vendor_library_a.py`), + 'vendor library lib_a is packaged in function hello3' + ); + t.true( + zipfiles_hello3.includes(`vendor_library_b.py`), + 'vendor library lib_b is NOT packaged in function hello3' + ); + + t.end(); +}); + +test('py3.6 can package different vendor libraries for each module, when modules are not moved up', t => { + process.chdir('tests/individually'); + const path = npm(['pack', '../..']); + npm(['i', path]); + sls([ + '--vendor-hello1=lib_a', + '--vendor-hello2=lib_b', + '--moveup=false', + 'package' + ]); + + const zipfiles_hello = listZipFiles('.serverless/hello1.zip'); + t.true( + zipfiles_hello.includes(`module1${sep}handler1.py`), + 'module1 is packaged as a module in function hello1' + ); + t.true( + zipfiles_hello.includes(`pyaml${sep}__init__.py`), + 'pyaml is packaged in function hello1' + ); + t.false( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello1' + ); + t.true( + zipfiles_hello.includes(`vendor_library_a.py`), + 'vendor library lib_a is packaged in function hello1' + ); + t.false( + zipfiles_hello.includes(`vendor_library_b.py`), + 'vendor library lib_b is NOT packaged in function hello1' + ); + + const zipfiles_hello2 = listZipFiles('.serverless/hello2.zip'); + t.true( + zipfiles_hello2.includes(`module2${sep}handler2.py`), + 'module2 is packaged as a module in function hello2' + ); + t.false( + zipfiles_hello2.includes(`pyaml${sep}__init__.py`), + 'pyaml is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`vendor_library_a.py`), + 'vendor library lib_a is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`vendor_library_b.py`), + 'vendor library lib_b is packaged in function hello2' + ); + + const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); + t.true( + zipfiles_hello3.includes(`module2${sep}handler2.py`), + 'module2 is packaged as a module in function hello3' + ); + t.false( + zipfiles_hello3.includes(`pyaml${sep}__init__.py`), + 'pyaml is NOT packaged in function hello3' + ); + t.true( + zipfiles_hello3.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`vendor_library_a.py`), + 'vendor library lib_a is packaged in function hello3' + ); + t.true( + zipfiles_hello3.includes(`vendor_library_b.py`), + 'vendor library lib_b is NOT packaged in function hello3' + ); + + t.end(); +}); + test('py3.6 can package lambda-decorators using vendor and invidiually option', t => { process.chdir('tests/base'); const path = npm(['pack', '../..']); npm(['i', path]); sls(['--individually=true', '--vendor=./vendor', 'package']); - const zipfiles_hello = listZipFiles('.serverless/hello.zip'); + const zipfiles_hello = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello.zip' + ); t.true( zipfiles_hello.includes('handler.py'), 'handler.py is packaged at root level in function hello' @@ -1546,7 +2025,9 @@ test('py3.6 can package lambda-decorators using vendor and invidiually option', 'dataclasses is NOT packaged in function hello' ); - const zipfiles_hello2 = listZipFiles('.serverless/hello2.zip'); + const zipfiles_hello2 = listZipFiles( + '.serverless/root-sls-py-req-test-dev-hello2.zip' + ); t.true( zipfiles_hello2.includes('handler.py'), 'handler.py is packaged at root level in function hello2' @@ -1564,6 +2045,10 @@ test('py3.6 can package lambda-decorators using vendor and invidiually option', 'dataclasses is NOT packaged in function hello2' ); + t.true( + !existsSync(`.serverless${sep}root-sls-py-req-test-dev-hello3.zip`), + 'individually packaged artifact is NOT created for function hello3 of non-python runtime' + ); const zipfiles_hello3 = listZipFiles('.serverless/hello3.zip'); t.true( zipfiles_hello3.includes('handler.py'), diff --git a/tests/base/common/__init__.py b/tests/base/common/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/base/fn2/handler.py b/tests/base/fn2/handler.py new file mode 100644 index 00000000..f351ed9c --- /dev/null +++ b/tests/base/fn2/handler.py @@ -0,0 +1,5 @@ +import requests + + +def hello(event, context): + return requests.get("https://httpbin.org/get").json() diff --git a/tests/base/fn2/other.py b/tests/base/fn2/other.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/base/fn3/__init__.py b/tests/base/fn3/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/base/fn3/fn3_handler.py b/tests/base/fn3/fn3_handler.py new file mode 100644 index 00000000..f351ed9c --- /dev/null +++ b/tests/base/fn3/fn3_handler.py @@ -0,0 +1,5 @@ +import requests + + +def hello(event, context): + return requests.get("https://httpbin.org/get").json() diff --git a/tests/base/serverless.yml b/tests/base/serverless.yml index b356c514..9150a4f5 100644 --- a/tests/base/serverless.yml +++ b/tests/base/serverless.yml @@ -15,6 +15,7 @@ custom: slimPatternsAppendDefaults: ${opt:slimPatternsAppendDefaults, self:custom.defaults.slimPatternsAppendDefaults} vendor: ${opt:vendor, ''} fileName: ${opt:fileName, 'requirements.txt'} + IndividuallyMoveUpModules: ${opt:moveup, self:custom.defaults.IndividuallyMoveUpModules} useStaticCache: ${opt:useStaticCache, self:custom.defaults.useStaticCache} useDownloadCache: ${opt:useDownloadCache, self:custom.defaults.useDownloadCache} cacheLocation: ${opt:cacheLocation, ''} @@ -25,8 +26,9 @@ custom: zip: false dockerizePip: false individually: false - useStaticCache: true - useDownloadCache: true + IndividuallyMoveUpModules: true + useStaticCache: false + useDownloadCache: false package: individually: ${opt:individually, self:custom.defaults.individually} @@ -38,8 +40,6 @@ package: functions: hello: handler: handler.hello - hello2: - handler: handler.hello hello3: handler: handler.hello runtime: nodejs6.10 @@ -49,5 +49,19 @@ functions: package: include: - 'fn2/**' - - + hello2: + handler: handler.hello + hello5: + handler: fn2.handler.hello2 + module: fn2 + package: + include: + - 'fn2/**' + - 'common/__init__.py' + hello6: + handler: fn3.fn3_handler.hello + module: fn3 + package: + include: + - 'fn3/**' + - 'common/__init__.py' diff --git a/tests/individually/lib_a/vendor_library_a.py b/tests/individually/lib_a/vendor_library_a.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/individually/lib_b/vendor_library_b.py b/tests/individually/lib_b/vendor_library_b.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/individually/serverless.yml b/tests/individually/serverless.yml index c7cf3802..a7ecb718 100644 --- a/tests/individually/serverless.yml +++ b/tests/individually/serverless.yml @@ -10,16 +10,26 @@ package: custom: pythonRequirements: dockerizePip: ${opt:dockerizePip, self:custom.defaults.dockerizePip} + IndividuallyMoveUpModules: ${opt:moveup, self:custom.defaults.IndividuallyMoveUpModules} defaults: dockerizePip: false + IndividuallyMoveUpModules: true functions: hello1: handler: handler1.hello module: module1 + vendor: ${opt:vendor-hello1, ''} + hello2: handler: handler2.hello module: module2 + vendor: ${opt:vendor-hello2, ''} + + hello3: + handler: handler2.hello + module: module2 + vendor: ${opt:vendor-hello1, ''} plugins: - serverless-python-requirements