From 1a307f64835fb568336007cabe227faf9e0a2699 Mon Sep 17 00:00:00 2001 From: Ben Samuel Date: Mon, 12 Apr 2021 00:38:19 -0400 Subject: [PATCH 1/2] Remove Python 2.7 support --- .github/workflows/test.yml | 2 +- README.md | 16 +- test.js | 510 ------------------------------------- 3 files changed, 14 insertions(+), 514 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa94f4b0..e203e0c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: [2.7, 3.6] + python-version: [3.6] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 0b3bad55..7756843b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,18 @@ A Serverless v1.x plugin to automatically bundle dependencies from `requirements.txt` and make them available in your `PYTHONPATH`. -## Requires Serverless >= v1.34 +## Requirements + + * Serverless >= v1.34 + * Python >= 3.6 + +### Python 2.7 note + +As of 6.0.0, Python 2.7 is no longer supported. This plugin delegates most work out to `pip` +directly or indirectly, so it may continue to work, but: + + * The test suite no longer includes 2.7 specific tests. + * Fixes for 2.7 specific bugs that require code branching by Python version will not be accepted. ## Install @@ -383,8 +394,7 @@ Quick notes on the config file: ### Customize Python executable -Sometimes your Python executable isn't available on your `$PATH` as `python2.7` -or `python3.6` (for example, windows or using pyenv). +Sometimes your Python executable isn't available on your `$PATH` as `python3.6`, possibly for example, on Windows or using pyenv. To support this, this plugin has the following option: ```yaml diff --git a/test.js b/test.js index e35b521c..bcd82821 100644 --- a/test.js +++ b/test.js @@ -528,294 +528,6 @@ test( { skip: !canUseDocker() || !hasPython(3.6) || brokenOn('win32') } ); -test( - 'py2.7 can package flask with default options', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([`--pythonBin=${getPythonBin(2)}`, '--runtime=python2.7', 'package']); - 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: !hasPython(2) } -); - -test( - 'py2.7 can package flask with slim option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--slim=true', - 'package' - ]); - 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(); - }, - { skip: !hasPython(2) } -); - -test( - 'py2.7 can package flask with zip option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--zip=true', - 'package' - ]); - 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(); - }, - { skip: !hasPython(2) } -); - -test( - 'py2.7 can package flask with slim & dockerizePip & slimPatterns options', - async t => { - process.chdir('tests/base'); - - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - '--slim=true', - 'package' - ]); - 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() || !hasPython(2) || brokenOn('win32') } -); - -test( - "py2.7 doesn't package bottle with noDeploy option", - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - perl([ - '-p', - '-i.bak', - '-e', - 's/(pythonRequirements:$)/\\1\\n noDeploy: [bottle]/', - 'serverless.yml' - ]); - sls([`--pythonBin=${getPythonBin(2)}`, '--runtime=python2.7', 'package']); - 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(); - }, - { skip: !hasPython(2) } -); - -test( - 'py2.7 can package flask with zip & dockerizePip option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - '--zip=true', - 'package' - ]); - - 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() || !hasPython(2) || brokenOn('win32') } -); - -test( - 'py2.7 can package flask with zip & slim & dockerizePip option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - '--zip=true', - '--slim=true', - 'package' - ]); - - 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() || !hasPython(2) || brokenOn('win32') } -); - -test( - 'py2.7 can package flask with dockerizePip option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - 'package' - ]); - - 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() || !hasPython(2) || brokenOn('win32') } -); - -test( - 'py2.7 can package flask with slim & dockerizePip option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - '--slim=true', - 'package' - ]); - 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() || !hasPython(2) || brokenOn('win32') } -); - -test( - 'py2.7 can package flask with slim & dockerizePip & slimPatterns options', - async t => { - process.chdir('tests/base'); - - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - `--pythonBin=${getPythonBin(2)}`, - '--runtime=python2.7', - '--dockerizePip=true', - '--slim=true', - 'package' - ]); - 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() || !hasPython(2) || brokenOn('win32') } -); - test( 'pipenv py3.6 can package flask with default options', async t => { @@ -1323,66 +1035,6 @@ test( { skip: !canUseDocker() || !hasPython(3.6) || brokenOn('win32') } ); -test( - 'py2.7 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false options', - async t => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - '--runtime=python2.7', - '--slim=true', - '--slimPatternsAppendDefaults=false', - 'package' - ]); - - 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: !hasPython(2.7) || brokenOn('win32') } -); - -test( - 'py2.7 can package flask with slim & dockerizePip & slimPatterns & slimPatternsAppendDefaults=false options', - async t => { - process.chdir('tests/base'); - copySync('_slimPatterns.yml', 'slimPatterns.yml'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - '--dockerizePip=true', - '--runtime=python2.7', - '--slim=true', - '--slimPatternsAppendDefaults=false', - 'package' - ]); - 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() || !hasPython(2.7) || brokenOn('win32') } -); - test( 'pipenv py3.6 can package flask with slim & slimPatterns & slimPatternsAppendDefaults=false option', async t => { @@ -1607,168 +1259,6 @@ test( { skip: !hasPython(3.6) } ); -test( - 'py2.7 can package flask with package individually option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls(['--individually=true', '--runtime=python2.7', 'package']); - - const zipfiles_hello = await listZipFiles('.serverless/hello.zip'); - t.true( - zipfiles_hello.includes('handler.py'), - 'handler.py is packaged in function hello' - ); - t.true( - zipfiles_hello.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello' - ); - t.false( - zipfiles_hello.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello' - ); - - const zipfiles_hello2 = await listZipFiles('.serverless/hello2.zip'); - t.true( - zipfiles_hello2.includes('handler.py'), - 'handler.py is packaged in function hello2' - ); - t.true( - zipfiles_hello2.includes(`flask${sep}__init__.py`), - 'flask is packaged in function hello2' - ); - t.false( - zipfiles_hello2.includes(`dataclasses.py`), - 'dataclasses is NOT packaged in function hello2' - ); - - const zipfiles_hello3 = await listZipFiles('.serverless/hello3.zip'); - t.true( - zipfiles_hello3.includes('handler.py'), - 'handler.py is packaged in function hello3' - ); - t.false( - zipfiles_hello3.includes(`flask${sep}__init__.py`), - 'flask 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(); - }, - { skip: !hasPython(2.7) } -); - -test( - 'py2.7 can package flask with package individually & slim option', - async t => { - process.chdir('tests/base'); - const path = npm(['pack', '../..']); - npm(['i', path]); - sls([ - '--individually=true', - '--runtime=python2.7', - '--slim=true', - 'package' - ]); - - 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' - ); - 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(); - }, - { skip: !hasPython(2.7) } -); - test( 'py3.6 can package only requirements of module', async t => { From ab6cedd9dbc5b1e81b45b315af2c3e0e0116fb68 Mon Sep 17 00:00:00 2001 From: Ben Samuel Date: Mon, 14 Jun 2021 11:18:05 -0400 Subject: [PATCH 2/2] Update .github/workflows/test.yml Co-authored-by: Mike Fiedler --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e203e0c5..3665bd86 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: [3.6] + python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2