Unverified Commit 522c59ce authored by Henry Schreiner's avatar Henry Schreiner Committed by GitHub
Browse files

chore: drop Python 3.5 (#3719)



* chore: drop Python 3.5 support

* chore: more fstrings with flynt's help

* ci: drop Python 3.5

* chore: bump dependency versions

* docs: touch up py::args

* tests: remove deprecation warning

* Ban smartquotes

* Very minor tweaks (by-product of reviewing PR #3719).
Co-authored-by: default avatarAaron Gokaslan <skylion.aaron@gmail.com>
Co-authored-by: default avatarRalf W. Grosse-Kunstleve <rwgk@google.com>
parent 1a432b42
...@@ -2,7 +2,7 @@ import nox ...@@ -2,7 +2,7 @@ import nox
nox.options.sessions = ["lint", "tests", "tests_packaging"] nox.options.sessions = ["lint", "tests", "tests_packaging"]
PYTHON_VERSIONS = ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
@nox.session(reuse_venv=True) @nox.session(reuse_venv=True)
......
import sys import sys
if sys.version_info < (3, 5): if sys.version_info < (3, 6):
msg = "pybind11 does not support Python < 3.5. 2.9 was the last release supporting older Pythons." msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
raise ImportError(msg) raise ImportError(msg)
......
...@@ -200,7 +200,7 @@ class Pybind11Extension(_Extension): # type: ignore[misc] ...@@ -200,7 +200,7 @@ class Pybind11Extension(_Extension): # type: ignore[misc]
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2]) current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
desired_macos = (10, 9) if level < 17 else (10, 14) desired_macos = (10, 9) if level < 17 else (10, 14)
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos)) macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
macosx_min = "-mmacosx-version-min={}".format(macos_string) macosx_min = f"-mmacosx-version-min={macos_string}"
cflags += [macosx_min] cflags += [macosx_min]
ldflags += [macosx_min] ldflags += [macosx_min]
...@@ -322,9 +322,9 @@ def intree_extensions( ...@@ -322,9 +322,9 @@ def intree_extensions(
if not exts: if not exts:
msg = ( msg = (
"path {path} is not a child of any of the directories listed " f"path {path} is not a child of any of the directories listed "
"in 'package_dir' ({package_dir})" f"in 'package_dir' ({package_dir})"
).format(path=path, package_dir=package_dir) )
raise ValueError(msg) raise ValueError(msg)
return exts return exts
...@@ -419,7 +419,7 @@ class ParallelCompile: ...@@ -419,7 +419,7 @@ class ParallelCompile:
self.default = default self.default = default
self.max = max self.max = max
self.needs_recompile = needs_recompile self.needs_recompile = needs_recompile
self._old = [] # type: List[CCompilerMethod] self._old: List[CCompilerMethod] = []
def function(self) -> CCompilerMethod: def function(self) -> CCompilerMethod:
""" """
......
...@@ -14,7 +14,6 @@ classifiers = ...@@ -14,7 +14,6 @@ classifiers =
Topic :: Utilities Topic :: Utilities
Programming Language :: C++ Programming Language :: C++
Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
...@@ -38,7 +37,7 @@ project_urls = ...@@ -38,7 +37,7 @@ project_urls =
Chat = https://gitter.im/pybind/Lobby Chat = https://gitter.im/pybind/Lobby
[options] [options]
python_requires = >=3.5 python_requires = >=3.6
zip_safe = False zip_safe = False
...@@ -46,14 +45,5 @@ zip_safe = False ...@@ -46,14 +45,5 @@ zip_safe = False
max-line-length = 120 max-line-length = 120
show_source = True show_source = True
exclude = .git, __pycache__, build, dist, docs, tools, venv exclude = .git, __pycache__, build, dist, docs, tools, venv
ignore = extend-ignore = E203, E722, B950
# required for pretty matrix formatting: multiple spaces after `,` and `[` select = C,E,F,N,W,B,B9
E201, E241, W504,
# camelcase 'cPickle' imported as lowercase 'pickle'
N813
# Black conflict
W503, E203
[tool:pytest]
timeout = 300
#!/usr/bin/env python #!/usr/bin/env python3
# Setup script for PyPI; use CMakeFile.txt to build extension modules # Setup script for PyPI; use CMakeFile.txt to build extension modules
...@@ -41,12 +41,10 @@ def build_expected_version_hex(matches: Dict[str, str]) -> str: ...@@ -41,12 +41,10 @@ def build_expected_version_hex(matches: Dict[str, str]) -> str:
serial = int(level_serial[len(level) :]) serial = int(level_serial[len(level) :])
break break
if serial is None: if serial is None:
msg = 'Invalid PYBIND11_VERSION_PATCH: "{}"'.format(patch_level_serial) msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
raise RuntimeError(msg) raise RuntimeError(msg)
version_hex_str = "{:02x}{:02x}{:02x}{}{:x}".format( version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
major, minor, patch, level[:1], serial return f"0x{version_hex_str.upper()}"
)
return "0x{}".format(version_hex_str.upper())
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers # PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
...@@ -66,7 +64,7 @@ to_src = ( ...@@ -66,7 +64,7 @@ to_src = (
# Read the listed version # Read the listed version
loc = {} # type: Dict[str, str] loc: Dict[str, str] = {}
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec") code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
exec(code, loc) exec(code, loc)
version = loc["__version__"] version = loc["__version__"]
...@@ -75,17 +73,13 @@ version = loc["__version__"] ...@@ -75,17 +73,13 @@ version = loc["__version__"]
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8"))) matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches) cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
if version != cpp_version: if version != cpp_version:
msg = "Python version {} does not match C++ version {}!".format( msg = f"Python version {version} does not match C++ version {cpp_version}!"
version, cpp_version
)
raise RuntimeError(msg) raise RuntimeError(msg)
version_hex = matches.get("HEX", "MISSING") version_hex = matches.get("HEX", "MISSING")
exp_version_hex = build_expected_version_hex(matches) exp_version_hex = build_expected_version_hex(matches)
if version_hex != exp_version_hex: if version_hex != exp_version_hex:
msg = "PYBIND11_VERSION_HEX {} does not match expected value {}!".format( msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
version_hex, exp_version_hex
)
raise RuntimeError(msg) raise RuntimeError(msg)
......
...@@ -145,9 +145,9 @@ def test_build_sdist(monkeypatch, tmpdir): ...@@ -145,9 +145,9 @@ def test_build_sdist(monkeypatch, tmpdir):
contents = f.read().decode("utf8") contents = f.read().decode("utf8")
assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in contents assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in contents
files = {"pybind11/{}".format(n) for n in all_files} files = {f"pybind11/{n}" for n in all_files}
files |= sdist_files files |= sdist_files
files |= {"pybind11{}".format(n) for n in local_sdist_files} files |= {f"pybind11{n}" for n in local_sdist_files}
files.add("pybind11.egg-info/entry_points.txt") files.add("pybind11.egg-info/entry_points.txt")
files.add("pybind11.egg-info/requires.txt") files.add("pybind11.egg-info/requires.txt")
assert simpler == files assert simpler == files
...@@ -200,9 +200,9 @@ def test_build_global_dist(monkeypatch, tmpdir): ...@@ -200,9 +200,9 @@ def test_build_global_dist(monkeypatch, tmpdir):
) as f: ) as f:
pyproject_toml = f.read() pyproject_toml = f.read()
files = {"pybind11/{}".format(n) for n in all_files} files = {f"pybind11/{n}" for n in all_files}
files |= sdist_files files |= sdist_files
files |= {"pybind11_global{}".format(n) for n in local_sdist_files} files |= {f"pybind11_global{n}" for n in local_sdist_files}
assert simpler == files assert simpler == files
with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f: with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
...@@ -227,7 +227,7 @@ def tests_build_wheel(monkeypatch, tmpdir): ...@@ -227,7 +227,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
(wheel,) = tmpdir.visit("*.whl") (wheel,) = tmpdir.visit("*.whl")
files = {"pybind11/{}".format(n) for n in all_files} files = {f"pybind11/{n}" for n in all_files}
files |= { files |= {
"dist-info/LICENSE", "dist-info/LICENSE",
"dist-info/METADATA", "dist-info/METADATA",
...@@ -241,9 +241,7 @@ def tests_build_wheel(monkeypatch, tmpdir): ...@@ -241,9 +241,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
names = z.namelist() names = z.namelist()
trimmed = {n for n in names if "dist-info" not in n} trimmed = {n for n in names if "dist-info" not in n}
trimmed |= { trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
"dist-info/{}".format(n.split("/", 1)[-1]) for n in names if "dist-info" in n
}
assert files == trimmed assert files == trimmed
...@@ -257,8 +255,8 @@ def tests_build_global_wheel(monkeypatch, tmpdir): ...@@ -257,8 +255,8 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
(wheel,) = tmpdir.visit("*.whl") (wheel,) = tmpdir.visit("*.whl")
files = {"data/data/{}".format(n) for n in src_files} files = {f"data/data/{n}" for n in src_files}
files |= {"data/headers/{}".format(n[8:]) for n in headers} files |= {f"data/headers/{n[8:]}" for n in headers}
files |= { files |= {
"dist-info/LICENSE", "dist-info/LICENSE",
"dist-info/METADATA", "dist-info/METADATA",
......
...@@ -18,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std): ...@@ -18,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
(tmpdir / "setup.py").write_text( (tmpdir / "setup.py").write_text(
dedent( dedent(
"""\ f"""\
import sys import sys
sys.path.append({MAIN_DIR!r}) sys.path.append({MAIN_DIR!r})
...@@ -51,7 +51,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std): ...@@ -51,7 +51,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
ext_modules=ext_modules, ext_modules=ext_modules,
) )
""" """
).format(MAIN_DIR=MAIN_DIR, std=std, parallel=parallel), ),
encoding="ascii", encoding="ascii",
) )
......
[pytest] [pytest]
minversion = 3.1 minversion = 3.10
norecursedirs = test_* extra_* norecursedirs = test_* extra_*
xfail_strict = True xfail_strict = True
addopts = addopts =
# show summary of skipped tests # show summary of tests
-rs -ra
# capture only Python print and C++ py::print, but not C output (low-level Python errors) # capture only Python print and C++ py::print, but not C output (low-level Python errors)
--capture=sys --capture=sys
# Show local info when a failure occurs
--showlocals
log_cli_level = info
filterwarnings = filterwarnings =
# make warnings into errors but ignore certain third-party extension issues # make warnings into errors but ignore certain third-party extension issues
error error
......
numpy==1.16.6; python_version<"3.6" and sys_platform!="win32" and platform_python_implementation!="PyPy" numpy==1.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
numpy==1.19.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.6"
numpy==1.20.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6" numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.11" numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"
py @ git+https://github.com/pytest-dev/py; python_version>="3.11" numpy==1.22.2; platform_python_implementation!="PyPy" and python_version>="3.10" and python_version<"3.11"
pytest==4.6.9; python_version<"3.5" pytest==7.0.0
pytest==6.1.2; python_version=="3.5"
pytest==6.2.4; python_version>="3.6"
pytest-timeout pytest-timeout
scipy==1.2.3; platform_python_implementation!="PyPy" and python_version<"3.6" scipy==1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
scipy==1.5.4; platform_python_implementation!="PyPy" and python_version>="3.6" and python_version<"3.10" scipy==1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10"
...@@ -50,7 +50,7 @@ def test_single_char_arguments(): ...@@ -50,7 +50,7 @@ def test_single_char_arguments():
"""Tests failures for passing invalid inputs to char-accepting functions""" """Tests failures for passing invalid inputs to char-accepting functions"""
def toobig_message(r): def toobig_message(r):
return "Character code point not in range({:#x})".format(r) return f"Character code point not in range({r:#x})"
toolong_message = "Expected a character, but multi-character string found" toolong_message = "Expected a character, but multi-character string found"
......
...@@ -17,7 +17,7 @@ def test_callbacks(): ...@@ -17,7 +17,7 @@ def test_callbacks():
return "func2", a, b, c, d return "func2", a, b, c, d
def func3(a): def func3(a):
return "func3({})".format(a) return f"func3({a})"
assert m.test_callback1(func1) == "func1" assert m.test_callback1(func1) == "func1"
assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5) assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
...@@ -188,14 +188,8 @@ def test_callback_num_times(): ...@@ -188,14 +188,8 @@ def test_callback_num_times():
if not rep: if not rep:
print() print()
print( print(
"callback_num_times: {:d} million / {:.3f} seconds = {:.3f} million / second".format( f"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
num_millions, td, rate
)
) )
if len(rates) > 1: if len(rates) > 1:
print("Min Mean Max") print("Min Mean Max")
print( print(f"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
"{:6.3f} {:6.3f} {:6.3f}".format(
min(rates), sum(rates) / len(rates), max(rates)
)
)
...@@ -100,7 +100,7 @@ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif( ...@@ -100,7 +100,7 @@ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
) )
def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch): def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
if tz is not None: if tz is not None:
monkeypatch.setenv("TZ", "/usr/share/zoneinfo/{}".format(tz)) monkeypatch.setenv("TZ", f"/usr/share/zoneinfo/{tz}")
# Roundtrip the time # Roundtrip the time
datetime2 = m.test_chrono2(time1) datetime2 = m.test_chrono2(time1)
......
...@@ -5,4 +5,4 @@ import test_cmake_build ...@@ -5,4 +5,4 @@ import test_cmake_build
assert isinstance(__file__, str) # Test this is properly set assert isinstance(__file__, str) # Test this is properly set
assert test_cmake_build.add(1, 2) == 3 assert test_cmake_build.add(1, 2) == 3
print("{} imports, runs, and adds: 1 + 2 = 3".format(sys.argv[1])) print(f"{sys.argv[1]} imports, runs, and adds: 1 + 2 = 3")
...@@ -221,9 +221,7 @@ def test_nonunit_stride_to_python(): ...@@ -221,9 +221,7 @@ def test_nonunit_stride_to_python():
assert np.all(m.diagonal(ref) == ref.diagonal()) assert np.all(m.diagonal(ref) == ref.diagonal())
assert np.all(m.diagonal_1(ref) == ref.diagonal(1)) assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
for i in range(-5, 7): for i in range(-5, 7):
assert np.all( assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
m.diagonal_n(ref, i) == ref.diagonal(i)
), "m.diagonal_n({})".format(i)
assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4]) assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4])
assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:]) assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:])
...@@ -236,7 +234,7 @@ def test_eigen_ref_to_python(): ...@@ -236,7 +234,7 @@ def test_eigen_ref_to_python():
mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]])) mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
assert np.all( assert np.all(
mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]]) mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
), "cholesky{}".format(i) ), f"cholesky{i}"
def assign_both(a1, a2, r, c, v): def assign_both(a1, a2, r, c, v):
......
...@@ -88,7 +88,7 @@ def test_python_call_in_catch(): ...@@ -88,7 +88,7 @@ def test_python_call_in_catch():
def ignore_pytest_unraisable_warning(f): def ignore_pytest_unraisable_warning(f):
unraisable = "PytestUnraisableExceptionWarning" unraisable = "PytestUnraisableExceptionWarning"
if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6 if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
dec = pytest.mark.filterwarnings("ignore::pytest.{}".format(unraisable)) dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
return dec(f) return dec(f)
else: else:
return f return f
......
...@@ -18,9 +18,7 @@ def test_dtypes(): ...@@ -18,9 +18,7 @@ def test_dtypes():
assert check.numpy == check.pybind11, check assert check.numpy == check.pybind11, check
if check.numpy.num != check.pybind11.num: if check.numpy.num != check.pybind11.num:
print( print(
"NOTE: typenum mismatch for {}: {} != {}".format( f"NOTE: typenum mismatch for {check}: {check.numpy.num} != {check.pybind11.num}"
check, check.numpy.num, check.pybind11.num
)
) )
...@@ -116,9 +114,7 @@ def test_at_fail(arr, dim): ...@@ -116,9 +114,7 @@ def test_at_fail(arr, dim):
for func in m.at_t, m.mutate_at_t: for func in m.at_t, m.mutate_at_t:
with pytest.raises(IndexError) as excinfo: with pytest.raises(IndexError) as excinfo:
func(arr, *([0] * dim)) func(arr, *([0] * dim))
assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format( assert str(excinfo.value) == f"index dimension mismatch: {dim} (ndim = 2)"
dim
)
def test_at(arr): def test_at(arr):
...@@ -192,8 +188,6 @@ def test_make_empty_shaped_array(): ...@@ -192,8 +188,6 @@ def test_make_empty_shaped_array():
def test_wrap(): def test_wrap():
def assert_references(a, b, base=None): def assert_references(a, b, base=None):
from distutils.version import LooseVersion
if base is None: if base is None:
base = a base = a
assert a is not b assert a is not b
...@@ -204,7 +198,8 @@ def test_wrap(): ...@@ -204,7 +198,8 @@ def test_wrap():
assert a.flags.f_contiguous == b.flags.f_contiguous assert a.flags.f_contiguous == b.flags.f_contiguous
assert a.flags.writeable == b.flags.writeable assert a.flags.writeable == b.flags.writeable
assert a.flags.aligned == b.flags.aligned assert a.flags.aligned == b.flags.aligned
if LooseVersion(np.__version__) >= LooseVersion("1.14.0"): # 1.13 supported Python 3.6
if tuple(int(x) for x in np.__version__.split(".")[:2]) >= (1, 14):
assert a.flags.writebackifcopy == b.flags.writebackifcopy assert a.flags.writebackifcopy == b.flags.writebackifcopy
else: else:
assert a.flags.updateifcopy == b.flags.updateifcopy assert a.flags.updateifcopy == b.flags.updateifcopy
......
...@@ -14,7 +14,7 @@ def simple_dtype(): ...@@ -14,7 +14,7 @@ def simple_dtype():
return np.dtype( return np.dtype(
{ {
"names": ["bool_", "uint_", "float_", "ldbl_"], "names": ["bool_", "uint_", "float_", "ldbl_"],
"formats": ["?", "u4", "f4", "f{}".format(ld.itemsize)], "formats": ["?", "u4", "f4", f"f{ld.itemsize}"],
"offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)], "offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)],
} }
) )
...@@ -125,7 +125,7 @@ def test_dtype(simple_dtype): ...@@ -125,7 +125,7 @@ def test_dtype(simple_dtype):
assert [x.replace(" ", "") for x in m.print_dtypes()] == [ assert [x.replace(" ", "") for x in m.print_dtypes()] == [
simple_dtype_fmt(), simple_dtype_fmt(),
packed_dtype_fmt(), packed_dtype_fmt(),
"[('a',{}),('b',{})]".format(simple_dtype_fmt(), packed_dtype_fmt()), f"[('a',{simple_dtype_fmt()}),('b',{packed_dtype_fmt()})]",
partial_dtype_fmt(), partial_dtype_fmt(),
partial_nested_fmt(), partial_nested_fmt(),
"[('a','S3'),('b','S3')]", "[('a','S3'),('b','S3')]",
......
...@@ -12,7 +12,7 @@ def test_string_list(): ...@@ -12,7 +12,7 @@ def test_string_list():
assert lst.back() == "Element 2" assert lst.back() == "Element 2"
for i, k in enumerate(lst, start=1): for i, k in enumerate(lst, start=1):
assert k == "Element {}".format(i) assert k == f"Element {i}"
lst.pop_back() lst.pop_back()
assert m.print_opaque_list(lst) == "Opaque list: [Element 1]" assert m.print_opaque_list(lst) == "Opaque list: [Element 1]"
......
...@@ -305,8 +305,8 @@ def test_non_converting_constructors(): ...@@ -305,8 +305,8 @@ def test_non_converting_constructors():
for move in [True, False]: for move in [True, False]:
with pytest.raises(TypeError) as excinfo: with pytest.raises(TypeError) as excinfo:
m.nonconverting_constructor(t, v, move) m.nonconverting_constructor(t, v, move)
expected_error = "Object of type '{}' is not an instance of '{}'".format( expected_error = (
type(v).__name__, t f"Object of type '{type(v).__name__}' is not an instance of '{t}'"
) )
assert str(excinfo.value) == expected_error assert str(excinfo.value) == expected_error
......
import pytest import pytest
from pytest import approx
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import sequences_and_iterators as m from pybind11_tests import sequences_and_iterators as m
def isclose(a, b, rel_tol=1e-05, abs_tol=0.0):
"""Like math.isclose() from Python 3.5"""
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
def allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0):
return all(
isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list)
)
def test_slice_constructors(): def test_slice_constructors():
assert m.make_forward_slice_size_t() == slice(0, -1, 1) assert m.make_forward_slice_size_t() == slice(0, -1, 1)
assert m.make_reversed_slice_object() == slice(None, None, -1) assert m.make_reversed_slice_object() == slice(None, None, -1)
...@@ -117,7 +107,8 @@ def test_sequence(): ...@@ -117,7 +107,8 @@ def test_sequence():
assert 12.34 not in s assert 12.34 not in s
s[0], s[3] = 12.34, 56.78 s[0], s[3] = 12.34, 56.78
assert 12.34 in s assert 12.34 in s
assert isclose(s[0], 12.34) and isclose(s[3], 56.78) assert s[0] == approx(12.34, rel=1e-05)
assert s[3] == approx(56.78, rel=1e-05)
rev = reversed(s) rev = reversed(s)
assert cstats.values() == ["of size", "5"] assert cstats.values() == ["of size", "5"]
...@@ -132,14 +123,14 @@ def test_sequence(): ...@@ -132,14 +123,14 @@ def test_sequence():
assert cstats.values() == ["of size", "0"] assert cstats.values() == ["of size", "0"]
expected = [0, 56.78, 0, 0, 12.34] expected = [0, 56.78, 0, 0, 12.34]
assert allclose(rev, expected) assert rev == approx(expected, rel=1e-05)
assert allclose(rev2, expected) assert rev2 == approx(expected, rel=1e-05)
assert rev == rev2 assert rev == rev2
rev[0::2] = m.Sequence([2.0, 2.0, 2.0]) rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
assert cstats.values() == ["of size", "3", "from std::vector"] assert cstats.values() == ["of size", "3", "from std::vector"]
assert allclose(rev, [2, 56.78, 2, 0, 2]) assert rev == approx([2, 56.78, 2, 0, 2], rel=1e-05)
assert cstats.alive() == 4 assert cstats.alive() == 4
del it del it
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment