diff --git a/aws_lambda_builders/validator.py b/aws_lambda_builders/validator.py index ce66282a7..05c179c86 100644 --- a/aws_lambda_builders/validator.py +++ b/aws_lambda_builders/validator.py @@ -15,7 +15,6 @@ "nodejs14.x": [ARM64, X86_64], "nodejs16.x": [ARM64, X86_64], "nodejs18.x": [ARM64, X86_64], - "python3.6": [X86_64], "python3.7": [X86_64], "python3.8": [ARM64, X86_64], "python3.9": [ARM64, X86_64], diff --git a/aws_lambda_builders/workflows/python_pip/packager.py b/aws_lambda_builders/workflows/python_pip/packager.py index f43b0c274..1b7d23a69 100644 --- a/aws_lambda_builders/workflows/python_pip/packager.py +++ b/aws_lambda_builders/workflows/python_pip/packager.py @@ -82,7 +82,6 @@ def __init__(self, version): def get_lambda_abi(runtime): supported = { - "python3.6": "cp36m", "python3.7": "cp37m", "python3.8": "cp38", "python3.9": "cp39", @@ -100,7 +99,7 @@ def __init__(self, runtime, osutils=None, dependency_builder=None, architecture= :type runtime: str :param runtime: Python version to build dependencies for. This can - either be python3.6, python3.7, python3.8 or python3.9. These are currently the + either be python3.7, python3.8 or python3.9. These are currently the only supported values. :type osutils: :class:`lambda_builders.utils.OSUtils` @@ -199,8 +198,6 @@ class DependencyBuilder(object): # Mapping of abi to glibc version in Lambda runtime. _RUNTIME_GLIBC = { - "cp27mu": (2, 17), - "cp36m": (2, 17), "cp37m": (2, 17), "cp38": (2, 26), "cp39": (2, 26), @@ -410,15 +407,11 @@ def _is_compatible_wheel_filename(self, filename): return True prefix_version = implementation[:3] if prefix_version == "cp3": - # Deploying python 3 function which means we need cp36m abi + # Deploying python 3 function which means we need cp37m abi # We can also accept abi3 which is the CPython 3 Stable ABI and # will work on any version of python 3. if abi == lambda_runtime_abi or abi == "abi3": return True - elif prefix_version == "cp2": - # Deploying to python 2 function which means we need cp27mu abi - if abi == "cp27mu": - return True # Don't know what we have but it didn't pass compatibility tests. return False diff --git a/aws_lambda_builders/workflows/python_pip/validator.py b/aws_lambda_builders/workflows/python_pip/validator.py index f3cd35808..7790b04c5 100644 --- a/aws_lambda_builders/workflows/python_pip/validator.py +++ b/aws_lambda_builders/workflows/python_pip/validator.py @@ -31,7 +31,7 @@ def validate(self, runtime_path): Returns ------- str - runtime_path, runtime to check eg: /usr/bin/python3.6 + runtime_path, runtime to check eg: /usr/bin/python3.9 Raises ------ diff --git a/pyproject.toml b/pyproject.toml index 584411312..ca16b1909 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ ignore = ["PLR0913"] [tool.black] line-length = 120 -target_version = ['py37', 'py36', 'py38'] +target_version = ['py37', 'py38', 'py39'] exclude = ''' ( diff --git a/requirements/dev.txt b/requirements/dev.txt index aa7562420..4a87142bc 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -11,11 +11,6 @@ mock==4.0.2 parameterized==0.7.4 pyelftools~=0.27 # Used to verify the generated Go binary architecture in integration tests (utils.py) - -# tempfile backport for < 3.7 -backports.tempfile==1.0; python_version<"3.7" - - # formatter black==22.3.0 ruff \ No newline at end of file diff --git a/setup.py b/setup.py index 2d578ab07..c5fe08787 100644 --- a/setup.py +++ b/setup.py @@ -43,8 +43,8 @@ def read_version(): license="Apache License 2.0", packages=find_packages(exclude=["tests.*", "tests"]), keywords="AWS Lambda Functions Building", - # Support 3.6 or greater - python_requires=(">=3.6"), + # Support 3.7 or greater + python_requires=(">=3.7"), entry_points={"console_scripts": ["{}=aws_lambda_builders.__main__:main".format(cmd_name)]}, install_requires=read_requirements("base.txt") + read_requirements("python_pip.txt"), extras_require={"dev": read_requirements("dev.txt")}, @@ -58,7 +58,6 @@ def read_version(): "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", diff --git a/tests/functional/workflows/python_pip/test_packager.py b/tests/functional/workflows/python_pip/test_packager.py index 643b08ad3..ed0ae4fb7 100644 --- a/tests/functional/workflows/python_pip/test_packager.py +++ b/tests/functional/workflows/python_pip/test_packager.py @@ -204,7 +204,7 @@ def _write_requirements_txt(self, packages, directory): def _make_appdir_and_dependency_builder(self, reqs, tmpdir, runner, **kwargs): appdir = str(_create_app_structure(tmpdir)) self._write_requirements_txt(reqs, appdir) - builder = DependencyBuilder(OSUtils(), "python3.6", runner, **kwargs) + builder = DependencyBuilder(OSUtils(), "python3.9", runner, **kwargs) return appdir, builder def test_can_build_local_dir_as_whl(self, tmpdir, pip_runner, osutils): @@ -215,7 +215,7 @@ def test_can_build_local_dir_as_whl(self, tmpdir, pip_runner, osutils): pip.set_return_tuple(0, (b"Processing ../foo\n" b" Link is a directory," b" ignoring download_dir"), b"") pip.wheels_to_build( expected_args=["--no-deps", "--wheel-dir", mock.ANY, "../foo"], - wheels_to_build=["foo-1.2-cp36-none-any.whl"], + wheels_to_build=["foo-1.2-cp39-none-any.whl"], ) site_packages = os.path.join(appdir, "site-packages") @@ -233,7 +233,7 @@ def test_can_get_whls_all_manylinux(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl", "bar-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl", "bar-1.2-cp39-cp39-manylinux1_x86_64.whl"], ) site_packages = os.path.join(appdir, ".chalice.", "site-packages") @@ -276,7 +276,7 @@ def test_can_expand_purelib_whl(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["foo-1.2.data/purelib/foo/"], ) @@ -296,7 +296,7 @@ def test_can_expand_platlib_whl(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["foo-1.2.data/platlib/foo/"], ) @@ -318,7 +318,7 @@ def test_can_expand_platlib_and_purelib(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["foo-1.2.data/platlib/foo/", "foo-1.2.data/purelib/bar/"], ) @@ -340,7 +340,7 @@ def test_does_ignore_data(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["foo/placeholder", "foo-1.2.data/data/bar/"], ) @@ -363,7 +363,7 @@ def test_does_ignore_include(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["foo/placeholder", "foo.1.2.data/includes/bar/"], ) @@ -386,7 +386,7 @@ def test_does_ignore_scripts(self, tmpdir, pip_runner, osutils): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=["{package_name}/placeholder", "{data_dir}/scripts/bar/placeholder"], ) @@ -410,7 +410,7 @@ def test_can_expand_platlib_and_platlib_and_root(self, tmpdir, pip_runner, osuti requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2-cp39-cp39-manylinux1_x86_64.whl"], whl_contents=[ "{package_name}/placeholder", "{data_dir}/platlib/bar/placeholder", @@ -435,9 +435,9 @@ def test_can_get_whls_mixed_compat(self, tmpdir, osutils, pip_runner): pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], packages=[ - "foo-1.0-cp36-none-any.whl", - "bar-1.2-cp36-cp36m-manylinux1_x86_64.whl", - "baz-1.5-cp36-cp36m-linux_x86_64.whl", + "foo-1.0-cp39-none-any.whl", + "bar-1.2-cp39-cp39-manylinux1_x86_64.whl", + "baz-1.5-cp39-cp39-linux_x86_64.whl", ], ) @@ -458,7 +458,7 @@ def test_can_support_pep_600_tags(self, tmpdir, osutils, pip_runner): pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], packages=[ - "foo-1.2-cp36-cp36m-manylinux_2_12_x86_64.whl", + "foo-1.2-cp39-cp39-manylinux_2_12_x86_64.whl", ], ) @@ -479,30 +479,7 @@ def test_can_support_compressed_tags(self, tmpdir, osutils, pip_runner): pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], packages=[ - "foo-1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", - ], - ) - - site_packages = os.path.join(appdir, ".chalice.", "site-packages") - with osutils.tempdir() as scratch_dir: - builder.build_site_packages(requirements_file, site_packages, scratch_dir) - installed_packages = os.listdir(site_packages) - - pip.validate() - for req in reqs: - assert req in installed_packages - - def test_can_get_py27_whls(self, tmpdir, osutils, pip_runner): - reqs = ["foo", "bar", "baz"] - pip, runner = pip_runner - appdir, builder = self._make_appdir_and_dependency_builder(reqs, tmpdir, runner) - requirements_file = os.path.join(appdir, "requirements.txt") - pip.packages_to_download( - expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=[ - "foo-1.0-cp27-none-any.whl", - "bar-1.2-cp27-none-manylinux1_x86_64.whl", - "baz-1.5-cp27-cp27mu-linux_x86_64.whl", + "foo-1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", ], ) @@ -523,9 +500,9 @@ def test_can_get_arm64_whls(self, tmpdir, osutils, pip_runner): pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], packages=[ - "foo-1.0-cp36-none-any.whl", - "bar-1.2-cp36-none-manylinux2014_aarch64.whl", - "baz-1.5-cp36-cp36m-manylinux2014_aarch64.whl", + "foo-1.0-cp39-none-any.whl", + "bar-1.2-cp39-none-manylinux2014_aarch64.whl", + "baz-1.5-cp39-cp39-manylinux2014_aarch64.whl", ], ) @@ -613,10 +590,10 @@ def test_does_fail_on_pep_600_tag_with_unsupported_glibc_version(self, tmpdir, o pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], packages=[ - "foo-1.2-cp36-cp36m-manylinux_2_12_x86_64.whl", - "bar-1.2-cp36-cp36m-manylinux_2_999_x86_64.whl", - "baz-1.2-cp36-cp36m-manylinux_3_12_x86_64.whl", - "qux-1.2-cp36-cp36m-manylinux_3_999_x86_64.whl", + "foo-1.2-cp39-cp39-manylinux_2_12_x86_64.whl", + "bar-1.2-cp39-cp39-manylinux_2_999_x86_64.whl", + "baz-1.2-cp39-cp39-manylinux_3_12_x86_64.whl", + "qux-1.2-cp39-cp39-manylinux_3_999_x86_64.whl", ], ) @@ -642,7 +619,7 @@ def test_can_replace_incompat_whl(self, tmpdir, osutils, pip_runner): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.0-cp36-none-any.whl", "bar-1.2-cp36-cp36m-macosx_10_6_intel.whl"], + packages=["foo-1.0-cp39-none-any.whl", "bar-1.2-cp39-cp39-macosx_10_6_intel.whl"], ) # Once the initial download has 1 incompatible whl file. The second, # more targeted download, finds manylinux1_x86_64 and downloads that. @@ -660,7 +637,7 @@ def test_can_replace_incompat_whl(self, tmpdir, osutils, pip_runner): mock.ANY, "bar==1.2", ], - packages=["bar-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["bar-1.2-cp39-cp39-manylinux1_x86_64.whl"], ) site_packages = os.path.join(appdir, ".chalice.", "site-packages") with osutils.tempdir() as scratch_dir: @@ -711,13 +688,13 @@ def test_can_build_sdist(self, tmpdir, osutils, pip_runner): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2.zip", "bar-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2.zip", "bar-1.2-cp39-cp39-manylinux1_x86_64.whl"], ) # Foo is built from and is pure python so it yields a compatible # wheel file. pip.wheels_to_build( expected_args=["--no-deps", "--wheel-dir", mock.ANY, PathArgumentEndingWith("foo-1.2.zip")], - wheels_to_build=["foo-1.2-cp36-none-any.whl"], + wheels_to_build=["foo-1.2-cp39-none-any.whl"], ) site_packages = os.path.join(appdir, ".chalice.", "site-packages") with osutils.tempdir() as scratch_dir: @@ -735,7 +712,7 @@ def test_build_sdist_makes_incompatible_whl(self, tmpdir, osutils, pip_runner): requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2.zip", "bar-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2.zip", "bar-1.2-cp39-cp39-manylinux1_x86_64.whl"], ) # foo is compiled since downloading it failed to get any wheels. And # the second download for manylinux1_x86_64 wheels failed as well. @@ -744,7 +721,7 @@ def test_build_sdist_makes_incompatible_whl(self, tmpdir, osutils, pip_runner): # can do to install this package. pip.wheels_to_build( expected_args=["--no-deps", "--wheel-dir", mock.ANY, PathArgumentEndingWith("foo-1.2.zip")], - wheels_to_build=["foo-1.2-cp36-cp36m-macosx_10_6_intel.whl"], + wheels_to_build=["foo-1.2-cp39-cp39-macosx_10_6_intel.whl"], ) site_packages = os.path.join(appdir, ".chalice.", "site-packages") with osutils.tempdir() as scratch_dir: @@ -813,7 +790,7 @@ def test_build_into_existing_dir_with_preinstalled_packages(self, tmpdir, osutil requirements_file = os.path.join(appdir, "requirements.txt") pip.packages_to_download( expected_args=["-r", requirements_file, "--dest", mock.ANY, "--exists-action", "i"], - packages=["foo-1.2.zip", "bar-1.2-cp36-cp36m-manylinux1_x86_64.whl"], + packages=["foo-1.2.zip", "bar-1.2-cp39-cp39-manylinux1_x86_64.whl"], ) pip.packages_to_download( expected_args=[ @@ -829,7 +806,7 @@ def test_build_into_existing_dir_with_preinstalled_packages(self, tmpdir, osutil mock.ANY, "foo==1.2", ], - packages=["foo-1.2-cp36-cp36m-macosx_10_6_intel.whl"], + packages=["foo-1.2-cp39-cp39-macosx_10_6_intel.whl"], ) # Add two fake packages foo and bar that have previously been diff --git a/tests/integration/workflows/python_pip/test_python_pip.py b/tests/integration/workflows/python_pip/test_python_pip.py index 3e1fe6cb3..705cb676a 100644 --- a/tests/integration/workflows/python_pip/test_python_pip.py +++ b/tests/integration/workflows/python_pip/test_python_pip.py @@ -57,7 +57,6 @@ def setUp(self): language=self.builder.capability.language, major=sys.version_info.major, minor=sys.version_info.minor ) self.runtime_mismatch = { - "python3.6": "python3.7", "python3.7": "python3.8", "python3.8": "python3.9", "python3.9": "python3.7", @@ -93,12 +92,8 @@ def test_must_build_python_project(self): experimental_flags=self.experimental_flags, ) - if self.runtime == "python3.6": - self.check_architecture_in("numpy-1.17.4.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) - expected_files = self.test_data_files.union({"numpy", "numpy-1.17.4.dist-info"}) - else: - self.check_architecture_in("numpy-1.20.3.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) - expected_files = self.test_data_files.union({"numpy", "numpy-1.20.3.dist-info", "numpy.libs"}) + self.check_architecture_in("numpy-1.20.3.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) + expected_files = self.test_data_files.union({"numpy", "numpy-1.20.3.dist-info", "numpy.libs"}) output_files = set(os.listdir(self.artifacts_dir)) self.assertEqual(expected_files, output_files) @@ -118,13 +113,8 @@ def test_must_build_python_project_python3_binary(self): experimental_flags=self.experimental_flags, executable_search_paths=[executable_dir], ) - - if self.runtime == "python3.6": - self.check_architecture_in("numpy-1.17.4.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) - expected_files = self.test_data_files.union({"numpy", "numpy-1.17.4.dist-info"}) - else: - self.check_architecture_in("numpy-1.20.3.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) - expected_files = self.test_data_files.union({"numpy", "numpy-1.20.3.dist-info", "numpy.libs"}) + self.check_architecture_in("numpy-1.20.3.dist-info", ["manylinux2010_x86_64", "manylinux1_x86_64"]) + expected_files = self.test_data_files.union({"numpy", "numpy-1.20.3.dist-info", "numpy.libs"}) output_files = set(os.listdir(self.artifacts_dir)) self.assertEqual(expected_files, output_files) diff --git a/tests/unit/test_validator.py b/tests/unit/test_validator.py index 8e889c2f3..083774aa6 100644 --- a/tests/unit/test_validator.py +++ b/tests/unit/test_validator.py @@ -22,7 +22,7 @@ def test_validate_with_unsupported_runtime(self): validator.validate("/usr/bin/unknown_runtime") def test_validate_with_runtime_and_incompatible_architecture(self): - runtime_list = ["python3.6", "python3.7"] + runtime_list = ["python3.7"] for runtime in runtime_list: validator = RuntimeValidator(runtime=runtime, architecture="arm64") with self.assertRaises(UnsupportedArchitectureError): diff --git a/tests/unit/workflows/python_pip/test_packager.py b/tests/unit/workflows/python_pip/test_packager.py index 7eaeb30b1..f27686af8 100644 --- a/tests/unit/workflows/python_pip/test_packager.py +++ b/tests/unit/workflows/python_pip/test_packager.py @@ -90,9 +90,6 @@ def popen(self, *args, **kwargs): class TestGetLambdaAbi(object): - def test_get_lambda_abi_python36(self): - assert "cp36m" == get_lambda_abi("python3.6") - def test_get_lambda_abi_python37(self): assert "cp37m" == get_lambda_abi("python3.7") @@ -157,7 +154,7 @@ def test_same_pkg_is_eq(self): def test_pkg_is_eq_to_similar_pkg(self): pure_pkg = Package("", "foobar-1.0-py3-none-any.whl") - plat_pkg = Package("", "foobar-1.0-py3-py36m-manylinux1_x86_64.whl") + plat_pkg = Package("", "foobar-1.0-py3-py39-manylinux1_x86_64.whl") assert pure_pkg == plat_pkg def test_pkg_is_not_equal_to_different_type(self): diff --git a/tests/unit/workflows/python_pip/test_validator.py b/tests/unit/workflows/python_pip/test_validator.py index 6d5abfcb7..cf9f7ac23 100644 --- a/tests/unit/workflows/python_pip/test_validator.py +++ b/tests/unit/workflows/python_pip/test_validator.py @@ -35,7 +35,7 @@ def test_runtime_validate_mismatch_version_runtime(self): with mock.patch("subprocess.Popen") as mock_subprocess: mock_subprocess.return_value = MockSubProcess(1) with self.assertRaises(MisMatchRuntimeError): - self.validator.validate(runtime_path="/usr/bin/python3.6") + self.validator.validate(runtime_path="/usr/bin/python3.9") self.assertTrue(mock_subprocess.call_count, 1) def test_python_command(self): @@ -46,7 +46,6 @@ def test_python_command(self): @parameterized.expand( [ - ("python3.6", "arm64"), ("python3.7", "arm64"), ] )