From c6bf6cde6d21df6c8055b591f56d708214f421f9 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Fri, 7 Feb 2025 17:15:47 +0100 Subject: [PATCH 01/17] fix: Use absolute paths to ensure compatibility with v4 Compose --- lib/inject.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index 12267376..dab5714d 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -153,7 +153,7 @@ async function injectAllRequirements(funcArtifact) { return this.options.zip ? func : injectRequirements( - path.join('.serverless', func.module, 'requirements'), + path.join(this.serverless.serviceDir, '.serverless', func.module, 'requirements'), func.package.artifact, injectionRelativePath, this.options @@ -161,7 +161,7 @@ async function injectAllRequirements(funcArtifact) { }); } else if (!this.options.zip) { await injectRequirements( - path.join('.serverless', 'requirements'), + path.join(this.serverless.serviceDir, '.serverless', 'requirements'), this.serverless.service.package.artifact || funcArtifact, injectionRelativePath, this.options From dfc5638a8464603363447f67df7c98faea6edea7 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Fri, 7 Feb 2025 17:30:52 +0100 Subject: [PATCH 02/17] fix: Prettify --- lib/inject.js | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index dab5714d..02c4849c 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -23,6 +23,9 @@ function injectRequirements( injectionRelativePath, options ) { + console.log('requirementsPath', requirementsPath); + console.log('injectionRelativePath', injectionRelativePath); + console.log('packagePath', packagePath); const noDeploy = new Set(options.noDeploy || []); return fse @@ -31,17 +34,21 @@ function injectRequirements( .then((zip) => BbPromise.resolve( glob.sync([path.join(requirementsPath, '**')], { + // glob.sync([path.join(packagePath, '..', 'requirements', '**')], { mark: true, dot: true, }) ) - .map((file) => [ - file, - path.join( - injectionRelativePath, - path.relative(requirementsPath, file) - ), - ]) + .map((file) => { + // console.log('first map file', file); + return [ + file, + path.join( + injectionRelativePath, + path.relative(requirementsPath, file) + ), + ]; + }) .filter( ([file, relativeFile]) => !file.endsWith('/') && @@ -51,12 +58,13 @@ function injectRequirements( .map(([file, relativeFile]) => Promise.all([file, relativeFile, fse.statAsync(file)]) ) - .mapSeries(([file, relativeFile, fileStat]) => - zipFile(zip, relativeFile, fse.readFileAsync(file), { + .mapSeries(([file, relativeFile, fileStat]) => { + // console.log('file', file); + return zipFile(zip, relativeFile, fse.readFileAsync(file), { unixPermissions: fileStat.mode, createFolders: false, - }) - ) + }); + }) .then(() => writeZip(zip, packagePath)) ); } @@ -150,10 +158,16 @@ async function injectAllRequirements(funcArtifact) { } }) .map((func) => { + console.log('func.module', func.module); return this.options.zip ? func : injectRequirements( - path.join(this.serverless.serviceDir, '.serverless', func.module, 'requirements'), + path.join( + this.serverless.serviceDir, + '.serverless', + func.module, + 'requirements' + ), func.package.artifact, injectionRelativePath, this.options From e3dfc43c92c1611daceb4be8a9021f96fc762bf6 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 15:15:42 +0100 Subject: [PATCH 03/17] fix: Remove peerDependencies --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 07466e23..f5754f24 100644 --- a/package.json +++ b/package.json @@ -77,9 +77,6 @@ "sha256-file": "1.0.0", "shell-quote": "^1.8.1" }, - "peerDependencies": { - "serverless": ">=2.32" - }, "lint-staged": { "*.js": [ "eslint" From 43686b6bdb86aacf53a2afd9f4b8e5df1a16bd7c Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 15:32:49 +0100 Subject: [PATCH 04/17] fix: Revert --- lib/inject.js | 40 +++++++++++++--------------------------- package.json | 3 +++ 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index 02c4849c..12267376 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -23,9 +23,6 @@ function injectRequirements( injectionRelativePath, options ) { - console.log('requirementsPath', requirementsPath); - console.log('injectionRelativePath', injectionRelativePath); - console.log('packagePath', packagePath); const noDeploy = new Set(options.noDeploy || []); return fse @@ -34,21 +31,17 @@ function injectRequirements( .then((zip) => BbPromise.resolve( glob.sync([path.join(requirementsPath, '**')], { - // glob.sync([path.join(packagePath, '..', 'requirements', '**')], { mark: true, dot: true, }) ) - .map((file) => { - // console.log('first map file', file); - return [ - file, - path.join( - injectionRelativePath, - path.relative(requirementsPath, file) - ), - ]; - }) + .map((file) => [ + file, + path.join( + injectionRelativePath, + path.relative(requirementsPath, file) + ), + ]) .filter( ([file, relativeFile]) => !file.endsWith('/') && @@ -58,13 +51,12 @@ function injectRequirements( .map(([file, relativeFile]) => Promise.all([file, relativeFile, fse.statAsync(file)]) ) - .mapSeries(([file, relativeFile, fileStat]) => { - // console.log('file', file); - return zipFile(zip, relativeFile, fse.readFileAsync(file), { + .mapSeries(([file, relativeFile, fileStat]) => + zipFile(zip, relativeFile, fse.readFileAsync(file), { unixPermissions: fileStat.mode, createFolders: false, - }); - }) + }) + ) .then(() => writeZip(zip, packagePath)) ); } @@ -158,16 +150,10 @@ async function injectAllRequirements(funcArtifact) { } }) .map((func) => { - console.log('func.module', func.module); return this.options.zip ? func : injectRequirements( - path.join( - this.serverless.serviceDir, - '.serverless', - func.module, - 'requirements' - ), + path.join('.serverless', func.module, 'requirements'), func.package.artifact, injectionRelativePath, this.options @@ -175,7 +161,7 @@ async function injectAllRequirements(funcArtifact) { }); } else if (!this.options.zip) { await injectRequirements( - path.join(this.serverless.serviceDir, '.serverless', 'requirements'), + path.join('.serverless', 'requirements'), this.serverless.service.package.artifact || funcArtifact, injectionRelativePath, this.options diff --git a/package.json b/package.json index f5754f24..07466e23 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,9 @@ "sha256-file": "1.0.0", "shell-quote": "^1.8.1" }, + "peerDependencies": { + "serverless": ">=2.32" + }, "lint-staged": { "*.js": [ "eslint" From 015af0e3f059bfed1cdb030deb528011a0f0d35b Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 15:34:49 +0100 Subject: [PATCH 05/17] fix: Fake change --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index ca8b191f..44906956 100644 --- a/index.js +++ b/index.js @@ -74,7 +74,7 @@ class ServerlessPythonRequirements { options.pythonBin = 'python'; } if (/python3[0-9]+/.test(options.pythonBin)) { - // "google" and "scaleway" providers' runtimes uses python3XX + // "google" and "scaleway" providers' runtimes use python3XX options.pythonBin = options.pythonBin.replace(/3([0-9]+)/, '3.$1'); } if (options.dockerizePip === 'non-linux') { From 37745a4bcd630ef905b1f40528b82d21ca8e9054 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 15:37:14 +0100 Subject: [PATCH 06/17] fix: Fake change --- tests/base/handler.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/base/handler.py b/tests/base/handler.py index 5e2e67ff..ba39cf69 100644 --- a/tests/base/handler.py +++ b/tests/base/handler.py @@ -1,5 +1,4 @@ import requests - def hello(event, context): return requests.get('https://httpbin.org/get').json() From 64ca4bf917f7a853480e3e456fc02970c72a12e0 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 19:47:45 +0100 Subject: [PATCH 07/17] fix: Use absolute paths to work with v4 Compose --- lib/inject.js | 40 +++++++++++++++++++++++++++------------- package.json | 3 --- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index 12267376..02c4849c 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -23,6 +23,9 @@ function injectRequirements( injectionRelativePath, options ) { + console.log('requirementsPath', requirementsPath); + console.log('injectionRelativePath', injectionRelativePath); + console.log('packagePath', packagePath); const noDeploy = new Set(options.noDeploy || []); return fse @@ -31,17 +34,21 @@ function injectRequirements( .then((zip) => BbPromise.resolve( glob.sync([path.join(requirementsPath, '**')], { + // glob.sync([path.join(packagePath, '..', 'requirements', '**')], { mark: true, dot: true, }) ) - .map((file) => [ - file, - path.join( - injectionRelativePath, - path.relative(requirementsPath, file) - ), - ]) + .map((file) => { + // console.log('first map file', file); + return [ + file, + path.join( + injectionRelativePath, + path.relative(requirementsPath, file) + ), + ]; + }) .filter( ([file, relativeFile]) => !file.endsWith('/') && @@ -51,12 +58,13 @@ function injectRequirements( .map(([file, relativeFile]) => Promise.all([file, relativeFile, fse.statAsync(file)]) ) - .mapSeries(([file, relativeFile, fileStat]) => - zipFile(zip, relativeFile, fse.readFileAsync(file), { + .mapSeries(([file, relativeFile, fileStat]) => { + // console.log('file', file); + return zipFile(zip, relativeFile, fse.readFileAsync(file), { unixPermissions: fileStat.mode, createFolders: false, - }) - ) + }); + }) .then(() => writeZip(zip, packagePath)) ); } @@ -150,10 +158,16 @@ async function injectAllRequirements(funcArtifact) { } }) .map((func) => { + console.log('func.module', func.module); return this.options.zip ? func : injectRequirements( - path.join('.serverless', func.module, 'requirements'), + path.join( + this.serverless.serviceDir, + '.serverless', + func.module, + 'requirements' + ), func.package.artifact, injectionRelativePath, this.options @@ -161,7 +175,7 @@ async function injectAllRequirements(funcArtifact) { }); } else if (!this.options.zip) { await injectRequirements( - path.join('.serverless', 'requirements'), + path.join(this.serverless.serviceDir, '.serverless', 'requirements'), this.serverless.service.package.artifact || funcArtifact, injectionRelativePath, this.options diff --git a/package.json b/package.json index 07466e23..f5754f24 100644 --- a/package.json +++ b/package.json @@ -77,9 +77,6 @@ "sha256-file": "1.0.0", "shell-quote": "^1.8.1" }, - "peerDependencies": { - "serverless": ">=2.32" - }, "lint-staged": { "*.js": [ "eslint" From d664007f688ec95f87f28897a5ef1f4f5f81e4c4 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Mon, 10 Feb 2025 19:49:07 +0100 Subject: [PATCH 08/17] fix: Install poetry-plugin-export plugin in pipeline --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 38f69696..23e2d67f 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -61,7 +61,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv poetry && poetry self add poetry-plugin-export - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} From 78b1f9e60653c4e740cb35fc179f64482b5c1e8e Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 17:20:44 +0100 Subject: [PATCH 09/17] fix: Remove console.log --- lib/inject.js | 30 +- package.json | 3 + test.js | 3224 ++++++++++++++++++++------------------- tests/base/handler.py | 1 + tests/base/package.json | 2 +- 5 files changed, 1629 insertions(+), 1631 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index 02c4849c..5733241b 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -23,9 +23,6 @@ function injectRequirements( injectionRelativePath, options ) { - console.log('requirementsPath', requirementsPath); - console.log('injectionRelativePath', injectionRelativePath); - console.log('packagePath', packagePath); const noDeploy = new Set(options.noDeploy || []); return fse @@ -34,21 +31,17 @@ function injectRequirements( .then((zip) => BbPromise.resolve( glob.sync([path.join(requirementsPath, '**')], { - // glob.sync([path.join(packagePath, '..', 'requirements', '**')], { mark: true, dot: true, }) ) - .map((file) => { - // console.log('first map file', file); - return [ - file, - path.join( - injectionRelativePath, - path.relative(requirementsPath, file) - ), - ]; - }) + .map((file) => [ + file, + path.join( + injectionRelativePath, + path.relative(requirementsPath, file) + ), + ]) .filter( ([file, relativeFile]) => !file.endsWith('/') && @@ -58,13 +51,12 @@ function injectRequirements( .map(([file, relativeFile]) => Promise.all([file, relativeFile, fse.statAsync(file)]) ) - .mapSeries(([file, relativeFile, fileStat]) => { - // console.log('file', file); - return zipFile(zip, relativeFile, fse.readFileAsync(file), { + .mapSeries(([file, relativeFile, fileStat]) => + zipFile(zip, relativeFile, fse.readFileAsync(file), { unixPermissions: fileStat.mode, createFolders: false, - }); - }) + }) + ) .then(() => writeZip(zip, packagePath)) ); } diff --git a/package.json b/package.json index f5754f24..07466e23 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,9 @@ "sha256-file": "1.0.0", "shell-quote": "^1.8.1" }, + "peerDependencies": { + "serverless": ">=2.32" + }, "lint-staged": { "*.js": [ "eslint" diff --git a/test.js b/test.js index 488b500f..7d7a3240 100644 --- a/test.js +++ b/test.js @@ -215,6 +215,8 @@ test( dockerImage: 'break the build to log the command', }, }); + console.log(`-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z`) + console.log('stderr', stderr); t.true( stderr.includes( `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` @@ -225,1614 +227,1614 @@ test( }, { skip: !canUseDocker() || brokenOn('win32') } ); - -test('default pythonBin can package flask with default options', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('py3.9 packages have the same hash', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const fileHash = sha256File('.serverless/sls-py-req-test.zip'); - sls(['package'], { env: {} }); - t.equal( - sha256File('.serverless/sls-py-req-test.zip'), - fileHash, - 'packages have the same hash' - ); - t.end(); -}); - -test('py3.9 can package flask with default options', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test( - 'py3.9 can package flask with hashes', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - fileName: 'requirements-w-hashes.txt', - pythonBin: getPythonBin(3), - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.end(); - }, - { skip: brokenOn('win32') } -); - -test('py3.9 can package flask with nested', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - fileName: 'requirements-w-nested.txt', - pythonBin: getPythonBin(3), - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('py3.9 can package flask with zip option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.end(); -}); - -test('py3.9 can package flask with slim option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true', pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.true( - zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, - '__main__.py files are packaged' - ); - t.end(); -}); - -test('py3.9 can package flask with slim & slimPatterns options', async (t) => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test("py3.9 doesn't package bottle with noDeploy option", async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', - 'serverless.yml', - ]); - sls(['package'], { env: { pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); - t.end(); -}); - -test('py3.9 can package boto3 with editable', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - fileName: 'requirements-w-editable.txt', - pythonBin: getPythonBin(3), - }, - }); - 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(); -}); - -test( - 'py3.9 can package flask with dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test( - 'py3.9 can package flask with slim & dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - '*.pyc files are NOT packaged' - ); - t.true( - zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > - 0, - '__main__.py files are packaged' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test( - 'py3.9 can package flask with slim & dockerizePip & slimPatterns options', - async (t) => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - '*.pyc files are packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test( - 'py3.9 can package flask with zip & dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - const zippedReqs = await listRequirementsZipFiles( - '.serverless/sls-py-req-test.zip' - ); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true( - zipfiles.includes(`unzip_requirements.py`), - 'unzip util is packaged' - ); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.true( - zippedReqs.includes(`flask/__init__.py`), - 'flask is packaged in the .requirements.zip file' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test( - 'py3.9 can package flask with zip & slim & dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { dockerizePip: 'true', zip: 'true', slim: 'true' }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - const zippedReqs = await listRequirementsZipFiles( - '.serverless/sls-py-req-test.zip' - ); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true( - zipfiles.includes(`unzip_requirements.py`), - 'unzip util is packaged' - ); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.true( - zippedReqs.includes(`flask/__init__.py`), - 'flask is packaged in the .requirements.zip file' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test('pipenv py3.9 can package flask with default options', async (t) => { - process.chdir('tests/pipenv'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.false( - zipfiles.includes(`pytest${sep}__init__.py`), - 'dev-package pytest is NOT packaged' - ); - t.end(); -}); - -test('pipenv py3.9 can package flask with slim option', async (t) => { - process.chdir('tests/pipenv'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.true( - zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, - '__main__.py files are packaged' - ); - t.end(); -}); - -test('pipenv py3.9 can package flask with slim & slimPatterns options', async (t) => { - process.chdir('tests/pipenv'); - - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test('pipenv py3.9 can package flask with zip option', async (t) => { - process.chdir('tests/pipenv'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.end(); -}); - -test("pipenv py3.9 doesn't package bottle with noDeploy option", async (t) => { - process.chdir('tests/pipenv'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', - 'serverless.yml', - ]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); - t.end(); -}); - -test('non build pyproject.toml uses requirements.txt', async (t) => { - process.chdir('tests/non_build_pyproject'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('non poetry pyproject.toml without requirements.txt packages handler only', async (t) => { - process.chdir('tests/non_poetry_pyproject'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`handler.py`), 'handler is packaged'); - t.end(); -}); - -test('poetry py3.9 can package flask with default options', async (t) => { - process.chdir('tests/poetry'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('poetry py3.9 can package flask with slim option', async (t) => { - process.chdir('tests/poetry'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.true( - zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, - '__main__.py files are packaged' - ); - t.end(); -}); - -test('poetry py3.9 can package flask with slim & slimPatterns options', async (t) => { - process.chdir('tests/poetry'); - - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test('poetry py3.9 can package flask with zip option', async (t) => { - process.chdir('tests/poetry'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.end(); -}); - -test("poetry py3.9 doesn't package bottle with noDeploy option", async (t) => { - process.chdir('tests/poetry'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', - 'serverless.yml', - ]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); - t.end(); -}); - -test('py3.9 can package flask with zip option and no explicit include', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - perl(['-p', '-i.bak', '-e', 's/include://', 'serverless.yml']); - perl(['-p', '-i.bak', '-e', 's/^.*handler.py.*$//', 'serverless.yml']); - sls(['package'], { env: { zip: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.end(); -}); - -test('py3.9 can package lambda-decorators using vendor option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { vendor: './vendor' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.true( - zipfiles.includes(`lambda_decorators.py`), - 'lambda_decorators.py is packaged' - ); - t.end(); -}); - -test( - "Don't nuke execute perms", - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - const perm = '755'; - - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(handler.py.*$)/$1\n - foobar/', - 'serverless.yml', - ]); - writeFileSync(`foobar`, ''); - chmodSync(`foobar`, perm); - sls(['package'], { env: { vendor: './vendor' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.true( - zipfiles.includes(`lambda_decorators.py`), - 'lambda_decorators.py is packaged' - ); - t.true(zipfiles.includes(`foobar`), 'foobar is packaged'); - - const zipfiles_with_metadata = await listZipFilesWithMetaData( - '.serverless/sls-py-req-test.zip' - ); - t.true( - zipfiles_with_metadata['foobar'].unixPermissions - .toString(8) - .slice(3, 6) === perm, - 'foobar has retained its executable file permissions' - ); - - const flaskPerm = statSync('.serverless/requirements/bin/flask').mode; - t.true( - zipfiles_with_metadata['bin/flask'].unixPermissions === flaskPerm, - 'bin/flask has retained its executable file permissions' - ); - - t.end(); - }, - { skip: process.platform === 'win32' } -); - -test('py3.9 can package flask in a project with a space in it', async (t) => { - copySync('tests/base', 'tests/base with a space'); - process.chdir('tests/base with a space'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test( - 'py3.9 can package flask in a project with a space in it with docker', - async (t) => { - copySync('tests/base', 'tests/base with a space'); - process.chdir('tests/base with a space'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test('py3.9 supports custom file name with fileName option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - writeFileSync('puck', 'requests'); - npm(['i', path]); - sls(['package'], { env: { fileName: 'puck' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes(`requests${sep}__init__.py`), - 'requests is packaged' - ); - t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); - t.false(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is NOT packaged'); - t.end(); -}); - -test("py3.9 doesn't package bottle with zip option", async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', - 'serverless.yml', - ]); - sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - const zippedReqs = await listRequirementsZipFiles( - '.serverless/sls-py-req-test.zip' - ); - t.true( - zipfiles.includes('.requirements.zip'), - 'zipped requirements are packaged' - ); - t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); - t.false( - zipfiles.includes(`flask${sep}__init__.py`), - "flask isn't packaged on its own" - ); - t.true( - zippedReqs.includes(`flask/__init__.py`), - 'flask is packaged in the .requirements.zip file' - ); - t.false( - zippedReqs.includes(`bottle.py`), - 'bottle is NOT packaged in the .requirements.zip file' - ); - t.end(); -}); - -test('py3.9 can package flask with slim, slimPatterns & slimPatternsAppendDefaults=false options', async (t) => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true( - zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, - 'pyc files are packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test( - 'py3.9 can package flask with slim & dockerizePip & slimPatterns & slimPatternsAppendDefaults=false options', - async (t) => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - dockerizePip: 'true', - slim: 'true', - slimPatternsAppendDefaults: 'false', - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true( - zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, - 'pyc files are packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test('pipenv py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { - process.chdir('tests/pipenv'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - - sls(['package'], { - env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true( - zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, - 'pyc files are packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test('poetry py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { - process.chdir('tests/poetry'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - - sls(['package'], { - env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true( - zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, - 'pyc files are packaged' - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('__main__.py')), - [], - '__main__.py files are NOT packaged' - ); - t.end(); -}); - -test('poetry py3.9 can package flask with package individually option', async (t) => { - process.chdir('tests/poetry_individually'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles( - '.serverless/module1-sls-py-req-test-dev-hello.zip' - ); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('py3.9 can package flask with package individually option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { individually: 'true' } }); - const zipfiles_hello = await 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_hello2 = await listZipFiles('.serverless/hello2.zip'); - t.false( - zipfiles_hello2.includes(`fn2${sep}__init__.py`), - 'fn2 is NOT packaged in function hello2' - ); - t.true( - zipfiles_hello2.includes('handler.py'), - 'handler.py is packaged in function hello2' - ); - t.false( - zipfiles_hello2.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello2' - ); - t.true( - zipfiles_hello2.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2' - ); - - const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); - t.false( - zipfiles_hello3.includes(`fn2${sep}__init__.py`), - 'fn2 is NOT packaged in function hello3' - ); - t.true( - zipfiles_hello3.includes('handler.py'), - 'handler.py is packaged in function hello3' - ); - t.false( - zipfiles_hello3.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello3' - ); - t.false( - zipfiles_hello3.includes(`flask${sep}__init__.py`), - 'flask is NOT packaged in function hello3' - ); - - const zipfiles_hello4 = await listZipFiles( - '.serverless/fn2-sls-py-req-test-dev-hello4.zip' - ); - t.false( - zipfiles_hello4.includes(`fn2${sep}__init__.py`), - 'fn2 is NOT packaged in function hello4' - ); - t.true( - zipfiles_hello4.includes('fn2_handler.py'), - 'fn2_handler is packaged in the zip-root 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.end(); -}); - -test('py3.9 can package flask with package individually & slim option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { individually: 'true', slim: 'true' } }); - const zipfiles_hello = await 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' - ); - t.false( - zipfiles_hello.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello' - ); - - const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); - t.true( - 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' - ); - t.false( - zipfiles_hello2.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello2' - ); - - const zipfiles_hello3 = await 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 = await listZipFiles( - '.serverless/fn2-sls-py-req-test-dev-hello4.zip' - ); - t.true( - zipfiles_hello4.includes('fn2_handler.py'), - 'fn2_handler is packaged in the zip-root 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' - ); - - t.end(); -}); - -test('py3.9 can package only requirements of module', async (t) => { - process.chdir('tests/individually'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles_hello = await 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.true( - zipfiles_hello.includes(`boto3${sep}__init__.py`), - 'boto3 is packaged in function hello1' - ); - t.false( - zipfiles_hello.includes(`flask${sep}__init__.py`), - 'flask is NOT packaged in function hello1' - ); - - const zipfiles_hello2 = await 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.false( - zipfiles_hello2.includes(`boto3${sep}__init__.py`), - 'boto3 is NOT packaged in function hello2' - ); - t.true( - zipfiles_hello2.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2' - ); - - t.end(); -}); - -test('py3.9 can package lambda-decorators using vendor and invidiually option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { individually: 'true', vendor: './vendor' } }); - const zipfiles_hello = await listZipFiles('.serverless/hello.zip'); - t.true( - zipfiles_hello.includes('handler.py'), - 'handler.py is packaged at root level in function hello' - ); - t.true( - zipfiles_hello.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello' - ); - t.true( - zipfiles_hello.includes(`lambda_decorators.py`), - 'lambda_decorators.py is packaged in function hello' - ); - t.false( - zipfiles_hello.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello' - ); - - const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); - t.true( - zipfiles_hello2.includes('handler.py'), - 'handler.py is packaged at root level in function hello2' - ); - t.true( - zipfiles_hello2.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2' - ); - t.true( - zipfiles_hello2.includes(`lambda_decorators.py`), - 'lambda_decorators.py is packaged in function hello2' - ); - t.false( - zipfiles_hello2.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello2' - ); - - const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); - t.true( - zipfiles_hello3.includes('handler.py'), - 'handler.py is packaged at root level in function hello3' - ); - t.false( - zipfiles_hello3.includes(`flask${sep}__init__.py`), - 'flask is NOT packaged in function hello3' - ); - t.false( - zipfiles_hello3.includes(`lambda_decorators.py`), - 'lambda_decorators.py is NOT packaged in function hello3' - ); - t.false( - zipfiles_hello3.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello3' - ); - - const zipfiles_hello4 = await listZipFiles( - '.serverless/fn2-sls-py-req-test-dev-hello4.zip' - ); - t.true( - zipfiles_hello4.includes('fn2_handler.py'), - 'fn2_handler is packaged in the zip-root 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.end(); -}); - -test( - "Don't nuke execute perms when using individually", - async (t) => { - process.chdir('tests/individually'); - const { stdout: path } = npm(['pack', '../..']); - const perm = '755'; - writeFileSync(`module1${sep}foobar`, ''); - chmodSync(`module1${sep}foobar`, perm); - - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles_hello1 = await listZipFilesWithMetaData( - '.serverless/hello1.zip' - ); - - t.true( - zipfiles_hello1['module1/foobar'].unixPermissions - .toString(8) - .slice(3, 6) === perm, - 'foobar has retained its executable file permissions' - ); - - const zipfiles_hello2 = await listZipFilesWithMetaData( - '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' - ); - const flaskPerm = statSync( - '.serverless/module2/requirements/bin/flask' - ).mode; - - t.true( - zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, - 'bin/flask has retained its executable file permissions' - ); - - t.end(); - }, - { skip: process.platform === 'win32' } -); - -test( - "Don't nuke execute perms when using individually w/docker", - async (t) => { - process.chdir('tests/individually'); - const { stdout: path } = npm(['pack', '../..']); - const perm = '755'; - writeFileSync(`module1${sep}foobar`, '', { mode: perm }); - chmodSync(`module1${sep}foobar`, perm); - - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true' } }); - const zipfiles_hello = await listZipFilesWithMetaData( - '.serverless/hello1.zip' - ); - - t.true( - zipfiles_hello['module1/foobar'].unixPermissions - .toString(8) - .slice(3, 6) === perm, - 'foobar has retained its executable file permissions' - ); - - const zipfiles_hello2 = await listZipFilesWithMetaData( - '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' - ); - const flaskPerm = statSync( - '.serverless/module2/requirements/bin/flask' - ).mode; - - t.true( - zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, - 'bin/flask has retained its executable file permissions' - ); - - t.end(); - }, - { skip: !canUseDocker() || process.platform === 'win32' } -); - -test( - 'py3.9 can package flask running in docker with module runtime & architecture of function', - async (t) => { - process.chdir('tests/individually_mixed_runtime'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - - sls(['package'], { - env: { dockerizePip: 'true' }, - }); - - const zipfiles_hello2 = await listZipFiles( - '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' - ); - t.true( - zipfiles_hello2.includes('handler2.py'), - 'handler2.py is packaged at root level in function hello2' - ); - t.true( - zipfiles_hello2.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2' - ); - }, - { - skip: !canUseDocker() || process.platform === 'win32', - } -); - -test( - 'py3.9 can package flask succesfully when using mixed architecture, docker and zipping', - async (t) => { - process.chdir('tests/individually_mixed_runtime'); - const { stdout: path } = npm(['pack', '../..']); - - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); - - const zipfiles_hello = await listZipFiles('.serverless/hello1.zip'); - t.true( - zipfiles_hello.includes(`module1${sep}handler1.ts`), - 'handler1.ts is packaged in module dir for hello1' - ); - t.false( - zipfiles_hello.includes('handler2.py'), - 'handler2.py is NOT packaged at root level in function hello1' - ); - t.false( - zipfiles_hello.includes(`flask${sep}__init__.py`), - 'flask is NOT packaged in function hello1' - ); - - const zipfiles_hello2 = await listZipFiles( - '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' - ); - const zippedReqs = await listRequirementsZipFiles( - '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-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(`module1${sep}handler1.ts`), - 'handler1.ts is NOT included at module1 level in hello2' - ); - t.false( - zipfiles_hello2.includes(`pyaml${sep}__init__.py`), - 'pyaml is NOT packaged in function hello2' - ); - t.false( - zipfiles_hello2.includes(`boto3${sep}__init__.py`), - 'boto3 is NOT included in zipfile' - ); - t.true( - zippedReqs.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2 in requirements.zip' - ); - - t.end(); - }, - { skip: !canUseDocker() || process.platform === 'win32' } -); - -test( - 'py3.9 uses download cache by default option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const cachepath = getUserCachePath(); - t.true( - pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), - 'cache directory exists' - ); - t.end(); - }, - { skip: true } -); - -test( - 'py3.9 uses download cache by default', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { cacheLocation: '.requirements-cache' } }); - t.true( - pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), - 'cache directory exists' - ); - t.end(); - }, - { skip: true } -); - -test( - 'py3.9 uses download cache with dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true' } }); - const cachepath = getUserCachePath(); - t.true( - pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), - 'cache directory exists' - ); - t.end(); - }, - // { skip: !canUseDocker() || brokenOn('win32') } - { skip: true } -); - -test( - 'py3.9 uses download cache with dockerizePip by default option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { dockerizePip: 'true', cacheLocation: '.requirements-cache' }, - }); - t.true( - pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), - 'cache directory exists' - ); - t.end(); - }, - // { skip: !canUseDocker() || brokenOn('win32') } - { skip: true } -); - -test( - 'py3.9 uses static and download cache', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const cachepath = getUserCachePath(); - const cacheFolderHash = sha256Path('.serverless/requirements.txt'); - const arch = 'x86_64'; - t.true( - pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), - 'http exists in download-cache' - ); - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` - ), - 'flask exists in static-cache' - ); - t.end(); - }, - { skip: true } -); - -test( - 'py3.9 uses static and download cache with dockerizePip option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true' } }); - const cachepath = getUserCachePath(); - const cacheFolderHash = sha256Path('.serverless/requirements.txt'); - const arch = 'x86_64'; - t.true( - pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), - 'http exists in download-cache' - ); - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` - ), - 'flask exists in static-cache' - ); - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test('py3.9 uses static cache', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const cachepath = getUserCachePath(); - const cacheFolderHash = sha256Path('.serverless/requirements.txt'); - const arch = 'x86_64'; - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` - ), - 'flask exists in static-cache' - ); - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` - ), - '.completed_requirements exists in static-cache' - ); - - // py3.9 checking that static cache actually pulls from cache (by poisoning it) - writeFileSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, - 'injected new file into static cache folder' - ); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('injected_file_is_bad_form'), - "static cache is really used when running 'sls package' again" - ); - - t.end(); -}); - -test('py3.9 uses static cache with cacheLocation option', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - const cachepath = '.requirements-cache'; - sls(['package'], { env: { cacheLocation: cachepath } }); - const cacheFolderHash = sha256Path('.serverless/requirements.txt'); - const arch = 'x86_64'; - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` - ), - 'flask exists in static-cache' - ); - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` - ), - '.completed_requirements exists in static-cache' - ); - t.end(); -}); - -test( - 'py3.9 uses static cache with dockerizePip & slim option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); - const cachepath = getUserCachePath(); - const cacheFolderHash = sha256Path('.serverless/requirements.txt'); - const arch = 'x86_64'; - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` - ), - 'flask exists in static-cache' - ); - t.true( - pathExistsSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` - ), - '.completed_requirements exists in static-cache' - ); - - // py3.9 checking that static cache actually pulls from cache (by poisoning it) - writeFileSync( - `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, - 'injected new file into static cache folder' - ); - sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes('injected_file_is_bad_form'), - "static cache is really used when running 'sls package' again" - ); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files are packaged' - ); - - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test( - 'py3.9 uses download cache with dockerizePip & slim option', - async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); - const cachepath = getUserCachePath(); - t.true( - pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), - 'http exists in download-cache' - ); - - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.deepEqual( - zipfiles.filter((filename) => filename.endsWith('.pyc')), - [], - 'no pyc files are packaged' - ); - - t.end(); - }, - { skip: !canUseDocker() || brokenOn('win32') } -); - -test('py3.9 can ignore functions defined with `image`', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { individually: 'true' } }); - t.true(pathExistsSync('.serverless/hello.zip'), 'function hello is packaged'); - t.true( - pathExistsSync('.serverless/hello2.zip'), - 'function hello2 is packaged' - ); - t.true( - pathExistsSync('.serverless/hello3.zip'), - 'function hello3 is packaged' - ); - t.true( - pathExistsSync('.serverless/hello4.zip'), - 'function hello4 is packaged' - ); - t.false( - pathExistsSync('.serverless/hello5.zip'), - 'function hello5 is not packaged' - ); - - t.end(); -}); - -test('poetry py3.9 fails packaging if poetry.lock is missing and flag requirePoetryLockFile is set to true', async (t) => { - copySync('tests/poetry', 'tests/base with a space'); - process.chdir('tests/base with a space'); - removeSync('poetry.lock'); - - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - const { stderr } = sls(['package'], { - env: { requirePoetryLockFile: 'true', slim: 'true' }, - noThrow: true, - }); - t.true( - stderr.includes( - 'poetry.lock file not found - set requirePoetryLockFile to false to disable this error' - ), - 'flag works and error is properly reported' - ); - t.end(); -}); - -test('works with provider.runtime not being python', async (t) => { - process.chdir('tests/base'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: { runtime: 'nodejs20.x' } }); - t.true( - pathExistsSync('.serverless/sls-py-req-test.zip'), - 'sls-py-req-test is packaged' - ); - t.end(); -}); - -test('poetry py3.9 packages additional optional packages', async (t) => { - process.chdir('tests/poetry_packages'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - poetryWithGroups: 'poetryWithGroups', - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('poetry py3.9 skips additional optional packages specified in withoutGroups', async (t) => { - process.chdir('tests/poetry_packages'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - poetryWithGroups: 'poetryWithGroups', - poetryWithoutGroups: 'poetryWithoutGroups', - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); - t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test('poetry py3.9 only installs optional packages specified in onlyGroups', async (t) => { - process.chdir('tests/poetry_packages'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { - env: { - poetryOnlyGroups: 'poetryOnlyGroups', - }, - }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); - t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); - t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); - t.end(); -}); - -test( - 'py3.7 injects dependencies into `package` folder when using scaleway provider', - async (t) => { - process.chdir('tests/scaleway_provider'); - const { stdout: path } = npm(['pack', '../..']); - npm(['i', path]); - sls(['package'], { env: {} }); - const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); - t.true( - zipfiles.includes(`package${sep}flask${sep}__init__.py`), - 'flask is packaged' - ); - t.true( - zipfiles.includes(`package${sep}boto3${sep}__init__.py`), - 'boto3 is packaged' - ); - t.end(); - }, - { skip: true } // sls v4 supports aws provider only -); +// +// test('default pythonBin can package flask with default options', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('py3.9 packages have the same hash', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const fileHash = sha256File('.serverless/sls-py-req-test.zip'); +// sls(['package'], { env: {} }); +// t.equal( +// sha256File('.serverless/sls-py-req-test.zip'), +// fileHash, +// 'packages have the same hash' +// ); +// t.end(); +// }); +// +// test('py3.9 can package flask with default options', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test( +// 'py3.9 can package flask with hashes', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// fileName: 'requirements-w-hashes.txt', +// pythonBin: getPythonBin(3), +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.end(); +// }, +// { skip: brokenOn('win32') } +// ); +// +// test('py3.9 can package flask with nested', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// fileName: 'requirements-w-nested.txt', +// pythonBin: getPythonBin(3), +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('py3.9 can package flask with zip option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.end(); +// }); +// +// test('py3.9 can package flask with slim option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true', pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, +// '__main__.py files are packaged' +// ); +// t.end(); +// }); +// +// test('py3.9 can package flask with slim & slimPatterns options', async (t) => { +// process.chdir('tests/base'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test("py3.9 doesn't package bottle with noDeploy option", async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// perl([ +// '-p', +// '-i.bak', +// '-e', +// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', +// 'serverless.yml', +// ]); +// sls(['package'], { env: { pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); +// t.end(); +// }); +// +// test('py3.9 can package boto3 with editable', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// fileName: 'requirements-w-editable.txt', +// pythonBin: getPythonBin(3), +// }, +// }); +// 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(); +// }); +// +// test( +// 'py3.9 can package flask with dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test( +// 'py3.9 can package flask with slim & dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// '*.pyc files are NOT packaged' +// ); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > +// 0, +// '__main__.py files are packaged' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test( +// 'py3.9 can package flask with slim & dockerizePip & slimPatterns options', +// async (t) => { +// process.chdir('tests/base'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// '*.pyc files are packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test( +// 'py3.9 can package flask with zip & dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// const zippedReqs = await listRequirementsZipFiles( +// '.serverless/sls-py-req-test.zip' +// ); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true( +// zipfiles.includes(`unzip_requirements.py`), +// 'unzip util is packaged' +// ); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.true( +// zippedReqs.includes(`flask/__init__.py`), +// 'flask is packaged in the .requirements.zip file' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test( +// 'py3.9 can package flask with zip & slim & dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { dockerizePip: 'true', zip: 'true', slim: 'true' }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// const zippedReqs = await listRequirementsZipFiles( +// '.serverless/sls-py-req-test.zip' +// ); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true( +// zipfiles.includes(`unzip_requirements.py`), +// 'unzip util is packaged' +// ); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.true( +// zippedReqs.includes(`flask/__init__.py`), +// 'flask is packaged in the .requirements.zip file' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test('pipenv py3.9 can package flask with default options', async (t) => { +// process.chdir('tests/pipenv'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.false( +// zipfiles.includes(`pytest${sep}__init__.py`), +// 'dev-package pytest is NOT packaged' +// ); +// t.end(); +// }); +// +// test('pipenv py3.9 can package flask with slim option', async (t) => { +// process.chdir('tests/pipenv'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, +// '__main__.py files are packaged' +// ); +// t.end(); +// }); +// +// test('pipenv py3.9 can package flask with slim & slimPatterns options', async (t) => { +// process.chdir('tests/pipenv'); +// +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test('pipenv py3.9 can package flask with zip option', async (t) => { +// process.chdir('tests/pipenv'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.end(); +// }); +// +// test("pipenv py3.9 doesn't package bottle with noDeploy option", async (t) => { +// process.chdir('tests/pipenv'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// perl([ +// '-p', +// '-i.bak', +// '-e', +// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', +// 'serverless.yml', +// ]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); +// t.end(); +// }); +// +// test('non build pyproject.toml uses requirements.txt', async (t) => { +// process.chdir('tests/non_build_pyproject'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('non poetry pyproject.toml without requirements.txt packages handler only', async (t) => { +// process.chdir('tests/non_poetry_pyproject'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`handler.py`), 'handler is packaged'); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with default options', async (t) => { +// process.chdir('tests/poetry'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with slim option', async (t) => { +// process.chdir('tests/poetry'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, +// '__main__.py files are packaged' +// ); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with slim & slimPatterns options', async (t) => { +// process.chdir('tests/poetry'); +// +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with zip option', async (t) => { +// process.chdir('tests/poetry'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.end(); +// }); +// +// test("poetry py3.9 doesn't package bottle with noDeploy option", async (t) => { +// process.chdir('tests/poetry'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// perl([ +// '-p', +// '-i.bak', +// '-e', +// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', +// 'serverless.yml', +// ]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); +// t.end(); +// }); +// +// test('py3.9 can package flask with zip option and no explicit include', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// perl(['-p', '-i.bak', '-e', 's/include://', 'serverless.yml']); +// perl(['-p', '-i.bak', '-e', 's/^.*handler.py.*$//', 'serverless.yml']); +// sls(['package'], { env: { zip: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.end(); +// }); +// +// test('py3.9 can package lambda-decorators using vendor option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { vendor: './vendor' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.true( +// zipfiles.includes(`lambda_decorators.py`), +// 'lambda_decorators.py is packaged' +// ); +// t.end(); +// }); +// +// test( +// "Don't nuke execute perms", +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// const perm = '755'; +// +// npm(['i', path]); +// perl([ +// '-p', +// '-i.bak', +// '-e', +// 's/(handler.py.*$)/$1\n - foobar/', +// 'serverless.yml', +// ]); +// writeFileSync(`foobar`, ''); +// chmodSync(`foobar`, perm); +// sls(['package'], { env: { vendor: './vendor' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.true( +// zipfiles.includes(`lambda_decorators.py`), +// 'lambda_decorators.py is packaged' +// ); +// t.true(zipfiles.includes(`foobar`), 'foobar is packaged'); +// +// const zipfiles_with_metadata = await listZipFilesWithMetaData( +// '.serverless/sls-py-req-test.zip' +// ); +// t.true( +// zipfiles_with_metadata['foobar'].unixPermissions +// .toString(8) +// .slice(3, 6) === perm, +// 'foobar has retained its executable file permissions' +// ); +// +// const flaskPerm = statSync('.serverless/requirements/bin/flask').mode; +// t.true( +// zipfiles_with_metadata['bin/flask'].unixPermissions === flaskPerm, +// 'bin/flask has retained its executable file permissions' +// ); +// +// t.end(); +// }, +// { skip: process.platform === 'win32' } +// ); +// +// test('py3.9 can package flask in a project with a space in it', async (t) => { +// copySync('tests/base', 'tests/base with a space'); +// process.chdir('tests/base with a space'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test( +// 'py3.9 can package flask in a project with a space in it with docker', +// async (t) => { +// copySync('tests/base', 'tests/base with a space'); +// process.chdir('tests/base with a space'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test('py3.9 supports custom file name with fileName option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// writeFileSync('puck', 'requests'); +// npm(['i', path]); +// sls(['package'], { env: { fileName: 'puck' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes(`requests${sep}__init__.py`), +// 'requests is packaged' +// ); +// t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); +// t.false(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is NOT packaged'); +// t.end(); +// }); +// +// test("py3.9 doesn't package bottle with zip option", async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// perl([ +// '-p', +// '-i.bak', +// '-e', +// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', +// 'serverless.yml', +// ]); +// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// const zippedReqs = await listRequirementsZipFiles( +// '.serverless/sls-py-req-test.zip' +// ); +// t.true( +// zipfiles.includes('.requirements.zip'), +// 'zipped requirements are packaged' +// ); +// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); +// t.false( +// zipfiles.includes(`flask${sep}__init__.py`), +// "flask isn't packaged on its own" +// ); +// t.true( +// zippedReqs.includes(`flask/__init__.py`), +// 'flask is packaged in the .requirements.zip file' +// ); +// t.false( +// zippedReqs.includes(`bottle.py`), +// 'bottle is NOT packaged in the .requirements.zip file' +// ); +// t.end(); +// }); +// +// test('py3.9 can package flask with slim, slimPatterns & slimPatternsAppendDefaults=false options', async (t) => { +// process.chdir('tests/base'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, +// 'pyc files are packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test( +// 'py3.9 can package flask with slim & dockerizePip & slimPatterns & slimPatternsAppendDefaults=false options', +// async (t) => { +// process.chdir('tests/base'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// dockerizePip: 'true', +// slim: 'true', +// slimPatternsAppendDefaults: 'false', +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, +// 'pyc files are packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test('pipenv py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { +// process.chdir('tests/pipenv'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// +// sls(['package'], { +// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, +// 'pyc files are packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { +// process.chdir('tests/poetry'); +// copySync('_slimPatterns.yml', 'slimPatterns.yml'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// +// sls(['package'], { +// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true( +// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, +// 'pyc files are packaged' +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('__main__.py')), +// [], +// '__main__.py files are NOT packaged' +// ); +// t.end(); +// }); +// +// test('poetry py3.9 can package flask with package individually option', async (t) => { +// process.chdir('tests/poetry_individually'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles( +// '.serverless/module1-sls-py-req-test-dev-hello.zip' +// ); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('py3.9 can package flask with package individually option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { individually: 'true' } }); +// const zipfiles_hello = await 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_hello2 = await listZipFiles('.serverless/hello2.zip'); +// t.false( +// zipfiles_hello2.includes(`fn2${sep}__init__.py`), +// 'fn2 is NOT packaged in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes('handler.py'), +// 'handler.py is packaged in function hello2' +// ); +// t.false( +// zipfiles_hello2.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello2' +// ); +// +// const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); +// t.false( +// zipfiles_hello3.includes(`fn2${sep}__init__.py`), +// 'fn2 is NOT packaged in function hello3' +// ); +// t.true( +// zipfiles_hello3.includes('handler.py'), +// 'handler.py is packaged in function hello3' +// ); +// t.false( +// zipfiles_hello3.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello3' +// ); +// t.false( +// zipfiles_hello3.includes(`flask${sep}__init__.py`), +// 'flask is NOT packaged in function hello3' +// ); +// +// const zipfiles_hello4 = await listZipFiles( +// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' +// ); +// t.false( +// zipfiles_hello4.includes(`fn2${sep}__init__.py`), +// 'fn2 is NOT packaged in function hello4' +// ); +// t.true( +// zipfiles_hello4.includes('fn2_handler.py'), +// 'fn2_handler is packaged in the zip-root 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.end(); +// }); +// +// test('py3.9 can package flask with package individually & slim option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { individually: 'true', slim: 'true' } }); +// const zipfiles_hello = await 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' +// ); +// t.false( +// zipfiles_hello.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello' +// ); +// +// const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); +// t.true( +// 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' +// ); +// t.false( +// zipfiles_hello2.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello2' +// ); +// +// const zipfiles_hello3 = await 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 = await listZipFiles( +// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' +// ); +// t.true( +// zipfiles_hello4.includes('fn2_handler.py'), +// 'fn2_handler is packaged in the zip-root 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' +// ); +// +// t.end(); +// }); +// +// test('py3.9 can package only requirements of module', async (t) => { +// process.chdir('tests/individually'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles_hello = await 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.true( +// zipfiles_hello.includes(`boto3${sep}__init__.py`), +// 'boto3 is packaged in function hello1' +// ); +// t.false( +// zipfiles_hello.includes(`flask${sep}__init__.py`), +// 'flask is NOT packaged in function hello1' +// ); +// +// const zipfiles_hello2 = await 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.false( +// zipfiles_hello2.includes(`boto3${sep}__init__.py`), +// 'boto3 is NOT packaged in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello2' +// ); +// +// t.end(); +// }); +// +// test('py3.9 can package lambda-decorators using vendor and invidiually option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { individually: 'true', vendor: './vendor' } }); +// const zipfiles_hello = await listZipFiles('.serverless/hello.zip'); +// t.true( +// zipfiles_hello.includes('handler.py'), +// 'handler.py is packaged at root level in function hello' +// ); +// t.true( +// zipfiles_hello.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello' +// ); +// t.true( +// zipfiles_hello.includes(`lambda_decorators.py`), +// 'lambda_decorators.py is packaged in function hello' +// ); +// t.false( +// zipfiles_hello.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello' +// ); +// +// const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); +// t.true( +// zipfiles_hello2.includes('handler.py'), +// 'handler.py is packaged at root level in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes(`lambda_decorators.py`), +// 'lambda_decorators.py is packaged in function hello2' +// ); +// t.false( +// zipfiles_hello2.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello2' +// ); +// +// const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); +// t.true( +// zipfiles_hello3.includes('handler.py'), +// 'handler.py is packaged at root level in function hello3' +// ); +// t.false( +// zipfiles_hello3.includes(`flask${sep}__init__.py`), +// 'flask is NOT packaged in function hello3' +// ); +// t.false( +// zipfiles_hello3.includes(`lambda_decorators.py`), +// 'lambda_decorators.py is NOT packaged in function hello3' +// ); +// t.false( +// zipfiles_hello3.includes(`dataclasses.py`), +// 'dataclasses is NOT packaged in function hello3' +// ); +// +// const zipfiles_hello4 = await listZipFiles( +// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' +// ); +// t.true( +// zipfiles_hello4.includes('fn2_handler.py'), +// 'fn2_handler is packaged in the zip-root 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.end(); +// }); +// +// test( +// "Don't nuke execute perms when using individually", +// async (t) => { +// process.chdir('tests/individually'); +// const { stdout: path } = npm(['pack', '../..']); +// const perm = '755'; +// writeFileSync(`module1${sep}foobar`, ''); +// chmodSync(`module1${sep}foobar`, perm); +// +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles_hello1 = await listZipFilesWithMetaData( +// '.serverless/hello1.zip' +// ); +// +// t.true( +// zipfiles_hello1['module1/foobar'].unixPermissions +// .toString(8) +// .slice(3, 6) === perm, +// 'foobar has retained its executable file permissions' +// ); +// +// const zipfiles_hello2 = await listZipFilesWithMetaData( +// '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' +// ); +// const flaskPerm = statSync( +// '.serverless/module2/requirements/bin/flask' +// ).mode; +// +// t.true( +// zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, +// 'bin/flask has retained its executable file permissions' +// ); +// +// t.end(); +// }, +// { skip: process.platform === 'win32' } +// ); +// +// test( +// "Don't nuke execute perms when using individually w/docker", +// async (t) => { +// process.chdir('tests/individually'); +// const { stdout: path } = npm(['pack', '../..']); +// const perm = '755'; +// writeFileSync(`module1${sep}foobar`, '', { mode: perm }); +// chmodSync(`module1${sep}foobar`, perm); +// +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true' } }); +// const zipfiles_hello = await listZipFilesWithMetaData( +// '.serverless/hello1.zip' +// ); +// +// t.true( +// zipfiles_hello['module1/foobar'].unixPermissions +// .toString(8) +// .slice(3, 6) === perm, +// 'foobar has retained its executable file permissions' +// ); +// +// const zipfiles_hello2 = await listZipFilesWithMetaData( +// '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' +// ); +// const flaskPerm = statSync( +// '.serverless/module2/requirements/bin/flask' +// ).mode; +// +// t.true( +// zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, +// 'bin/flask has retained its executable file permissions' +// ); +// +// t.end(); +// }, +// { skip: !canUseDocker() || process.platform === 'win32' } +// ); +// +// test( +// 'py3.9 can package flask running in docker with module runtime & architecture of function', +// async (t) => { +// process.chdir('tests/individually_mixed_runtime'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// +// sls(['package'], { +// env: { dockerizePip: 'true' }, +// }); +// +// const zipfiles_hello2 = await listZipFiles( +// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' +// ); +// t.true( +// zipfiles_hello2.includes('handler2.py'), +// 'handler2.py is packaged at root level in function hello2' +// ); +// t.true( +// zipfiles_hello2.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello2' +// ); +// }, +// { +// skip: !canUseDocker() || process.platform === 'win32', +// } +// ); +// +// test( +// 'py3.9 can package flask succesfully when using mixed architecture, docker and zipping', +// async (t) => { +// process.chdir('tests/individually_mixed_runtime'); +// const { stdout: path } = npm(['pack', '../..']); +// +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); +// +// const zipfiles_hello = await listZipFiles('.serverless/hello1.zip'); +// t.true( +// zipfiles_hello.includes(`module1${sep}handler1.ts`), +// 'handler1.ts is packaged in module dir for hello1' +// ); +// t.false( +// zipfiles_hello.includes('handler2.py'), +// 'handler2.py is NOT packaged at root level in function hello1' +// ); +// t.false( +// zipfiles_hello.includes(`flask${sep}__init__.py`), +// 'flask is NOT packaged in function hello1' +// ); +// +// const zipfiles_hello2 = await listZipFiles( +// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' +// ); +// const zippedReqs = await listRequirementsZipFiles( +// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-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(`module1${sep}handler1.ts`), +// 'handler1.ts is NOT included at module1 level in hello2' +// ); +// t.false( +// zipfiles_hello2.includes(`pyaml${sep}__init__.py`), +// 'pyaml is NOT packaged in function hello2' +// ); +// t.false( +// zipfiles_hello2.includes(`boto3${sep}__init__.py`), +// 'boto3 is NOT included in zipfile' +// ); +// t.true( +// zippedReqs.includes(`flask${sep}__init__.py`), +// 'flask is packaged in function hello2 in requirements.zip' +// ); +// +// t.end(); +// }, +// { skip: !canUseDocker() || process.platform === 'win32' } +// ); +// +// test( +// 'py3.9 uses download cache by default option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const cachepath = getUserCachePath(); +// t.true( +// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), +// 'cache directory exists' +// ); +// t.end(); +// }, +// { skip: true } +// ); +// +// test( +// 'py3.9 uses download cache by default', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { cacheLocation: '.requirements-cache' } }); +// t.true( +// pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), +// 'cache directory exists' +// ); +// t.end(); +// }, +// { skip: true } +// ); +// +// test( +// 'py3.9 uses download cache with dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true' } }); +// const cachepath = getUserCachePath(); +// t.true( +// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), +// 'cache directory exists' +// ); +// t.end(); +// }, +// // { skip: !canUseDocker() || brokenOn('win32') } +// { skip: true } +// ); +// +// test( +// 'py3.9 uses download cache with dockerizePip by default option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { dockerizePip: 'true', cacheLocation: '.requirements-cache' }, +// }); +// t.true( +// pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), +// 'cache directory exists' +// ); +// t.end(); +// }, +// // { skip: !canUseDocker() || brokenOn('win32') } +// { skip: true } +// ); +// +// test( +// 'py3.9 uses static and download cache', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const cachepath = getUserCachePath(); +// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); +// const arch = 'x86_64'; +// t.true( +// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), +// 'http exists in download-cache' +// ); +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` +// ), +// 'flask exists in static-cache' +// ); +// t.end(); +// }, +// { skip: true } +// ); +// +// test( +// 'py3.9 uses static and download cache with dockerizePip option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true' } }); +// const cachepath = getUserCachePath(); +// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); +// const arch = 'x86_64'; +// t.true( +// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), +// 'http exists in download-cache' +// ); +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` +// ), +// 'flask exists in static-cache' +// ); +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test('py3.9 uses static cache', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const cachepath = getUserCachePath(); +// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); +// const arch = 'x86_64'; +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` +// ), +// 'flask exists in static-cache' +// ); +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` +// ), +// '.completed_requirements exists in static-cache' +// ); +// +// // py3.9 checking that static cache actually pulls from cache (by poisoning it) +// writeFileSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, +// 'injected new file into static cache folder' +// ); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('injected_file_is_bad_form'), +// "static cache is really used when running 'sls package' again" +// ); +// +// t.end(); +// }); +// +// test('py3.9 uses static cache with cacheLocation option', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// const cachepath = '.requirements-cache'; +// sls(['package'], { env: { cacheLocation: cachepath } }); +// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); +// const arch = 'x86_64'; +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` +// ), +// 'flask exists in static-cache' +// ); +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` +// ), +// '.completed_requirements exists in static-cache' +// ); +// t.end(); +// }); +// +// test( +// 'py3.9 uses static cache with dockerizePip & slim option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); +// const cachepath = getUserCachePath(); +// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); +// const arch = 'x86_64'; +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` +// ), +// 'flask exists in static-cache' +// ); +// t.true( +// pathExistsSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` +// ), +// '.completed_requirements exists in static-cache' +// ); +// +// // py3.9 checking that static cache actually pulls from cache (by poisoning it) +// writeFileSync( +// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, +// 'injected new file into static cache folder' +// ); +// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes('injected_file_is_bad_form'), +// "static cache is really used when running 'sls package' again" +// ); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files are packaged' +// ); +// +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test( +// 'py3.9 uses download cache with dockerizePip & slim option', +// async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); +// const cachepath = getUserCachePath(); +// t.true( +// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), +// 'http exists in download-cache' +// ); +// +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.deepEqual( +// zipfiles.filter((filename) => filename.endsWith('.pyc')), +// [], +// 'no pyc files are packaged' +// ); +// +// t.end(); +// }, +// { skip: !canUseDocker() || brokenOn('win32') } +// ); +// +// test('py3.9 can ignore functions defined with `image`', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { individually: 'true' } }); +// t.true(pathExistsSync('.serverless/hello.zip'), 'function hello is packaged'); +// t.true( +// pathExistsSync('.serverless/hello2.zip'), +// 'function hello2 is packaged' +// ); +// t.true( +// pathExistsSync('.serverless/hello3.zip'), +// 'function hello3 is packaged' +// ); +// t.true( +// pathExistsSync('.serverless/hello4.zip'), +// 'function hello4 is packaged' +// ); +// t.false( +// pathExistsSync('.serverless/hello5.zip'), +// 'function hello5 is not packaged' +// ); +// +// t.end(); +// }); + +// test('poetry py3.9 fails packaging if poetry.lock is missing and flag requirePoetryLockFile is set to true', async (t) => { +// copySync('tests/poetry', 'tests/base with a space'); +// process.chdir('tests/base with a space'); +// removeSync('poetry.lock'); +// +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// const { stderr } = sls(['package'], { +// env: { requirePoetryLockFile: 'true', slim: 'true' }, +// noThrow: true, +// }); +// t.true( +// stderr.includes( +// 'poetry.lock file not found - set requirePoetryLockFile to false to disable this error' +// ), +// 'flag works and error is properly reported' +// ); +// t.end(); +// }); + +// test('works with provider.runtime not being python', async (t) => { +// process.chdir('tests/base'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: { runtime: 'nodejs20.x' } }); +// t.true( +// pathExistsSync('.serverless/sls-py-req-test.zip'), +// 'sls-py-req-test is packaged' +// ); +// t.end(); +// }); +// +// test('poetry py3.9 packages additional optional packages', async (t) => { +// process.chdir('tests/poetry_packages'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// poetryWithGroups: 'poetryWithGroups', +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('poetry py3.9 skips additional optional packages specified in withoutGroups', async (t) => { +// process.chdir('tests/poetry_packages'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// poetryWithGroups: 'poetryWithGroups', +// poetryWithoutGroups: 'poetryWithoutGroups', +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); +// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test('poetry py3.9 only installs optional packages specified in onlyGroups', async (t) => { +// process.chdir('tests/poetry_packages'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { +// env: { +// poetryOnlyGroups: 'poetryOnlyGroups', +// }, +// }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); +// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); +// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); +// t.end(); +// }); +// +// test( +// 'py3.7 injects dependencies into `package` folder when using scaleway provider', +// async (t) => { +// process.chdir('tests/scaleway_provider'); +// const { stdout: path } = npm(['pack', '../..']); +// npm(['i', path]); +// sls(['package'], { env: {} }); +// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); +// t.true( +// zipfiles.includes(`package${sep}flask${sep}__init__.py`), +// 'flask is packaged' +// ); +// t.true( +// zipfiles.includes(`package${sep}boto3${sep}__init__.py`), +// 'boto3 is packaged' +// ); +// t.end(); +// }, +// { skip: true } // sls v4 supports aws provider only +// ); diff --git a/tests/base/handler.py b/tests/base/handler.py index ba39cf69..5e2e67ff 100644 --- a/tests/base/handler.py +++ b/tests/base/handler.py @@ -1,4 +1,5 @@ import requests + def hello(event, context): return requests.get('https://httpbin.org/get').json() diff --git a/tests/base/package.json b/tests/base/package.json index b07744c9..dceb03e8 100644 --- a/tests/base/package.json +++ b/tests/base/package.json @@ -9,6 +9,6 @@ "author": "", "license": "ISC", "dependencies": { - "serverless-python-requirements": "file:serverless-python-requirements-6.0.1.tgz" + "serverless-python-requirements": "file:serverless-python-requirements-6.1.1.tgz" } } From 8a59b56decb57fe5cc06efca632c69ab3f601a16 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 17:24:53 +0100 Subject: [PATCH 10/17] fix: Run prettier --- test.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test.js b/test.js index 7d7a3240..f3bbb5b3 100644 --- a/test.js +++ b/test.js @@ -215,7 +215,9 @@ test( dockerImage: 'break the build to log the command', }, }); - console.log(`-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z`) + console.log( + `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` + ); console.log('stderr', stderr); t.true( stderr.includes( From a2a0d4e0a7cab9d740c4ae5cae8713b3d96378f9 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 17:43:50 +0100 Subject: [PATCH 11/17] fix: Run prettier --- test.js | 64 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/test.js b/test.js index f3bbb5b3..05868af5 100644 --- a/test.js +++ b/test.js @@ -1,22 +1,22 @@ const crossSpawn = require('cross-spawn'); const glob = require('glob-all'); const JSZip = require('jszip'); -const sha256File = require('sha256-file'); +// const sha256File = require('sha256-file'); const tape = require('tape-promise/tape'); const { - chmodSync, + // chmodSync, removeSync, readFile, copySync, - writeFileSync, - statSync, - pathExistsSync, + // writeFileSync, + // statSync, + // pathExistsSync, } = require('fs-extra'); const { quote } = require('shell-quote'); const { sep } = require('path'); -const { getUserCachePath, sha256Path } = require('./lib/shared'); +const { getUserCachePath } = require('./lib/shared'); const initialWorkingDir = process.cwd(); @@ -53,7 +53,7 @@ const mkCommand = const sls = mkCommand('sls'); const git = mkCommand('git'); const npm = mkCommand('npm'); -const perl = mkCommand('perl'); +// const perl = mkCommand('perl'); const setup = () => { removeSync(getUserCachePath()); @@ -161,31 +161,31 @@ const availablePythons = (() => { return mapping; })(); -const getPythonBin = (version) => { - const bin = availablePythons[String(version)]; - if (!bin) throw new Error(`No python version ${version} available`); - return bin; -}; - -const listZipFiles = async function (filename) { - const file = await readFile(filename); - const zip = await new JSZip().loadAsync(file); - return Object.keys(zip.files); -}; - -const listZipFilesWithMetaData = async function (filename) { - const file = await readFile(filename); - const zip = await new JSZip().loadAsync(file); - return Object(zip.files); -}; - -const listRequirementsZipFiles = async function (filename) { - const file = await readFile(filename); - const zip = await new JSZip().loadAsync(file); - const reqsBuffer = await zip.file('.requirements.zip').async('nodebuffer'); - const reqsZip = await new JSZip().loadAsync(reqsBuffer); - return Object.keys(reqsZip.files); -}; +// const getPythonBin = (version) => { +// const bin = availablePythons[String(version)]; +// if (!bin) throw new Error(`No python version ${version} available`); +// return bin; +// }; +// +// const listZipFiles = async function (filename) { +// const file = await readFile(filename); +// const zip = await new JSZip().loadAsync(file); +// return Object.keys(zip.files); +// }; +// +// const listZipFilesWithMetaData = async function (filename) { +// const file = await readFile(filename); +// const zip = await new JSZip().loadAsync(file); +// return Object(zip.files); +// }; +// +// const listRequirementsZipFiles = async function (filename) { +// const file = await readFile(filename); +// const zip = await new JSZip().loadAsync(file); +// const reqsBuffer = await zip.file('.requirements.zip').async('nodebuffer'); +// const reqsZip = await new JSZip().loadAsync(reqsBuffer); +// return Object.keys(reqsZip.files); +// }; const canUseDocker = () => { let result; From fe884de7bbd86b95446f9f7341e254cf59f1315b Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 17:46:40 +0100 Subject: [PATCH 12/17] fix: Run prettier --- test.js | 70 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/test.js b/test.js index 05868af5..77c39940 100644 --- a/test.js +++ b/test.js @@ -1,14 +1,14 @@ const crossSpawn = require('cross-spawn'); const glob = require('glob-all'); -const JSZip = require('jszip'); +// const JSZip = require('jszip'); // const sha256File = require('sha256-file'); const tape = require('tape-promise/tape'); const { // chmodSync, removeSync, - readFile, - copySync, + // readFile, + // copySync, // writeFileSync, // statSync, // pathExistsSync, @@ -128,38 +128,38 @@ const test = (desc, func, opts = {}) => } }); -const availablePythons = (() => { - const binaries = []; - const mapping = {}; - if (process.env.USE_PYTHON) { - binaries.push( - ...process.env.USE_PYTHON.split(',').map((v) => v.toString().trim()) - ); - } else { - // For running outside of CI - binaries.push('python'); - } - const exe = process.platform === 'win32' ? '.exe' : ''; - for (const bin of binaries) { - const python = `${bin}${exe}`; - const { stdout, status } = crossSpawn.sync(python, [ - '-c', - 'import sys; sys.stdout.write(".".join(map(str, sys.version_info[:2])))', - ]); - const ver = stdout && stdout.toString().trim(); - if (!status && ver) { - for (const recommend of [ver, ver.split('.')[0]]) { - if (!mapping[recommend]) { - mapping[recommend] = python; - } - } - } - } - if (!Object.entries(mapping).length) { - throw new Error('No pythons found'); - } - return mapping; -})(); +// const availablePythons = (() => { +// const binaries = []; +// const mapping = {}; +// if (process.env.USE_PYTHON) { +// binaries.push( +// ...process.env.USE_PYTHON.split(',').map((v) => v.toString().trim()) +// ); +// } else { +// // For running outside of CI +// binaries.push('python3'); +// } +// const exe = process.platform === 'win32' ? '.exe' : ''; +// for (const bin of binaries) { +// const python = `${bin}${exe}`; +// const { stdout, status } = crossSpawn.sync(python, [ +// '-c', +// 'import sys; sys.stdout.write(".".join(map(str, sys.version_info[:2])))', +// ]); +// const ver = stdout && stdout.toString().trim(); +// if (!status && ver) { +// for (const recommend of [ver, ver.split('.')[0]]) { +// if (!mapping[recommend]) { +// mapping[recommend] = python; +// } +// } +// } +// } +// if (!Object.entries(mapping).length) { +// throw new Error('No pythons found'); +// } +// return mapping; +// })(); // const getPythonBin = (version) => { // const bin = availablePythons[String(version)]; From 684d29b7b425ab23ab079ab46fb203fabcc5a2ef Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 17:55:02 +0100 Subject: [PATCH 13/17] fix: Remove peerDependencies --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 07466e23..f5754f24 100644 --- a/package.json +++ b/package.json @@ -77,9 +77,6 @@ "sha256-file": "1.0.0", "shell-quote": "^1.8.1" }, - "peerDependencies": { - "serverless": ">=2.32" - }, "lint-staged": { "*.js": [ "eslint" From 12c60025e5f03fed8cfe4f1d448cb4e3f6cab907 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 18:01:51 +0100 Subject: [PATCH 14/17] fix: Use stdout instead of stdout --- test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test.js b/test.js index 77c39940..c4b977f3 100644 --- a/test.js +++ b/test.js @@ -206,7 +206,7 @@ test( process.chdir('tests/base'); const { stdout: path } = npm(['pack', '../..']); npm(['i', path]); - const { stderr } = sls(['package'], { + const { stderr, stdout } = sls(['package'], { noThrow: true, env: { dockerizePip: true, @@ -219,8 +219,9 @@ test( `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` ); console.log('stderr', stderr); + console.log('stdout', stdout); t.true( - stderr.includes( + stdout.includes( `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` ), 'docker command properly resolved' From ba129c1671552929e9b30625e421fc5b8a659c5c Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 18:16:21 +0100 Subject: [PATCH 15/17] fix: Use stdout instead of stdout --- lib/inject.js | 1 - test.js | 3367 +++++++++++++++++++-------------------- tests/base/package.json | 2 +- 3 files changed, 1683 insertions(+), 1687 deletions(-) diff --git a/lib/inject.js b/lib/inject.js index 5733241b..f4acde9d 100644 --- a/lib/inject.js +++ b/lib/inject.js @@ -150,7 +150,6 @@ async function injectAllRequirements(funcArtifact) { } }) .map((func) => { - console.log('func.module', func.module); return this.options.zip ? func : injectRequirements( diff --git a/test.js b/test.js index c4b977f3..e6c89d10 100644 --- a/test.js +++ b/test.js @@ -1,22 +1,22 @@ const crossSpawn = require('cross-spawn'); const glob = require('glob-all'); -// const JSZip = require('jszip'); -// const sha256File = require('sha256-file'); +const JSZip = require('jszip'); +const sha256File = require('sha256-file'); const tape = require('tape-promise/tape'); const { - // chmodSync, + chmodSync, removeSync, - // readFile, - // copySync, - // writeFileSync, - // statSync, - // pathExistsSync, + readFile, + copySync, + writeFileSync, + statSync, + pathExistsSync, } = require('fs-extra'); const { quote } = require('shell-quote'); const { sep } = require('path'); -const { getUserCachePath } = require('./lib/shared'); +const { getUserCachePath, sha256Path } = require('./lib/shared'); const initialWorkingDir = process.cwd(); @@ -53,7 +53,7 @@ const mkCommand = const sls = mkCommand('sls'); const git = mkCommand('git'); const npm = mkCommand('npm'); -// const perl = mkCommand('perl'); +const perl = mkCommand('perl'); const setup = () => { removeSync(getUserCachePath()); @@ -128,64 +128,64 @@ const test = (desc, func, opts = {}) => } }); -// const availablePythons = (() => { -// const binaries = []; -// const mapping = {}; -// if (process.env.USE_PYTHON) { -// binaries.push( -// ...process.env.USE_PYTHON.split(',').map((v) => v.toString().trim()) -// ); -// } else { -// // For running outside of CI -// binaries.push('python3'); -// } -// const exe = process.platform === 'win32' ? '.exe' : ''; -// for (const bin of binaries) { -// const python = `${bin}${exe}`; -// const { stdout, status } = crossSpawn.sync(python, [ -// '-c', -// 'import sys; sys.stdout.write(".".join(map(str, sys.version_info[:2])))', -// ]); -// const ver = stdout && stdout.toString().trim(); -// if (!status && ver) { -// for (const recommend of [ver, ver.split('.')[0]]) { -// if (!mapping[recommend]) { -// mapping[recommend] = python; -// } -// } -// } -// } -// if (!Object.entries(mapping).length) { -// throw new Error('No pythons found'); -// } -// return mapping; -// })(); - -// const getPythonBin = (version) => { -// const bin = availablePythons[String(version)]; -// if (!bin) throw new Error(`No python version ${version} available`); -// return bin; -// }; -// -// const listZipFiles = async function (filename) { -// const file = await readFile(filename); -// const zip = await new JSZip().loadAsync(file); -// return Object.keys(zip.files); -// }; -// -// const listZipFilesWithMetaData = async function (filename) { -// const file = await readFile(filename); -// const zip = await new JSZip().loadAsync(file); -// return Object(zip.files); -// }; -// -// const listRequirementsZipFiles = async function (filename) { -// const file = await readFile(filename); -// const zip = await new JSZip().loadAsync(file); -// const reqsBuffer = await zip.file('.requirements.zip').async('nodebuffer'); -// const reqsZip = await new JSZip().loadAsync(reqsBuffer); -// return Object.keys(reqsZip.files); -// }; +const availablePythons = (() => { + const binaries = []; + const mapping = {}; + if (process.env.USE_PYTHON) { + binaries.push( + ...process.env.USE_PYTHON.split(',').map((v) => v.toString().trim()) + ); + } else { + // For running outside of CI + binaries.push('python3'); + } + const exe = process.platform === 'win32' ? '.exe' : ''; + for (const bin of binaries) { + const python = `${bin}${exe}`; + const { stdout, status } = crossSpawn.sync(python, [ + '-c', + 'import sys; sys.stdout.write(".".join(map(str, sys.version_info[:2])))', + ]); + const ver = stdout && stdout.toString().trim(); + if (!status && ver) { + for (const recommend of [ver, ver.split('.')[0]]) { + if (!mapping[recommend]) { + mapping[recommend] = python; + } + } + } + } + if (!Object.entries(mapping).length) { + throw new Error('No pythons found'); + } + return mapping; +})(); + +const getPythonBin = (version) => { + const bin = availablePythons[String(version)]; + if (!bin) throw new Error(`No python version ${version} available`); + return bin; +}; + +const listZipFiles = async function (filename) { + const file = await readFile(filename); + const zip = await new JSZip().loadAsync(file); + return Object.keys(zip.files); +}; + +const listZipFilesWithMetaData = async function (filename) { + const file = await readFile(filename); + const zip = await new JSZip().loadAsync(file); + return Object(zip.files); +}; + +const listRequirementsZipFiles = async function (filename) { + const file = await readFile(filename); + const zip = await new JSZip().loadAsync(file); + const reqsBuffer = await zip.file('.requirements.zip').async('nodebuffer'); + const reqsZip = await new JSZip().loadAsync(reqsBuffer); + return Object.keys(reqsZip.files); +}; const canUseDocker = () => { let result; @@ -206,7 +206,7 @@ test( process.chdir('tests/base'); const { stdout: path } = npm(['pack', '../..']); npm(['i', path]); - const { stderr, stdout } = sls(['package'], { + const { stdout } = sls(['package'], { noThrow: true, env: { dockerizePip: true, @@ -215,11 +215,6 @@ test( dockerImage: 'break the build to log the command', }, }); - console.log( - `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` - ); - console.log('stderr', stderr); - console.log('stdout', stdout); t.true( stdout.includes( `-v ${__dirname}${sep}tests${sep}base${sep}custom_ssh:/root/.ssh/custom_ssh:z` @@ -230,1614 +225,1616 @@ test( }, { skip: !canUseDocker() || brokenOn('win32') } ); -// -// test('default pythonBin can package flask with default options', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('py3.9 packages have the same hash', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const fileHash = sha256File('.serverless/sls-py-req-test.zip'); -// sls(['package'], { env: {} }); -// t.equal( -// sha256File('.serverless/sls-py-req-test.zip'), -// fileHash, -// 'packages have the same hash' -// ); -// t.end(); -// }); -// -// test('py3.9 can package flask with default options', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test( -// 'py3.9 can package flask with hashes', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// fileName: 'requirements-w-hashes.txt', -// pythonBin: getPythonBin(3), -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.end(); -// }, -// { skip: brokenOn('win32') } -// ); -// -// test('py3.9 can package flask with nested', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// fileName: 'requirements-w-nested.txt', -// pythonBin: getPythonBin(3), -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('py3.9 can package flask with zip option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.end(); -// }); -// -// test('py3.9 can package flask with slim option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true', pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, -// '__main__.py files are packaged' -// ); -// t.end(); -// }); -// -// test('py3.9 can package flask with slim & slimPatterns options', async (t) => { -// process.chdir('tests/base'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test("py3.9 doesn't package bottle with noDeploy option", async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// perl([ -// '-p', -// '-i.bak', -// '-e', -// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', -// 'serverless.yml', -// ]); -// sls(['package'], { env: { pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); -// t.end(); -// }); -// -// test('py3.9 can package boto3 with editable', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// fileName: 'requirements-w-editable.txt', -// pythonBin: getPythonBin(3), -// }, -// }); -// 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(); -// }); -// -// test( -// 'py3.9 can package flask with dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test( -// 'py3.9 can package flask with slim & dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// '*.pyc files are NOT packaged' -// ); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > -// 0, -// '__main__.py files are packaged' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test( -// 'py3.9 can package flask with slim & dockerizePip & slimPatterns options', -// async (t) => { -// process.chdir('tests/base'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// '*.pyc files are packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test( -// 'py3.9 can package flask with zip & dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// const zippedReqs = await listRequirementsZipFiles( -// '.serverless/sls-py-req-test.zip' -// ); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true( -// zipfiles.includes(`unzip_requirements.py`), -// 'unzip util is packaged' -// ); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.true( -// zippedReqs.includes(`flask/__init__.py`), -// 'flask is packaged in the .requirements.zip file' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test( -// 'py3.9 can package flask with zip & slim & dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { dockerizePip: 'true', zip: 'true', slim: 'true' }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// const zippedReqs = await listRequirementsZipFiles( -// '.serverless/sls-py-req-test.zip' -// ); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true( -// zipfiles.includes(`unzip_requirements.py`), -// 'unzip util is packaged' -// ); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.true( -// zippedReqs.includes(`flask/__init__.py`), -// 'flask is packaged in the .requirements.zip file' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test('pipenv py3.9 can package flask with default options', async (t) => { -// process.chdir('tests/pipenv'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.false( -// zipfiles.includes(`pytest${sep}__init__.py`), -// 'dev-package pytest is NOT packaged' -// ); -// t.end(); -// }); -// -// test('pipenv py3.9 can package flask with slim option', async (t) => { -// process.chdir('tests/pipenv'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, -// '__main__.py files are packaged' -// ); -// t.end(); -// }); -// -// test('pipenv py3.9 can package flask with slim & slimPatterns options', async (t) => { -// process.chdir('tests/pipenv'); -// -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test('pipenv py3.9 can package flask with zip option', async (t) => { -// process.chdir('tests/pipenv'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.end(); -// }); -// -// test("pipenv py3.9 doesn't package bottle with noDeploy option", async (t) => { -// process.chdir('tests/pipenv'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// perl([ -// '-p', -// '-i.bak', -// '-e', -// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', -// 'serverless.yml', -// ]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); -// t.end(); -// }); -// -// test('non build pyproject.toml uses requirements.txt', async (t) => { -// process.chdir('tests/non_build_pyproject'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('non poetry pyproject.toml without requirements.txt packages handler only', async (t) => { -// process.chdir('tests/non_poetry_pyproject'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`handler.py`), 'handler is packaged'); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with default options', async (t) => { -// process.chdir('tests/poetry'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with slim option', async (t) => { -// process.chdir('tests/poetry'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, -// '__main__.py files are packaged' -// ); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with slim & slimPatterns options', async (t) => { -// process.chdir('tests/poetry'); -// -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with zip option', async (t) => { -// process.chdir('tests/poetry'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.end(); -// }); -// -// test("poetry py3.9 doesn't package bottle with noDeploy option", async (t) => { -// process.chdir('tests/poetry'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// perl([ -// '-p', -// '-i.bak', -// '-e', -// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', -// 'serverless.yml', -// ]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); -// t.end(); -// }); -// -// test('py3.9 can package flask with zip option and no explicit include', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// perl(['-p', '-i.bak', '-e', 's/include://', 'serverless.yml']); -// perl(['-p', '-i.bak', '-e', 's/^.*handler.py.*$//', 'serverless.yml']); -// sls(['package'], { env: { zip: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.end(); -// }); -// -// test('py3.9 can package lambda-decorators using vendor option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { vendor: './vendor' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.true( -// zipfiles.includes(`lambda_decorators.py`), -// 'lambda_decorators.py is packaged' -// ); -// t.end(); -// }); -// -// test( -// "Don't nuke execute perms", -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// const perm = '755'; -// -// npm(['i', path]); -// perl([ -// '-p', -// '-i.bak', -// '-e', -// 's/(handler.py.*$)/$1\n - foobar/', -// 'serverless.yml', -// ]); -// writeFileSync(`foobar`, ''); -// chmodSync(`foobar`, perm); -// sls(['package'], { env: { vendor: './vendor' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.true( -// zipfiles.includes(`lambda_decorators.py`), -// 'lambda_decorators.py is packaged' -// ); -// t.true(zipfiles.includes(`foobar`), 'foobar is packaged'); -// -// const zipfiles_with_metadata = await listZipFilesWithMetaData( -// '.serverless/sls-py-req-test.zip' -// ); -// t.true( -// zipfiles_with_metadata['foobar'].unixPermissions -// .toString(8) -// .slice(3, 6) === perm, -// 'foobar has retained its executable file permissions' -// ); -// -// const flaskPerm = statSync('.serverless/requirements/bin/flask').mode; -// t.true( -// zipfiles_with_metadata['bin/flask'].unixPermissions === flaskPerm, -// 'bin/flask has retained its executable file permissions' -// ); -// -// t.end(); -// }, -// { skip: process.platform === 'win32' } -// ); -// -// test('py3.9 can package flask in a project with a space in it', async (t) => { -// copySync('tests/base', 'tests/base with a space'); -// process.chdir('tests/base with a space'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test( -// 'py3.9 can package flask in a project with a space in it with docker', -// async (t) => { -// copySync('tests/base', 'tests/base with a space'); -// process.chdir('tests/base with a space'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test('py3.9 supports custom file name with fileName option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// writeFileSync('puck', 'requests'); -// npm(['i', path]); -// sls(['package'], { env: { fileName: 'puck' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes(`requests${sep}__init__.py`), -// 'requests is packaged' -// ); -// t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); -// t.false(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is NOT packaged'); -// t.end(); -// }); -// -// test("py3.9 doesn't package bottle with zip option", async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// perl([ -// '-p', -// '-i.bak', -// '-e', -// 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', -// 'serverless.yml', -// ]); -// sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// const zippedReqs = await listRequirementsZipFiles( -// '.serverless/sls-py-req-test.zip' -// ); -// t.true( -// zipfiles.includes('.requirements.zip'), -// 'zipped requirements are packaged' -// ); -// t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); -// t.false( -// zipfiles.includes(`flask${sep}__init__.py`), -// "flask isn't packaged on its own" -// ); -// t.true( -// zippedReqs.includes(`flask/__init__.py`), -// 'flask is packaged in the .requirements.zip file' -// ); -// t.false( -// zippedReqs.includes(`bottle.py`), -// 'bottle is NOT packaged in the .requirements.zip file' -// ); -// t.end(); -// }); -// -// test('py3.9 can package flask with slim, slimPatterns & slimPatternsAppendDefaults=false options', async (t) => { -// process.chdir('tests/base'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, -// 'pyc files are packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test( -// 'py3.9 can package flask with slim & dockerizePip & slimPatterns & slimPatternsAppendDefaults=false options', -// async (t) => { -// process.chdir('tests/base'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// dockerizePip: 'true', -// slim: 'true', -// slimPatternsAppendDefaults: 'false', -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, -// 'pyc files are packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test('pipenv py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { -// process.chdir('tests/pipenv'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// -// sls(['package'], { -// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, -// 'pyc files are packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { -// process.chdir('tests/poetry'); -// copySync('_slimPatterns.yml', 'slimPatterns.yml'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// -// sls(['package'], { -// env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true( -// zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, -// 'pyc files are packaged' -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('__main__.py')), -// [], -// '__main__.py files are NOT packaged' -// ); -// t.end(); -// }); -// -// test('poetry py3.9 can package flask with package individually option', async (t) => { -// process.chdir('tests/poetry_individually'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles( -// '.serverless/module1-sls-py-req-test-dev-hello.zip' -// ); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('py3.9 can package flask with package individually option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { individually: 'true' } }); -// const zipfiles_hello = await 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_hello2 = await listZipFiles('.serverless/hello2.zip'); -// t.false( -// zipfiles_hello2.includes(`fn2${sep}__init__.py`), -// 'fn2 is NOT packaged in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes('handler.py'), -// 'handler.py is packaged in function hello2' -// ); -// t.false( -// zipfiles_hello2.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello2' -// ); -// -// const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); -// t.false( -// zipfiles_hello3.includes(`fn2${sep}__init__.py`), -// 'fn2 is NOT packaged in function hello3' -// ); -// t.true( -// zipfiles_hello3.includes('handler.py'), -// 'handler.py is packaged in function hello3' -// ); -// t.false( -// zipfiles_hello3.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello3' -// ); -// t.false( -// zipfiles_hello3.includes(`flask${sep}__init__.py`), -// 'flask is NOT packaged in function hello3' -// ); -// -// const zipfiles_hello4 = await listZipFiles( -// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' -// ); -// t.false( -// zipfiles_hello4.includes(`fn2${sep}__init__.py`), -// 'fn2 is NOT packaged in function hello4' -// ); -// t.true( -// zipfiles_hello4.includes('fn2_handler.py'), -// 'fn2_handler is packaged in the zip-root 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.end(); -// }); -// -// test('py3.9 can package flask with package individually & slim option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { individually: 'true', slim: 'true' } }); -// const zipfiles_hello = await 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' -// ); -// t.false( -// zipfiles_hello.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello' -// ); -// -// const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); -// t.true( -// 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' -// ); -// t.false( -// zipfiles_hello2.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello2' -// ); -// -// const zipfiles_hello3 = await 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 = await listZipFiles( -// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' -// ); -// t.true( -// zipfiles_hello4.includes('fn2_handler.py'), -// 'fn2_handler is packaged in the zip-root 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' -// ); -// -// t.end(); -// }); -// -// test('py3.9 can package only requirements of module', async (t) => { -// process.chdir('tests/individually'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles_hello = await 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.true( -// zipfiles_hello.includes(`boto3${sep}__init__.py`), -// 'boto3 is packaged in function hello1' -// ); -// t.false( -// zipfiles_hello.includes(`flask${sep}__init__.py`), -// 'flask is NOT packaged in function hello1' -// ); -// -// const zipfiles_hello2 = await 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.false( -// zipfiles_hello2.includes(`boto3${sep}__init__.py`), -// 'boto3 is NOT packaged in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello2' -// ); -// -// t.end(); -// }); -// -// test('py3.9 can package lambda-decorators using vendor and invidiually option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { individually: 'true', vendor: './vendor' } }); -// const zipfiles_hello = await listZipFiles('.serverless/hello.zip'); -// t.true( -// zipfiles_hello.includes('handler.py'), -// 'handler.py is packaged at root level in function hello' -// ); -// t.true( -// zipfiles_hello.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello' -// ); -// t.true( -// zipfiles_hello.includes(`lambda_decorators.py`), -// 'lambda_decorators.py is packaged in function hello' -// ); -// t.false( -// zipfiles_hello.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello' -// ); -// -// const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); -// t.true( -// zipfiles_hello2.includes('handler.py'), -// 'handler.py is packaged at root level in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes(`lambda_decorators.py`), -// 'lambda_decorators.py is packaged in function hello2' -// ); -// t.false( -// zipfiles_hello2.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello2' -// ); -// -// const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); -// t.true( -// zipfiles_hello3.includes('handler.py'), -// 'handler.py is packaged at root level in function hello3' -// ); -// t.false( -// zipfiles_hello3.includes(`flask${sep}__init__.py`), -// 'flask is NOT packaged in function hello3' -// ); -// t.false( -// zipfiles_hello3.includes(`lambda_decorators.py`), -// 'lambda_decorators.py is NOT packaged in function hello3' -// ); -// t.false( -// zipfiles_hello3.includes(`dataclasses.py`), -// 'dataclasses is NOT packaged in function hello3' -// ); -// -// const zipfiles_hello4 = await listZipFiles( -// '.serverless/fn2-sls-py-req-test-dev-hello4.zip' -// ); -// t.true( -// zipfiles_hello4.includes('fn2_handler.py'), -// 'fn2_handler is packaged in the zip-root 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.end(); -// }); -// -// test( -// "Don't nuke execute perms when using individually", -// async (t) => { -// process.chdir('tests/individually'); -// const { stdout: path } = npm(['pack', '../..']); -// const perm = '755'; -// writeFileSync(`module1${sep}foobar`, ''); -// chmodSync(`module1${sep}foobar`, perm); -// -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles_hello1 = await listZipFilesWithMetaData( -// '.serverless/hello1.zip' -// ); -// -// t.true( -// zipfiles_hello1['module1/foobar'].unixPermissions -// .toString(8) -// .slice(3, 6) === perm, -// 'foobar has retained its executable file permissions' -// ); -// -// const zipfiles_hello2 = await listZipFilesWithMetaData( -// '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' -// ); -// const flaskPerm = statSync( -// '.serverless/module2/requirements/bin/flask' -// ).mode; -// -// t.true( -// zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, -// 'bin/flask has retained its executable file permissions' -// ); -// -// t.end(); -// }, -// { skip: process.platform === 'win32' } -// ); -// -// test( -// "Don't nuke execute perms when using individually w/docker", -// async (t) => { -// process.chdir('tests/individually'); -// const { stdout: path } = npm(['pack', '../..']); -// const perm = '755'; -// writeFileSync(`module1${sep}foobar`, '', { mode: perm }); -// chmodSync(`module1${sep}foobar`, perm); -// -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true' } }); -// const zipfiles_hello = await listZipFilesWithMetaData( -// '.serverless/hello1.zip' -// ); -// -// t.true( -// zipfiles_hello['module1/foobar'].unixPermissions -// .toString(8) -// .slice(3, 6) === perm, -// 'foobar has retained its executable file permissions' -// ); -// -// const zipfiles_hello2 = await listZipFilesWithMetaData( -// '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' -// ); -// const flaskPerm = statSync( -// '.serverless/module2/requirements/bin/flask' -// ).mode; -// -// t.true( -// zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, -// 'bin/flask has retained its executable file permissions' -// ); -// -// t.end(); -// }, -// { skip: !canUseDocker() || process.platform === 'win32' } -// ); -// -// test( -// 'py3.9 can package flask running in docker with module runtime & architecture of function', -// async (t) => { -// process.chdir('tests/individually_mixed_runtime'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// -// sls(['package'], { -// env: { dockerizePip: 'true' }, -// }); -// -// const zipfiles_hello2 = await listZipFiles( -// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' -// ); -// t.true( -// zipfiles_hello2.includes('handler2.py'), -// 'handler2.py is packaged at root level in function hello2' -// ); -// t.true( -// zipfiles_hello2.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello2' -// ); -// }, -// { -// skip: !canUseDocker() || process.platform === 'win32', -// } -// ); -// -// test( -// 'py3.9 can package flask succesfully when using mixed architecture, docker and zipping', -// async (t) => { -// process.chdir('tests/individually_mixed_runtime'); -// const { stdout: path } = npm(['pack', '../..']); -// -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); -// -// const zipfiles_hello = await listZipFiles('.serverless/hello1.zip'); -// t.true( -// zipfiles_hello.includes(`module1${sep}handler1.ts`), -// 'handler1.ts is packaged in module dir for hello1' -// ); -// t.false( -// zipfiles_hello.includes('handler2.py'), -// 'handler2.py is NOT packaged at root level in function hello1' -// ); -// t.false( -// zipfiles_hello.includes(`flask${sep}__init__.py`), -// 'flask is NOT packaged in function hello1' -// ); -// -// const zipfiles_hello2 = await listZipFiles( -// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' -// ); -// const zippedReqs = await listRequirementsZipFiles( -// '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-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(`module1${sep}handler1.ts`), -// 'handler1.ts is NOT included at module1 level in hello2' -// ); -// t.false( -// zipfiles_hello2.includes(`pyaml${sep}__init__.py`), -// 'pyaml is NOT packaged in function hello2' -// ); -// t.false( -// zipfiles_hello2.includes(`boto3${sep}__init__.py`), -// 'boto3 is NOT included in zipfile' -// ); -// t.true( -// zippedReqs.includes(`flask${sep}__init__.py`), -// 'flask is packaged in function hello2 in requirements.zip' -// ); -// -// t.end(); -// }, -// { skip: !canUseDocker() || process.platform === 'win32' } -// ); -// -// test( -// 'py3.9 uses download cache by default option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const cachepath = getUserCachePath(); -// t.true( -// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), -// 'cache directory exists' -// ); -// t.end(); -// }, -// { skip: true } -// ); -// -// test( -// 'py3.9 uses download cache by default', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { cacheLocation: '.requirements-cache' } }); -// t.true( -// pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), -// 'cache directory exists' -// ); -// t.end(); -// }, -// { skip: true } -// ); -// -// test( -// 'py3.9 uses download cache with dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true' } }); -// const cachepath = getUserCachePath(); -// t.true( -// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), -// 'cache directory exists' -// ); -// t.end(); -// }, -// // { skip: !canUseDocker() || brokenOn('win32') } -// { skip: true } -// ); -// -// test( -// 'py3.9 uses download cache with dockerizePip by default option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { dockerizePip: 'true', cacheLocation: '.requirements-cache' }, -// }); -// t.true( -// pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), -// 'cache directory exists' -// ); -// t.end(); -// }, -// // { skip: !canUseDocker() || brokenOn('win32') } -// { skip: true } -// ); -// -// test( -// 'py3.9 uses static and download cache', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const cachepath = getUserCachePath(); -// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); -// const arch = 'x86_64'; -// t.true( -// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), -// 'http exists in download-cache' -// ); -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` -// ), -// 'flask exists in static-cache' -// ); -// t.end(); -// }, -// { skip: true } -// ); -// -// test( -// 'py3.9 uses static and download cache with dockerizePip option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true' } }); -// const cachepath = getUserCachePath(); -// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); -// const arch = 'x86_64'; -// t.true( -// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), -// 'http exists in download-cache' -// ); -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` -// ), -// 'flask exists in static-cache' -// ); -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test('py3.9 uses static cache', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const cachepath = getUserCachePath(); -// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); -// const arch = 'x86_64'; -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` -// ), -// 'flask exists in static-cache' -// ); -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` -// ), -// '.completed_requirements exists in static-cache' -// ); -// -// // py3.9 checking that static cache actually pulls from cache (by poisoning it) -// writeFileSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, -// 'injected new file into static cache folder' -// ); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('injected_file_is_bad_form'), -// "static cache is really used when running 'sls package' again" -// ); -// -// t.end(); -// }); -// -// test('py3.9 uses static cache with cacheLocation option', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// const cachepath = '.requirements-cache'; -// sls(['package'], { env: { cacheLocation: cachepath } }); -// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); -// const arch = 'x86_64'; -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` -// ), -// 'flask exists in static-cache' -// ); -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` -// ), -// '.completed_requirements exists in static-cache' -// ); -// t.end(); -// }); -// -// test( -// 'py3.9 uses static cache with dockerizePip & slim option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); -// const cachepath = getUserCachePath(); -// const cacheFolderHash = sha256Path('.serverless/requirements.txt'); -// const arch = 'x86_64'; -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` -// ), -// 'flask exists in static-cache' -// ); -// t.true( -// pathExistsSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` -// ), -// '.completed_requirements exists in static-cache' -// ); -// -// // py3.9 checking that static cache actually pulls from cache (by poisoning it) -// writeFileSync( -// `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, -// 'injected new file into static cache folder' -// ); -// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes('injected_file_is_bad_form'), -// "static cache is really used when running 'sls package' again" -// ); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files are packaged' -// ); -// -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test( -// 'py3.9 uses download cache with dockerizePip & slim option', -// async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); -// const cachepath = getUserCachePath(); -// t.true( -// pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), -// 'http exists in download-cache' -// ); -// -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.deepEqual( -// zipfiles.filter((filename) => filename.endsWith('.pyc')), -// [], -// 'no pyc files are packaged' -// ); -// -// t.end(); -// }, -// { skip: !canUseDocker() || brokenOn('win32') } -// ); -// -// test('py3.9 can ignore functions defined with `image`', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { individually: 'true' } }); -// t.true(pathExistsSync('.serverless/hello.zip'), 'function hello is packaged'); -// t.true( -// pathExistsSync('.serverless/hello2.zip'), -// 'function hello2 is packaged' -// ); -// t.true( -// pathExistsSync('.serverless/hello3.zip'), -// 'function hello3 is packaged' -// ); -// t.true( -// pathExistsSync('.serverless/hello4.zip'), -// 'function hello4 is packaged' -// ); -// t.false( -// pathExistsSync('.serverless/hello5.zip'), -// 'function hello5 is not packaged' -// ); -// -// t.end(); -// }); - -// test('poetry py3.9 fails packaging if poetry.lock is missing and flag requirePoetryLockFile is set to true', async (t) => { -// copySync('tests/poetry', 'tests/base with a space'); -// process.chdir('tests/base with a space'); -// removeSync('poetry.lock'); -// -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// const { stderr } = sls(['package'], { -// env: { requirePoetryLockFile: 'true', slim: 'true' }, -// noThrow: true, -// }); -// t.true( -// stderr.includes( -// 'poetry.lock file not found - set requirePoetryLockFile to false to disable this error' -// ), -// 'flag works and error is properly reported' -// ); -// t.end(); -// }); - -// test('works with provider.runtime not being python', async (t) => { -// process.chdir('tests/base'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: { runtime: 'nodejs20.x' } }); -// t.true( -// pathExistsSync('.serverless/sls-py-req-test.zip'), -// 'sls-py-req-test is packaged' -// ); -// t.end(); -// }); -// -// test('poetry py3.9 packages additional optional packages', async (t) => { -// process.chdir('tests/poetry_packages'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// poetryWithGroups: 'poetryWithGroups', -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('poetry py3.9 skips additional optional packages specified in withoutGroups', async (t) => { -// process.chdir('tests/poetry_packages'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// poetryWithGroups: 'poetryWithGroups', -// poetryWithoutGroups: 'poetryWithoutGroups', -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); -// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test('poetry py3.9 only installs optional packages specified in onlyGroups', async (t) => { -// process.chdir('tests/poetry_packages'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { -// env: { -// poetryOnlyGroups: 'poetryOnlyGroups', -// }, -// }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); -// t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); -// t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); -// t.end(); -// }); -// -// test( -// 'py3.7 injects dependencies into `package` folder when using scaleway provider', -// async (t) => { -// process.chdir('tests/scaleway_provider'); -// const { stdout: path } = npm(['pack', '../..']); -// npm(['i', path]); -// sls(['package'], { env: {} }); -// const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); -// t.true( -// zipfiles.includes(`package${sep}flask${sep}__init__.py`), -// 'flask is packaged' -// ); -// t.true( -// zipfiles.includes(`package${sep}boto3${sep}__init__.py`), -// 'boto3 is packaged' -// ); -// t.end(); -// }, -// { skip: true } // sls v4 supports aws provider only -// ); + +test('default pythonBin can package flask with default options', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('py3.9 packages have the same hash', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const fileHash = sha256File('.serverless/sls-py-req-test.zip'); + sls(['package'], { env: {} }); + t.equal( + sha256File('.serverless/sls-py-req-test.zip'), + fileHash, + 'packages have the same hash' + ); + t.end(); +}); + +test('py3.9 can package flask with default options', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test( + 'py3.9 can package flask with hashes', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + fileName: 'requirements-w-hashes.txt', + pythonBin: getPythonBin(3), + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.end(); + }, + { skip: brokenOn('win32') } +); + +test('py3.9 can package flask with nested', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + fileName: 'requirements-w-nested.txt', + pythonBin: getPythonBin(3), + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('py3.9 can package flask with zip option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.end(); +}); + +test('py3.9 can package flask with slim option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true', pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.true( + zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, + '__main__.py files are packaged' + ); + t.end(); +}); + +test('py3.9 can package flask with slim & slimPatterns options', async (t) => { + process.chdir('tests/base'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test("py3.9 doesn't package bottle with noDeploy option", async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + perl([ + '-p', + '-i.bak', + '-e', + 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', + 'serverless.yml', + ]); + sls(['package'], { env: { pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); + t.end(); +}); + +test('py3.9 can package boto3 with editable', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + fileName: 'requirements-w-editable.txt', + pythonBin: getPythonBin(3), + }, + }); + 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(); +}); + +test( + 'py3.9 can package flask with dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test( + 'py3.9 can package flask with slim & dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + '*.pyc files are NOT packaged' + ); + t.true( + zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > + 0, + '__main__.py files are packaged' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test( + 'py3.9 can package flask with slim & dockerizePip & slimPatterns options', + async (t) => { + process.chdir('tests/base'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + '*.pyc files are packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test( + 'py3.9 can package flask with zip & dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + const zippedReqs = await listRequirementsZipFiles( + '.serverless/sls-py-req-test.zip' + ); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true( + zipfiles.includes(`unzip_requirements.py`), + 'unzip util is packaged' + ); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.true( + zippedReqs.includes(`flask/__init__.py`), + 'flask is packaged in the .requirements.zip file' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test( + 'py3.9 can package flask with zip & slim & dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { dockerizePip: 'true', zip: 'true', slim: 'true' }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + const zippedReqs = await listRequirementsZipFiles( + '.serverless/sls-py-req-test.zip' + ); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true( + zipfiles.includes(`unzip_requirements.py`), + 'unzip util is packaged' + ); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.true( + zippedReqs.includes(`flask/__init__.py`), + 'flask is packaged in the .requirements.zip file' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test('pipenv py3.9 can package flask with default options', async (t) => { + process.chdir('tests/pipenv'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.false( + zipfiles.includes(`pytest${sep}__init__.py`), + 'dev-package pytest is NOT packaged' + ); + t.end(); +}); + +test('pipenv py3.9 can package flask with slim option', async (t) => { + process.chdir('tests/pipenv'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.true( + zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, + '__main__.py files are packaged' + ); + t.end(); +}); + +test('pipenv py3.9 can package flask with slim & slimPatterns options', async (t) => { + process.chdir('tests/pipenv'); + + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test('pipenv py3.9 can package flask with zip option', async (t) => { + process.chdir('tests/pipenv'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.end(); +}); + +test("pipenv py3.9 doesn't package bottle with noDeploy option", async (t) => { + process.chdir('tests/pipenv'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + perl([ + '-p', + '-i.bak', + '-e', + 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', + 'serverless.yml', + ]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); + t.end(); +}); + +test('non build pyproject.toml uses requirements.txt', async (t) => { + process.chdir('tests/non_build_pyproject'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('non poetry pyproject.toml without requirements.txt packages handler only', async (t) => { + process.chdir('tests/non_poetry_pyproject'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`handler.py`), 'handler is packaged'); + t.end(); +}); + +test('poetry py3.9 can package flask with default options', async (t) => { + process.chdir('tests/poetry'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('poetry py3.9 can package flask with slim option', async (t) => { + process.chdir('tests/poetry'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.true( + zipfiles.filter((filename) => filename.endsWith('__main__.py')).length > 0, + '__main__.py files are packaged' + ); + t.end(); +}); + +test('poetry py3.9 can package flask with slim & slimPatterns options', async (t) => { + process.chdir('tests/poetry'); + + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test('poetry py3.9 can package flask with zip option', async (t) => { + process.chdir('tests/poetry'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.end(); +}); + +test("poetry py3.9 doesn't package bottle with noDeploy option", async (t) => { + process.chdir('tests/poetry'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + perl([ + '-p', + '-i.bak', + '-e', + 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', + 'serverless.yml', + ]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); + t.end(); +}); + +test('py3.9 can package flask with zip option and no explicit include', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + perl(['-p', '-i.bak', '-e', 's/include://', 'serverless.yml']); + perl(['-p', '-i.bak', '-e', 's/^.*handler.py.*$//', 'serverless.yml']); + sls(['package'], { env: { zip: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.end(); +}); + +test('py3.9 can package lambda-decorators using vendor option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { vendor: './vendor' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.true( + zipfiles.includes(`lambda_decorators.py`), + 'lambda_decorators.py is packaged' + ); + t.end(); +}); + +test( + "Don't nuke execute perms", + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + const perm = '755'; + + npm(['i', path]); + perl([ + '-p', + '-i.bak', + '-e', + 's/(handler.py.*$)/$1\n - foobar/', + 'serverless.yml', + ]); + writeFileSync(`foobar`, ''); + chmodSync(`foobar`, perm); + sls(['package'], { env: { vendor: './vendor' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.true( + zipfiles.includes(`lambda_decorators.py`), + 'lambda_decorators.py is packaged' + ); + t.true(zipfiles.includes(`foobar`), 'foobar is packaged'); + + const zipfiles_with_metadata = await listZipFilesWithMetaData( + '.serverless/sls-py-req-test.zip' + ); + t.true( + zipfiles_with_metadata['foobar'].unixPermissions + .toString(8) + .slice(3, 6) === perm, + 'foobar has retained its executable file permissions' + ); + + const flaskPerm = statSync('.serverless/requirements/bin/flask').mode; + t.true( + zipfiles_with_metadata['bin/flask'].unixPermissions === flaskPerm, + 'bin/flask has retained its executable file permissions' + ); + + t.end(); + }, + { skip: process.platform === 'win32' } +); + +test('py3.9 can package flask in a project with a space in it', async (t) => { + copySync('tests/base', 'tests/base with a space'); + process.chdir('tests/base with a space'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test( + 'py3.9 can package flask in a project with a space in it with docker', + async (t) => { + copySync('tests/base', 'tests/base with a space'); + process.chdir('tests/base with a space'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test('py3.9 supports custom file name with fileName option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + writeFileSync('puck', 'requests'); + npm(['i', path]); + sls(['package'], { env: { fileName: 'puck' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes(`requests${sep}__init__.py`), + 'requests is packaged' + ); + t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); + t.false(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is NOT packaged'); + t.end(); +}); + +test("py3.9 doesn't package bottle with zip option", async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + perl([ + '-p', + '-i.bak', + '-e', + 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', + 'serverless.yml', + ]); + sls(['package'], { env: { zip: 'true', pythonBin: getPythonBin(3) } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + const zippedReqs = await listRequirementsZipFiles( + '.serverless/sls-py-req-test.zip' + ); + t.true( + zipfiles.includes('.requirements.zip'), + 'zipped requirements are packaged' + ); + t.true(zipfiles.includes(`unzip_requirements.py`), 'unzip util is packaged'); + t.false( + zipfiles.includes(`flask${sep}__init__.py`), + "flask isn't packaged on its own" + ); + t.true( + zippedReqs.includes(`flask/__init__.py`), + 'flask is packaged in the .requirements.zip file' + ); + t.false( + zippedReqs.includes(`bottle.py`), + 'bottle is NOT packaged in the .requirements.zip file' + ); + t.end(); +}); + +test('py3.9 can package flask with slim, slimPatterns & slimPatternsAppendDefaults=false options', async (t) => { + process.chdir('tests/base'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true( + zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, + 'pyc files are packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test( + 'py3.9 can package flask with slim & dockerizePip & slimPatterns & slimPatternsAppendDefaults=false options', + async (t) => { + process.chdir('tests/base'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + dockerizePip: 'true', + slim: 'true', + slimPatternsAppendDefaults: 'false', + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true( + zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, + 'pyc files are packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test('pipenv py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { + process.chdir('tests/pipenv'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + + sls(['package'], { + env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true( + zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, + 'pyc files are packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test('poetry py3.9 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async (t) => { + process.chdir('tests/poetry'); + copySync('_slimPatterns.yml', 'slimPatterns.yml'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + + sls(['package'], { + env: { slim: 'true', slimPatternsAppendDefaults: 'false' }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true( + zipfiles.filter((filename) => filename.endsWith('.pyc')).length >= 1, + 'pyc files are packaged' + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('__main__.py')), + [], + '__main__.py files are NOT packaged' + ); + t.end(); +}); + +test('poetry py3.9 can package flask with package individually option', async (t) => { + process.chdir('tests/poetry_individually'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles( + '.serverless/module1-sls-py-req-test-dev-hello.zip' + ); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('py3.9 can package flask with package individually option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { individually: 'true' } }); + const zipfiles_hello = await 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_hello2 = await listZipFiles('.serverless/hello2.zip'); + t.false( + zipfiles_hello2.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes('handler.py'), + 'handler.py is packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + + const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); + t.false( + zipfiles_hello3.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello3' + ); + t.true( + zipfiles_hello3.includes('handler.py'), + 'handler.py is packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello3' + ); + + const zipfiles_hello4 = await listZipFiles( + '.serverless/fn2-sls-py-req-test-dev-hello4.zip' + ); + t.false( + zipfiles_hello4.includes(`fn2${sep}__init__.py`), + 'fn2 is NOT packaged in function hello4' + ); + t.true( + zipfiles_hello4.includes('fn2_handler.py'), + 'fn2_handler is packaged in the zip-root 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.end(); +}); + +test('py3.9 can package flask with package individually & slim option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { individually: 'true', slim: 'true' } }); + const zipfiles_hello = await 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' + ); + t.false( + zipfiles_hello.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello' + ); + + const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); + t.true( + 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' + ); + t.false( + zipfiles_hello2.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello2' + ); + + const zipfiles_hello3 = await 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 = await listZipFiles( + '.serverless/fn2-sls-py-req-test-dev-hello4.zip' + ); + t.true( + zipfiles_hello4.includes('fn2_handler.py'), + 'fn2_handler is packaged in the zip-root 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' + ); + + t.end(); +}); + +test('py3.9 can package only requirements of module', async (t) => { + process.chdir('tests/individually'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles_hello = await 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.true( + zipfiles_hello.includes(`boto3${sep}__init__.py`), + 'boto3 is packaged in function hello1' + ); + t.false( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello1' + ); + + const zipfiles_hello2 = await 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.false( + zipfiles_hello2.includes(`boto3${sep}__init__.py`), + 'boto3 is NOT packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + + t.end(); +}); + +test('py3.9 can package lambda-decorators using vendor and invidiually option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { individually: 'true', vendor: './vendor' } }); + const zipfiles_hello = await listZipFiles('.serverless/hello.zip'); + t.true( + zipfiles_hello.includes('handler.py'), + 'handler.py is packaged at root level in function hello' + ); + t.true( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello' + ); + t.true( + zipfiles_hello.includes(`lambda_decorators.py`), + 'lambda_decorators.py is packaged in function hello' + ); + t.false( + zipfiles_hello.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello' + ); + + const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); + t.true( + zipfiles_hello2.includes('handler.py'), + 'handler.py is packaged at root level in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + t.true( + zipfiles_hello2.includes(`lambda_decorators.py`), + 'lambda_decorators.py is packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello2' + ); + + const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); + t.true( + zipfiles_hello3.includes('handler.py'), + 'handler.py is packaged at root level in function hello3' + ); + t.false( + zipfiles_hello3.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`lambda_decorators.py`), + 'lambda_decorators.py is NOT packaged in function hello3' + ); + t.false( + zipfiles_hello3.includes(`dataclasses.py`), + 'dataclasses is NOT packaged in function hello3' + ); + + const zipfiles_hello4 = await listZipFiles( + '.serverless/fn2-sls-py-req-test-dev-hello4.zip' + ); + t.true( + zipfiles_hello4.includes('fn2_handler.py'), + 'fn2_handler is packaged in the zip-root 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.end(); +}); + +test( + "Don't nuke execute perms when using individually", + async (t) => { + process.chdir('tests/individually'); + const { stdout: path } = npm(['pack', '../..']); + const perm = '755'; + writeFileSync(`module1${sep}foobar`, ''); + chmodSync(`module1${sep}foobar`, perm); + + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles_hello1 = await listZipFilesWithMetaData( + '.serverless/hello1.zip' + ); + + t.true( + zipfiles_hello1['module1/foobar'].unixPermissions + .toString(8) + .slice(3, 6) === perm, + 'foobar has retained its executable file permissions' + ); + + const zipfiles_hello2 = await listZipFilesWithMetaData( + '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' + ); + const flaskPerm = statSync( + '.serverless/module2/requirements/bin/flask' + ).mode; + + t.true( + zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, + 'bin/flask has retained its executable file permissions' + ); + + t.end(); + }, + { skip: process.platform === 'win32' } +); + +test( + "Don't nuke execute perms when using individually w/docker", + async (t) => { + process.chdir('tests/individually'); + const { stdout: path } = npm(['pack', '../..']); + const perm = '755'; + writeFileSync(`module1${sep}foobar`, '', { mode: perm }); + chmodSync(`module1${sep}foobar`, perm); + + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true' } }); + const zipfiles_hello = await listZipFilesWithMetaData( + '.serverless/hello1.zip' + ); + + t.true( + zipfiles_hello['module1/foobar'].unixPermissions + .toString(8) + .slice(3, 6) === perm, + 'foobar has retained its executable file permissions' + ); + + const zipfiles_hello2 = await listZipFilesWithMetaData( + '.serverless/module2-sls-py-req-test-indiv-dev-hello2.zip' + ); + const flaskPerm = statSync( + '.serverless/module2/requirements/bin/flask' + ).mode; + + t.true( + zipfiles_hello2['bin/flask'].unixPermissions === flaskPerm, + 'bin/flask has retained its executable file permissions' + ); + + t.end(); + }, + { skip: !canUseDocker() || process.platform === 'win32' } +); + +test( + 'py3.9 can package flask running in docker with module runtime & architecture of function', + async (t) => { + process.chdir('tests/individually_mixed_runtime'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + + sls(['package'], { + env: { dockerizePip: 'true' }, + }); + + const zipfiles_hello2 = await listZipFiles( + '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' + ); + t.true( + zipfiles_hello2.includes('handler2.py'), + 'handler2.py is packaged at root level in function hello2' + ); + t.true( + zipfiles_hello2.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2' + ); + }, + { + skip: !canUseDocker() || process.platform === 'win32', + } +); + +test( + 'py3.9 can package flask succesfully when using mixed architecture, docker and zipping', + async (t) => { + process.chdir('tests/individually_mixed_runtime'); + const { stdout: path } = npm(['pack', '../..']); + + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', zip: 'true' } }); + + const zipfiles_hello = await listZipFiles('.serverless/hello1.zip'); + t.true( + zipfiles_hello.includes(`module1${sep}handler1.ts`), + 'handler1.ts is packaged in module dir for hello1' + ); + t.false( + zipfiles_hello.includes('handler2.py'), + 'handler2.py is NOT packaged at root level in function hello1' + ); + t.false( + zipfiles_hello.includes(`flask${sep}__init__.py`), + 'flask is NOT packaged in function hello1' + ); + + const zipfiles_hello2 = await listZipFiles( + '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-dev-hello2.zip' + ); + const zippedReqs = await listRequirementsZipFiles( + '.serverless/module2-sls-py-req-test-indiv-mixed-runtime-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(`module1${sep}handler1.ts`), + 'handler1.ts is NOT included at module1 level in hello2' + ); + t.false( + zipfiles_hello2.includes(`pyaml${sep}__init__.py`), + 'pyaml is NOT packaged in function hello2' + ); + t.false( + zipfiles_hello2.includes(`boto3${sep}__init__.py`), + 'boto3 is NOT included in zipfile' + ); + t.true( + zippedReqs.includes(`flask${sep}__init__.py`), + 'flask is packaged in function hello2 in requirements.zip' + ); + + t.end(); + }, + { skip: !canUseDocker() || process.platform === 'win32' } +); + +test( + 'py3.9 uses download cache by default option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const cachepath = getUserCachePath(); + t.true( + pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), + 'cache directory exists' + ); + t.end(); + }, + { skip: true } +); + +test( + 'py3.9 uses download cache by default', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { cacheLocation: '.requirements-cache' } }); + t.true( + pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), + 'cache directory exists' + ); + t.end(); + }, + { skip: true } +); + +test( + 'py3.9 uses download cache with dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true' } }); + const cachepath = getUserCachePath(); + t.true( + pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), + 'cache directory exists' + ); + t.end(); + }, + // { skip: !canUseDocker() || brokenOn('win32') } + { skip: true } +); + +test( + 'py3.9 uses download cache with dockerizePip by default option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { dockerizePip: 'true', cacheLocation: '.requirements-cache' }, + }); + t.true( + pathExistsSync(`.requirements-cache${sep}downloadCacheslspyc${sep}http`), + 'cache directory exists' + ); + t.end(); + }, + // { skip: !canUseDocker() || brokenOn('win32') } + { skip: true } +); + +test( + 'py3.9 uses static and download cache', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const cachepath = getUserCachePath(); + const cacheFolderHash = sha256Path('.serverless/requirements.txt'); + const arch = 'x86_64'; + t.true( + pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), + 'http exists in download-cache' + ); + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` + ), + 'flask exists in static-cache' + ); + t.end(); + }, + { skip: true } +); + +test( + 'py3.9 uses static and download cache with dockerizePip option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true' } }); + const cachepath = getUserCachePath(); + const cacheFolderHash = sha256Path('.serverless/requirements.txt'); + const arch = 'x86_64'; + t.true( + pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), + 'http exists in download-cache' + ); + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` + ), + 'flask exists in static-cache' + ); + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test('py3.9 uses static cache', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const cachepath = getUserCachePath(); + const cacheFolderHash = sha256Path('.serverless/requirements.txt'); + const arch = 'x86_64'; + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` + ), + 'flask exists in static-cache' + ); + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` + ), + '.completed_requirements exists in static-cache' + ); + + // py3.9 checking that static cache actually pulls from cache (by poisoning it) + writeFileSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, + 'injected new file into static cache folder' + ); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('injected_file_is_bad_form'), + "static cache is really used when running 'sls package' again" + ); + + t.end(); +}); + +test('py3.9 uses static cache with cacheLocation option', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + const cachepath = '.requirements-cache'; + sls(['package'], { env: { cacheLocation: cachepath } }); + const cacheFolderHash = sha256Path('.serverless/requirements.txt'); + const arch = 'x86_64'; + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` + ), + 'flask exists in static-cache' + ); + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` + ), + '.completed_requirements exists in static-cache' + ); + t.end(); +}); + +test( + 'py3.9 uses static cache with dockerizePip & slim option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); + const cachepath = getUserCachePath(); + const cacheFolderHash = sha256Path('.serverless/requirements.txt'); + const arch = 'x86_64'; + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}flask` + ), + 'flask exists in static-cache' + ); + t.true( + pathExistsSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}.completed_requirements` + ), + '.completed_requirements exists in static-cache' + ); + + // py3.9 checking that static cache actually pulls from cache (by poisoning it) + writeFileSync( + `${cachepath}${sep}${cacheFolderHash}_${arch}_slspyc${sep}injected_file_is_bad_form`, + 'injected new file into static cache folder' + ); + sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes('injected_file_is_bad_form'), + "static cache is really used when running 'sls package' again" + ); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files are packaged' + ); + + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test( + 'py3.9 uses download cache with dockerizePip & slim option', + async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { dockerizePip: 'true', slim: 'true' } }); + const cachepath = getUserCachePath(); + t.true( + pathExistsSync(`${cachepath}${sep}downloadCacheslspyc${sep}http`), + 'http exists in download-cache' + ); + + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.deepEqual( + zipfiles.filter((filename) => filename.endsWith('.pyc')), + [], + 'no pyc files are packaged' + ); + + t.end(); + }, + { skip: !canUseDocker() || brokenOn('win32') } +); + +test('py3.9 can ignore functions defined with `image`', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { individually: 'true' } }); + t.true(pathExistsSync('.serverless/hello.zip'), 'function hello is packaged'); + t.true( + pathExistsSync('.serverless/hello2.zip'), + 'function hello2 is packaged' + ); + t.true( + pathExistsSync('.serverless/hello3.zip'), + 'function hello3 is packaged' + ); + t.true( + pathExistsSync('.serverless/hello4.zip'), + 'function hello4 is packaged' + ); + t.false( + pathExistsSync('.serverless/hello5.zip'), + 'function hello5 is not packaged' + ); + + t.end(); +}); + +test('poetry py3.9 fails packaging if poetry.lock is missing and flag requirePoetryLockFile is set to true', async (t) => { + copySync('tests/poetry', 'tests/base with a space'); + process.chdir('tests/base with a space'); + removeSync('poetry.lock'); + + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + const { stderr, stdout } = sls(['package'], { + env: { requirePoetryLockFile: 'true', slim: 'true' }, + noThrow: true, + }); + console.log('stderr', stderr); + console.log('stdout', stdout); + t.true( + stdout.includes( + 'poetry.lock file not found - set requirePoetryLockFile to false to disable this error' + ), + 'flag works and error is properly reported' + ); + t.end(); +}); + +test('works with provider.runtime not being python', async (t) => { + process.chdir('tests/base'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: { runtime: 'nodejs20.x' } }); + t.true( + pathExistsSync('.serverless/sls-py-req-test.zip'), + 'sls-py-req-test is packaged' + ); + t.end(); +}); + +test('poetry py3.9 packages additional optional packages', async (t) => { + process.chdir('tests/poetry_packages'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + poetryWithGroups: 'poetryWithGroups', + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.true(zipfiles.includes(`bottle.py`), 'bottle is packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('poetry py3.9 skips additional optional packages specified in withoutGroups', async (t) => { + process.chdir('tests/poetry_packages'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + poetryWithGroups: 'poetryWithGroups', + poetryWithoutGroups: 'poetryWithoutGroups', + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true(zipfiles.includes(`flask${sep}__init__.py`), 'flask is packaged'); + t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test('poetry py3.9 only installs optional packages specified in onlyGroups', async (t) => { + process.chdir('tests/poetry_packages'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { + env: { + poetryOnlyGroups: 'poetryOnlyGroups', + }, + }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.false(zipfiles.includes(`flask${sep}__init__.py`), 'flask is NOT packaged'); + t.false(zipfiles.includes(`bottle.py`), 'bottle is NOT packaged'); + t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged'); + t.end(); +}); + +test( + 'py3.7 injects dependencies into `package` folder when using scaleway provider', + async (t) => { + process.chdir('tests/scaleway_provider'); + const { stdout: path } = npm(['pack', '../..']); + npm(['i', path]); + sls(['package'], { env: {} }); + const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip'); + t.true( + zipfiles.includes(`package${sep}flask${sep}__init__.py`), + 'flask is packaged' + ); + t.true( + zipfiles.includes(`package${sep}boto3${sep}__init__.py`), + 'boto3 is packaged' + ); + t.end(); + }, + { skip: true } // sls v4 supports aws provider only +); diff --git a/tests/base/package.json b/tests/base/package.json index dceb03e8..b07744c9 100644 --- a/tests/base/package.json +++ b/tests/base/package.json @@ -9,6 +9,6 @@ "author": "", "license": "ISC", "dependencies": { - "serverless-python-requirements": "file:serverless-python-requirements-6.1.1.tgz" + "serverless-python-requirements": "file:serverless-python-requirements-6.0.1.tgz" } } From 6e0823beb1148d00bb1b469816006d7e9f09f2e7 Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 18:18:44 +0100 Subject: [PATCH 16/17] fix: Run prettier --- test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.js b/test.js index e6c89d10..7a3bd0ad 100644 --- a/test.js +++ b/test.js @@ -206,7 +206,7 @@ test( process.chdir('tests/base'); const { stdout: path } = npm(['pack', '../..']); npm(['i', path]); - const { stdout } = sls(['package'], { + const { stdout } = sls(['package'], { noThrow: true, env: { dockerizePip: true, From 7175a8998a30357219e100a321662f805152cf0e Mon Sep 17 00:00:00 2001 From: Tomasz Czubocha Date: Tue, 11 Feb 2025 18:34:33 +0100 Subject: [PATCH 17/17] fix: Remove console logs --- test.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test.js b/test.js index 7a3bd0ad..1967330b 100644 --- a/test.js +++ b/test.js @@ -137,7 +137,7 @@ const availablePythons = (() => { ); } else { // For running outside of CI - binaries.push('python3'); + binaries.push('python'); } const exe = process.platform === 'win32' ? '.exe' : ''; for (const bin of binaries) { @@ -1742,12 +1742,10 @@ test('poetry py3.9 fails packaging if poetry.lock is missing and flag requirePoe const { stdout: path } = npm(['pack', '../..']); npm(['i', path]); - const { stderr, stdout } = sls(['package'], { + const { stdout } = sls(['package'], { env: { requirePoetryLockFile: 'true', slim: 'true' }, noThrow: true, }); - console.log('stderr', stderr); - console.log('stdout', stdout); t.true( stdout.includes( 'poetry.lock file not found - set requirePoetryLockFile to false to disable this error'