From 1caca79910e1ab5a724b1ac82aa5ed4c5a7c5239 Mon Sep 17 00:00:00 2001 From: James Saryerwinnie Date: Wed, 21 Feb 2024 12:59:33 -0500 Subject: [PATCH] Drop support for Python 3.7 Following the policy outlined in: https://aws.amazon.com/blogs/developer/python-support-policy-updates-for-aws-sdks-and-tools/ The PSF dropped support for Python 3.7 June 2023, and the AWS SDKs dropped support for Python 3.7 December 2023. You can also no longer create or update Lambda functions on Python 3.7. --- .../61280530708-enhancement-Python-7389.json | 5 +++ .github/workflows/run-tests.yml | 22 +--------- chalice/config.py | 20 +++++---- chalice/deploy/packager.py | 3 -- setup.py | 3 -- tests/functional/test_deployer.py | 44 +++++++++---------- 6 files changed, 39 insertions(+), 58 deletions(-) create mode 100644 .changes/next-release/61280530708-enhancement-Python-7389.json diff --git a/.changes/next-release/61280530708-enhancement-Python-7389.json b/.changes/next-release/61280530708-enhancement-Python-7389.json new file mode 100644 index 000000000..f986e3782 --- /dev/null +++ b/.changes/next-release/61280530708-enhancement-Python-7389.json @@ -0,0 +1,5 @@ +{ + "type": "enhancement", + "category": "Python", + "description": "Drop support for Python 3.7 (#2095)" +} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c7aad1b21..0dc2eb3c4 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -29,31 +29,11 @@ jobs: make install-dev-deps - name: Run PRCheck run: make prcheck - testsonly: - runs-on: ${{ matrix.os }} - env: - HYPOTHESIS_PROFILE: ci - CHALICE_TEST_EXTENDED_PACKAGING: true - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - python-version: [3.7] - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - name: Set up Python ${{ matrix.python-version }} - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - pip install -r requirements-test.txt --upgrade --upgrade-strategy eager -e . - - name: Run Tests - run: make coverage cdktests: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, '3.10', 3.11] + python-version: [3.8, 3.9, '3.10', 3.11] cdk-version: [cdk, cdkv2] steps: - uses: actions/checkout@v2 diff --git a/chalice/config.py b/chalice/config.py index 9b73a682a..b57455620 100644 --- a/chalice/config.py +++ b/chalice/config.py @@ -148,16 +148,18 @@ def lambda_python_version(self) -> str: # we attempt to match your python version to the closest version # supported by lambda. major, minor = sys.version_info[0], sys.version_info[1] - if major == 2: - return 'python2.7' - # Python 3 for backwards compatibility needs to select python3.6 - # for python versions 3.0-3.6. 3.7-3.10 will use their version. - # 3.11 and higher will use 3.11 - elif (major, minor) <= (3, 6): - return 'python3.6' - elif (major, minor) <= (3, 10): + # We default to the minimum version supported by Lambda if you're + # using an version no longer supported by Lambda. + if (major, minor) < (3, 8): + return 'python3.8' + elif (major, minor) <= (3, 11): + # Otherwise we use your current version of python if Lambda + # supports it. return 'python%s.%s' % (major, minor) - return 'python3.11' + else: + # Otherwise if you're using a new version than what's supported + # by Lambda we default to the latest version Lambda supports. + return 'python3.11' @property def log_retention_in_days(self) -> int: diff --git a/chalice/deploy/packager.py b/chalice/deploy/packager.py index 813e57d34..30bb6bdea 100644 --- a/chalice/deploy/packager.py +++ b/chalice/deploy/packager.py @@ -76,9 +76,6 @@ class BaseLambdaDeploymentPackager(object): _VENDOR_DIR = 'vendor' _RUNTIME_TO_ABI = { - 'python2.7': 'cp27mu', - 'python3.6': 'cp36m', - 'python3.7': 'cp37m', 'python3.8': 'cp38', 'python3.9': 'cp39', 'python3.10': 'cp310', diff --git a/setup.py b/setup.py index 289632731..5628d3593 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,6 @@ def recursive_include(relative_dir): install_requires = [ 'click>=7,<9.0', 'botocore>=1.14.0,<2.0.0', - 'typing==3.6.4;python_version<"3.7"', 'typing-extensions>=4.0.0,<5.0.0', 'six>=1.10.0,<2.0.0', 'pip>=9,<23.4', @@ -70,8 +69,6 @@ def recursive_include(relative_dir): 'License :: OSI Approved :: Apache Software License', 'Natural Language :: English', "Programming Language :: Python :: 3", - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', diff --git a/tests/functional/test_deployer.py b/tests/functional/test_deployer.py index 7e3bc2288..1bfd81c6c 100644 --- a/tests/functional/test_deployer.py +++ b/tests/functional/test_deployer.py @@ -72,7 +72,7 @@ def test_can_create_deployment_package(tmpdir, chalice_deployer): appdir.join('app.py').write('# Test app') chalice_dir = appdir.join('.chalice') chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') # There should now be a zip file created. contents = chalice_dir.join('deployments').listdir() assert len(contents) == 1 @@ -85,7 +85,7 @@ def test_can_inject_latest_app(tmpdir, chalice_deployer): appdir.join('app.py').write('# Test app v1') chalice_dir = appdir.join('.chalice') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') # Now suppose we update our app code but not any deps. # We can use inject_latest_app. @@ -105,7 +105,7 @@ def test_zipfile_hash_only_based_on_contents(tmpdir, chalice_deployer): appdir = _create_app_structure(tmpdir) appdir.join('app.py').write('# Test app v1') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with open(name, 'rb') as f: original_checksum = hashlib.md5(f.read()).hexdigest() @@ -118,7 +118,7 @@ def test_zipfile_hash_only_based_on_contents(tmpdir, chalice_deployer): # checksum. os.utime(str(app_file), (631152000.0, 631152000.0)) name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with open(name, 'rb') as f: new_checksum = hashlib.md5(f.read()).hexdigest() assert new_checksum == original_checksum @@ -129,7 +129,7 @@ def test_app_injection_still_compresses_file(tmpdir, chalice_deployer): appdir = _create_app_structure(tmpdir) appdir.join('app.py').write('# Test app v1') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') original_size = os.path.getsize(name) appdir.join('app.py').write('# Test app v2') chalice_deployer.inject_latest_app(name, str(appdir)) @@ -148,7 +148,7 @@ def test_no_error_message_printed_on_empty_reqs_file(tmpdir, appdir.join('app.py').write('# Foo') appdir.join('requirements.txt').write('\n') chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') out, err = capfd.readouterr() assert err.strip() == '' @@ -182,7 +182,7 @@ def test_includes_app_and_chalicelib_dir(tmpdir, chalice_deployer): subdir.join('submodule.py').write('# Test submodule') subdir.join('subconfig.json').write('{"test": "subconfig"}') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('chalicelib/__init__.py', b'# Test package', f) _assert_in_zip('chalicelib/mymodule.py', b'# Test module', f) @@ -213,7 +213,7 @@ def test_subsequent_deploy_replaces_chalicelib(tmpdir, chalice_deployer): subdir.join('submodule.py').write('# Test submodule') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') subdir.join('submodule.py').write('# Test submodule v2') appdir.join('chalicelib', '__init__.py').remove() chalice_deployer.inject_latest_app(name, str(appdir)) @@ -232,7 +232,7 @@ def test_vendor_dir_included(tmpdir, chalice_deployer): extra_package = vendor.mkdir('mypackage') extra_package.join('__init__.py').write('# Test package') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('mypackage/__init__.py', b'# Test package', f) @@ -248,7 +248,7 @@ def test_no_vendor_in_app_only_packager(tmpdir, app_only_packager): extra_package = vendor.mkdir('mypackage') extra_package.join('__init__.py').write('# Test package') name = packager.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_not_in_zip('mypackage/__init__.py', f) _assert_in_zip('chalicelib/__init__.py', b'# Test package', f) @@ -267,16 +267,16 @@ def test_py_deps_in_layer_package(tmpdir, layer_packager): extra_package = vendor.mkdir('mypackage') extra_package.join('__init__.py').write('# Test package') name = packager.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') assert os.path.basename(name).startswith('managed-layer-') with zipfile.ZipFile(name) as f: - prefix = 'python/lib/python2.7/site-packages' + prefix = 'python/lib/python3.11/site-packages' _assert_in_zip( '%s/mypackage/__init__.py' % prefix, b'# Test package', f) _assert_not_in_zip('%s/chalicelib/__init__.py' % prefix, f) _assert_not_in_zip('%s/app.py' % prefix, f) deps_builder.build_site_packages.assert_called_with( - 'cp27mu', str(appdir.join('requirements.txt')), mock.ANY + 'cp311', str(appdir.join('requirements.txt')), mock.ANY ) @@ -286,10 +286,10 @@ def test_empty_layer_package_raises_error(tmpdir, layer_packager): appdir.mkdir('chalicelib') appdir.join('requirements.txt').write('') appdir.join('chalicelib', '__init__.py').write('# Test package') - filename = packager.deployment_package_filename(str(appdir), 'python2.7') + filename = packager.deployment_package_filename(str(appdir), 'python3.11') with pytest.raises(EmptyPackageError): packager.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') # We should also verify that the file does not exist so it doesn't # get reused in subsequent caches. This shouldn't affect anything, # we're just trying to cleanup properly. @@ -303,11 +303,11 @@ def test_subsequent_deploy_replaces_vendor_dir(tmpdir, chalice_deployer): extra_package = vendor.mkdir('mypackage') extra_package.join('__init__.py').write('# v1') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') # Now we update a package in vendor/ with a new version. extra_package.join('__init__.py').write('# v2') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('mypackage/__init__.py', b'# v2', f) @@ -320,7 +320,7 @@ def test_vendor_symlink_included(tmpdir, chalice_deployer): vendor = appdir.mkdir('vendor') os.symlink(str(extra_package), str(vendor.join('otherpackage'))) name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('otherpackage/__init__.py', b'# Test package', f) @@ -333,13 +333,13 @@ def test_subsequent_deploy_replaces_vendor_symlink(tmpdir, chalice_deployer): vendor = appdir.mkdir('vendor') os.symlink(str(extra_package), str(vendor.join('otherpackage'))) name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('otherpackage/__init__.py', b'# v1', f) # Now we update a package in vendor/ with a new version. extra_package.join('__init__.py').write('# v2') name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') with zipfile.ZipFile(name) as f: _assert_in_zip('otherpackage/__init__.py', b'# v2', f) @@ -375,7 +375,7 @@ def test_zip_filename_changes_on_vendor_symlink(tmpdir, chalice_deployer): def test_chalice_runtime_injected_on_change(tmpdir, chalice_deployer): appdir = _create_app_structure(tmpdir) name = chalice_deployer.create_deployment_package( - str(appdir), 'python2.7') + str(appdir), 'python3.11') # We're verifying that we always inject the chalice runtime # but we can't actually modify the runtime in this repo, so # instead we'll modify the deployment package and change the @@ -405,7 +405,7 @@ def test_does_handle_missing_dependency_error(tmpdir): dependency_builder=builder, ui=ui, ) - packager.create_deployment_package(str(appdir), 'python2.7') + packager.create_deployment_package(str(appdir), 'python3.11') output = ''.join([call[0][0] for call in ui.write.call_args_list]) assert 'Could not install dependencies:\nfoo==1.2' in output