Drop Python 2.7

This commit is contained in:
mayeut
2021-05-07 11:54:27 -04:00
committed by Henry Schreiner
parent bf31d18fbb
commit 3e22cd9a41
28 changed files with 145 additions and 506 deletions
+5 -5
View File
@@ -5,11 +5,11 @@ from . import test_projects, utils
project_with_skip_asserts = test_projects.new_c_project(
setup_py_add=textwrap.dedent(
r"""
# explode if run on Python 2.7 or Python 3.7 (these should be skipped)
if sys.version_info[0:2] == (2, 7):
raise Exception("Python 2.7 should not be built")
# explode if run on PyPyor Python 3.7 (these should be skipped)
if sys.implementation.name != "cpython":
raise Exception("Only CPython shall be built")
if sys.version_info[0:2] == (3, 7):
raise Exception("Python 3.7 should be skipped")
raise Exception("CPython 3.7 should be skipped")
"""
)
)
@@ -28,7 +28,7 @@ def test(tmp_path):
},
)
# check that we got the right wheels. There should be no 2.7 or 3.7.
# check that we got the right wheels. There should be no PyPy or 3.7.
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if ("-cp3" in w) and ("-cp37" not in w)
]
+14 -105
View File
@@ -36,38 +36,18 @@ spam_system(PyObject *self, PyObject *args)
}
/* Module initialization */
#if PY_MAJOR_VERSION >= 3
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \
m = PyModule_Create(&moduledef);
#define MOD_RETURN(m) return m;
#else
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
m = Py_InitModule3(name, methods, doc);
#define MOD_RETURN(m) return;
#endif
static PyMethodDef module_methods[] = {
{"system", (PyCFunction)spam_system, METH_VARARGS,
"Execute a shell command."},
{NULL} /* Sentinel */
};
MOD_INIT(spam)
PyMODINIT_FUNC PyInit_spam(void)
{
PyObject* m;
MOD_DEF(m,
"spam",
"Example module",
module_methods,
-1)
MOD_RETURN(m)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT, "spam", "Example module", -1, module_methods,
};
return PyModule_Create(&moduledef);
}
"""
@@ -87,15 +67,8 @@ def test_cpp11(tmp_path):
cpp11_project.generate(project_dir)
# VC++ for Python 2.7 does not support modern standards
add_env = {"CIBW_SKIP": "cp27-win* pp27-win32"}
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0")
if "cp27-cp27m-win" not in w and "pp27-pypy_73-win32" not in w
]
actual_wheels = utils.cibuildwheel_run(project_dir)
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0")]
assert set(actual_wheels) == set(expected_wheels)
@@ -113,27 +86,17 @@ def test_cpp14(tmp_path):
cpp14_project.generate(project_dir)
# VC++ for Python 2.7 does not support modern standards
# The manylinux1 docker image does not have a compiler which supports C++11
add_env = {"CIBW_SKIP": "cp27-win* pp27-win32"}
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0")
if "cp27-cp27m-win" not in w and "pp27-pypy_73-win32" not in w
]
actual_wheels = utils.cibuildwheel_run(project_dir)
expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0")]
assert set(actual_wheels) == set(expected_wheels)
cpp17_project = cpp_test_project.copy()
# Python and PyPy 2.7 headers use the `register` keyword, which is forbidden in
# the C++17 standard, so we need the -Wno-register or /wd5033 options
cpp17_project.template_context["extra_compile_args"] = (
["/std:c++17", "/wd5033"] if utils.platform == "windows" else ["-std=c++17", "-Wno-register"]
)
cpp17_project.template_context["extra_compile_args"] = [
"/std:c++17" if utils.platform == "windows" else "-std=c++17"
]
cpp17_project.template_context[
"spam_cpp_top_level_add"
] = r"""
@@ -153,7 +116,7 @@ def test_cpp17(tmp_path):
# Pypy's distutils sets the default compiler to 'msvc9compiler', which
# is too old to support cpp17.
add_env = {"CIBW_SKIP": "cp27-win* pp??-*"}
add_env = {"CIBW_SKIP": "pp??-*"}
if utils.platform == "macos":
add_env["MACOSX_DEPLOYMENT_TARGET"] = "10.13"
@@ -162,61 +125,7 @@ def test_cpp17(tmp_path):
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0", macosx_deployment_target="10.13")
if "cp27-cp27m-win" not in w and "-pp" not in w
]
assert set(actual_wheels) == set(expected_wheels)
def test_cpp17_py27_modern_msvc_workaround(tmp_path):
# This test checks the workaround for building Python 2.7 wheel with MSVC 14
if utils.platform != "windows":
pytest.skip("the test is only relevant to the Windows build")
if os.environ.get("APPVEYOR_BUILD_WORKER_IMAGE", "") == "Visual Studio 2015":
pytest.skip("Visual Studio 2015 does not support C++17")
project_dir = tmp_path / "project"
cpp17_project.generate(project_dir)
# VC++ for Python 2.7 (i.e., MSVC 9) does not support modern standards
# This is a workaround which forces distutils/setupstools to a newer version
# Wheels compiled need a more modern C++ redistributable installed, which is not
# included with Python: see documentation for more info
# DISTUTILS_USE_SDK and MSSdk=1 tell distutils/setuptools that we are adding
# MSVC's compiler, tools, and libraries to PATH ourselves
add_env = {"DISTUTILS_USE_SDK": "1", "MSSdk": "1"}
# Use existing setuptools code to run Visual Studio's vcvarsall.bat and get the
# necessary environment variables, since running vcvarsall.bat in a subprocess
# does not keep the relevant environment variables
# There are different environment variables for 32-bit/64-bit targets, so we
# need to run cibuildwheel twice, once for 32-bit with `vcvarsall.bat x86, and
# once for 64-bit with `vcvarsall.bat x64`
# In a normal CI setup, just run vcvarsall.bat before running cibuildwheel and set
# DISTUTILS_USE_SDK and MSSdk
import setuptools
def add_vcvars(prev_env, platform):
vcvarsall_env = setuptools.msvc.msvc14_get_vc_env(platform)
env = prev_env.copy()
for vcvar in ["path", "include", "lib"]:
env[vcvar] = vcvarsall_env[vcvar]
return env
add_env_x86 = add_vcvars(add_env, "x86")
add_env_x86["CIBW_BUILD"] = "?p27-win32"
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env_x86)
add_env_x64 = add_vcvars(add_env, "x64")
add_env_x64["CIBW_BUILD"] = "cp27-win_amd64"
actual_wheels += utils.cibuildwheel_run(project_dir, add_env=add_env_x64)
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0", exclude_27=False)
if "cp27-cp27m-win" in w or "pp27-pypy_73-win32" in w
if "-pp" not in w
]
assert set(actual_wheels) == set(expected_wheels)
+14 -31
View File
@@ -47,31 +47,28 @@ def get_versions_from_constraint_file(constraint_file):
}
@pytest.mark.parametrize("python_version", ["2.7", "3.6", "3.8", "3.9"])
@pytest.mark.parametrize("python_version", ["3.6", "3.8", "3.9"])
def test_pinned_versions(tmp_path, python_version):
if utils.platform == "linux":
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
if utils.platform == "windows" and python_version == "2.7":
pytest.skip("Windows requires a workaround")
project_dir = tmp_path / "project"
project_with_expected_version_checks.generate(project_dir)
build_environment = {}
if python_version == "2.7":
constraint_filename = "constraints-python27.txt"
build_pattern = "[cp]p27-*"
elif python_version == "3.6":
if python_version == "3.6":
constraint_filename = "constraints-python36.txt"
build_pattern = "[cp]p36-*"
elif python_version == "3.7":
constraint_filename = "constraints-python37.txt"
build_pattern = "[cp]p37-*"
elif python_version == "3.8":
constraint_filename = "constraints-python38.txt"
build_pattern = "[cp]p38-*"
else:
constraint_filename = "constraints.txt"
build_pattern = "[cp]p38-*"
build_pattern = "[cp]p39-*"
constraint_file = cibuildwheel.util.resources_dir / constraint_filename
constraint_versions = get_versions_from_constraint_file(constraint_file)
@@ -92,11 +89,7 @@ def test_pinned_versions(tmp_path, python_version):
)
# also check that we got the right wheels
if python_version == "2.7":
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp27" in w or "-pp27" in w
]
elif python_version == "3.6":
if python_version == "3.6":
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp36" in w or "-pp36" in w
]
@@ -104,26 +97,26 @@ def test_pinned_versions(tmp_path, python_version):
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp38" in w or "-pp38" in w
]
elif python_version == "3.9":
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp39" in w or "-pp39" in w
]
else:
raise ValueError("unhandled python version")
assert set(actual_wheels) == set(expected_wheels)
@pytest.mark.parametrize("python_version", ["2.7", "3.x"])
def test_dependency_constraints_file(tmp_path, python_version):
def test_dependency_constraints_file(tmp_path):
if utils.platform == "linux":
pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead")
if utils.platform == "windows" and python_version == "2.7":
pytest.skip("Windows + Travis CI requires a workaround")
project_dir = tmp_path / "project"
project_with_expected_version_checks.generate(project_dir)
tool_versions = {
"pip": "20.0.2",
"setuptools": "44.0.0" if python_version == "2.7" else "46.0.0",
"setuptools": "53.0.0",
"wheel": "0.34.2",
"virtualenv": "20.0.10",
}
@@ -154,22 +147,12 @@ def test_dependency_constraints_file(tmp_path, python_version):
actual_wheels = utils.cibuildwheel_run(
project_dir,
add_env={
"CIBW_BUILD": "[cp]p27-*" if python_version == "2.7" else "[cp]p3?-*",
"CIBW_ENVIRONMENT": cibw_environment_option,
"CIBW_DEPENDENCY_VERSIONS": str(constraints_file),
},
)
# also check that we got the right wheels
if python_version == "2.7":
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0") if "-cp27" in w or "-pp27" in w
]
else:
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0")
if "-cp27" not in w and "-pp27" not in w
]
expected_wheels = utils.expected_wheels("spam", "0.1.0")
assert set(actual_wheels) == set(expected_wheels)
+2 -4
View File
@@ -37,14 +37,12 @@ def test(tmp_path):
add_env={
"CIBW_MANYLINUX_X86_64_IMAGE": "dockcross/manylinux2010-x64",
"CIBW_MANYLINUX_I686_IMAGE": "dockcross/manylinux2010-x86",
"CIBW_SKIP": "pp* cp27-* cp39-*",
"CIBW_SKIP": "pp* cp39-*",
},
)
# also check that we got the right wheels built
expected_wheels = [
w
for w in utils.expected_wheels("spam", "0.1.0")
if "-pp" not in w and "-cp39-" not in w and "-cp27-" not in w
w for w in utils.expected_wheels("spam", "0.1.0") if "-pp" not in w and "-cp39-" not in w
]
assert set(actual_wheels) == set(expected_wheels)
+3 -7
View File
@@ -65,20 +65,16 @@ def test(manylinux_image, tmp_path):
"CIBW_MANYLINUX_PPC64LE_IMAGE": manylinux_image,
"CIBW_MANYLINUX_S390X_IMAGE": manylinux_image,
}
if manylinux_image == "manylinux1":
if manylinux_image in {"manylinux1", "manylinux2014", "manylinux_2_24"}:
# We don't have a manylinux1 image for PyPy
# We don't have a manylinux2014 / manylinux_2_24 image for PyPy (yet?)
add_env["CIBW_SKIP"] = "pp*"
elif manylinux_image in {"manylinux2014", "manylinux_2_24"}:
# We don't have a manylinux2014 / 'manylinux_2_24' image for PyPy (yet?)
# Python 2.7 not available on manylinux2014 / 'manylinux_2_24'
add_env["CIBW_SKIP"] = "cp27* pp*"
actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env)
expected_wheels = [
w for w in utils.expected_wheels("spam", "0.1.0", manylinux_versions=[manylinux_image])
]
if manylinux_image in {"manylinux2014", "manylinux_2_24"}:
expected_wheels = [w for w in expected_wheels if "-cp27" not in w]
if manylinux_image in {"manylinux1", "manylinux2014", "manylinux_2_24"}:
expected_wheels = [w for w in expected_wheels if "-pp" not in w]
assert set(actual_wheels) == set(expected_wheels)
+2 -6
View File
@@ -8,10 +8,7 @@ basic_project = test_projects.new_c_project(
"""
# Will fail if PEP 518 does work
import requests
if sys.version_info < (3, 6, 0):
assert requests.__version__ == "2.22.0", "Requests found but wrong version ({0})".format(requests.__version__)
else:
assert requests.__version__ == "2.23.0", "Requests found but wrong version ({0})".format(requests.__version__)
assert requests.__version__ == "2.23.0", "Requests found but wrong version ({0})".format(requests.__version__)
# Just making sure environment is still set
import os
@@ -29,8 +26,7 @@ requires = [
"setuptools >= 42",
"setuptools_scm[toml]>=4.1.2",
"wheel",
"requests==2.22.0; python_version<'3.6'",
"requests==2.23.0; python_version>='3.6'"
"requests==2.23.0"
]
build-backend = "setuptools.build_meta"
+5 -25
View File
@@ -24,38 +24,18 @@ spam_system(PyObject *self, PyObject *args)
}
/* Module initialization */
#if PY_MAJOR_VERSION >= 3
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \
m = PyModule_Create(&moduledef);
#define MOD_RETURN(m) return m;
#else
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
m = Py_InitModule3(name, methods, doc);
#define MOD_RETURN(m) return;
#endif
static PyMethodDef module_methods[] = {
{"system", (PyCFunction)spam_system, METH_VARARGS,
"Execute a shell command."},
{NULL} /* Sentinel */
};
MOD_INIT(spam)
PyMODINIT_FUNC PyInit_spam(void)
{
PyObject* m;
MOD_DEF(m,
"spam",
"Example module",
module_methods,
-1)
MOD_RETURN(m)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT, "spam", "Example module", -1, module_methods,
};
return PyModule_Create(&moduledef);
}
"""
+1 -4
View File
@@ -7,10 +7,7 @@ project_with_ssl_tests = test_projects.new_c_project(
r"""
import ssl
if sys.version_info[0] == 2:
from urllib2 import urlopen
else:
from urllib.request import urlopen
from urllib.request import urlopen
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
data = urlopen("https://www.nist.gov", context=context)
+1 -2
View File
@@ -52,8 +52,7 @@ class TestSpam(TestCase):
# sys.prefix is different from sys.base_prefix when running a virtualenv
# See https://docs.python.org/3/library/venv.html, which virtualenv seems
# to honor in recent releases
# Python 2 doesn't have sys.base_prefix by default
if not hasattr(sys, 'base_prefix') or sys.prefix == sys.base_prefix:
if sys.prefix == sys.base_prefix:
self.fail("Not running in a virtualenv")
self.assertTrue(path_contains(sys.prefix, sys.executable))
+5 -28
View File
@@ -6,11 +6,9 @@ This file is added to the PYTHONPATH in the test runner at bin/run_test.py.
import os
import platform as pm
import shutil
import subprocess
import sys
from contextlib import contextmanager
from tempfile import mkdtemp
from tempfile import TemporaryDirectory
platform: str
@@ -26,17 +24,6 @@ else:
raise Exception("Unsupported platform")
# Python 2 does not have a tempfile.TemporaryDirectory context manager
@contextmanager
def TemporaryDirectoryIfNone(path):
_path = path or mkdtemp()
try:
yield _path
finally:
if path is None:
shutil.rmtree(_path)
def cibuildwheel_get_build_identifiers(project_path, env=None):
"""
Returns the list of build identifiers that cibuildwheel will try to build
@@ -76,21 +63,21 @@ def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, outp
if add_env is not None:
env.update(add_env)
with TemporaryDirectoryIfNone(output_dir) as _output_dir:
with TemporaryDirectory() as tmp_output_dir:
subprocess.run(
[
sys.executable,
"-m",
"cibuildwheel",
"--output-dir",
str(_output_dir),
str(output_dir or tmp_output_dir),
str(package_dir),
],
env=env,
cwd=project_path,
check=True,
)
wheels = os.listdir(_output_dir)
wheels = os.listdir(output_dir or tmp_output_dir)
return wheels
@@ -113,8 +100,6 @@ def expected_wheels(
manylinux_versions=None,
macosx_deployment_target="10.9",
machine_arch=None,
*,
exclude_27=platform == "windows",
):
"""
Returns a list of expected wheels from a run of cibuildwheel.
@@ -136,10 +121,7 @@ def expected_wheels(
python_abi_tags = ["cp36-cp36m", "cp37-cp37m", "cp38-cp38", "cp39-cp39"]
if machine_arch in ["x86_64", "AMD64", "x86"]:
python_abi_tags += ["cp27-cp27m", "pp27-pypy_73", "pp36-pypy36_pp73", "pp37-pypy37_pp73"]
if platform == "linux":
python_abi_tags.append("cp27-cp27mu") # python 2.7 has 2 different ABI on manylinux
python_abi_tags += ["pp36-pypy36_pp73", "pp37-pypy37_pp73"]
if platform == "macos" and get_macos_version() >= (10, 16):
# 10.16 is sometimes reported as the macOS version on macOS 11.
@@ -193,11 +175,6 @@ def expected_wheels(
for platform_tag in platform_tags:
wheels.append(f"{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl")
# Travis on Windows does not support using the default Python 2.7 compiler,
# so we support skipping here.
if exclude_27:
wheels = [w for w in wheels if "-cp27-" not in w and "-pp2" not in w]
return wheels