chore: move to Ruff and add rules (#4483)

This commit is contained in:
Henry Schreiner 2023-02-22 06:18:55 -08:00 committed by GitHub
parent a19daeac16
commit 438034c5b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 266 additions and 279 deletions

View File

@ -39,19 +39,6 @@ repos:
- id: requirements-txt-fixer
- id: trailing-whitespace
# Upgrade old Python syntax
- repo: https://github.com/asottile/pyupgrade
rev: "v3.3.1"
hooks:
- id: pyupgrade
args: [--py36-plus]
# Nicely sort includes
- repo: https://github.com/PyCQA/isort
rev: "5.12.0"
hooks:
- id: isort
# Black, the code formatter, natively supports pre-commit
- repo: https://github.com/psf/black
rev: "23.1.0" # Keep in sync with blacken-docs
@ -72,47 +59,28 @@ repos:
hooks:
- id: remove-tabs
# Avoid directional quotes
- repo: https://github.com/sirosen/texthooks
rev: "0.5.0"
hooks:
- id: fix-ligatures
- id: fix-smartquotes
# Autoremoves unused imports
- repo: https://github.com/hadialqattan/pycln
rev: "v2.1.3"
# Ruff, the Python auto-correcting linter written in Rust
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.251
hooks:
- id: pycln
stages: [manual]
- id: ruff
args: ["--fix", "--show-fixes"]
# Checking for common mistakes
- repo: https://github.com/pre-commit/pygrep-hooks
rev: "v1.10.0"
hooks:
- id: python-check-blanket-noqa
- id: python-check-blanket-type-ignore
- id: python-no-log-warn
- id: python-use-type-annotations
- id: rst-backticks
- id: rst-directive-colons
- id: rst-inline-touching-normal
# Automatically remove noqa that are not used
- repo: https://github.com/asottile/yesqa
rev: "v1.4.0"
hooks:
- id: yesqa
additional_dependencies: &flake8_dependencies
- flake8-bugbear
- pep8-naming
# Flake8 also supports pre-commit natively (same author)
- repo: https://github.com/PyCQA/flake8
rev: "6.0.0"
hooks:
- id: flake8
exclude: ^(docs/.*|tools/.*)$
additional_dependencies: *flake8_dependencies
# PyLint has native support - not always usable, but works for us
- repo: https://github.com/PyCQA/pylint

View File

@ -353,7 +353,7 @@ def prepare(app):
f.write(contents)
def clean_up(app, exception):
def clean_up(app, exception): # noqa: ARG001
(DIR / "readme.rst").unlink()

View File

@ -1,6 +1,6 @@
import sys
if sys.version_info < (3, 6):
if sys.version_info < (3, 6): # noqa: UP036
msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
raise ImportError(msg)

View File

@ -3,7 +3,7 @@ import os
DIR = os.path.abspath(os.path.dirname(__file__))
def get_include(user: bool = False) -> str: # pylint: disable=unused-argument
def get_include(user: bool = False) -> str: # noqa: ARG001
"""
Return the path to the pybind11 include directory. The historical "user"
argument is unused, and may be removed.

View File

@ -341,7 +341,7 @@ def naive_recompile(obj: str, src: str) -> bool:
return os.stat(obj).st_mtime < os.stat(src).st_mtime
def no_recompile(obg: str, src: str) -> bool: # pylint: disable=unused-argument
def no_recompile(obg: str, src: str) -> bool: # noqa: ARG001
"""
This is the safest but slowest choice (and is the default) - will always
recompile sources.

View File

@ -15,12 +15,6 @@ ignore = [
"noxfile.py",
]
[tool.isort]
# Needs the compiled .so modules and env.py from tests
known_first_party = "env,pybind11_cross_module_tests,pybind11_tests,"
# For black compatibility
profile = "black"
[tool.mypy]
files = ["pybind11"]
python_version = "3.6"
@ -58,4 +52,44 @@ messages_control.disable = [
"invalid-name",
"protected-access",
"missing-module-docstring",
"unused-argument", # covered by Ruff ARG
]
[tool.ruff]
select = [
"E", "F", "W", # flake8
"B", "B904", # flake8-bugbear
"I", # isort
"N", # pep8-naming
"ARG", # flake8-unused-arguments
"C4", # flake8-comprehensions
"EM", # flake8-errmsg
"ICN", # flake8-import-conventions
"ISC", # flake8-implicit-str-concat
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PT", # flake8-pytest-style
"RET", # flake8-return
"RUF100", # Ruff-specific
"SIM", # flake8-simplify
"UP", # pyupgrade
"YTT", # flake8-2020
]
ignore = [
"PLR", # Design related pylint
"E501", # Line too long (Black is enough)
"PT011", # Too broad with raises in pytest
"PT004", # Fixture that doesn't return needs underscore (no, it is fine)
"SIM118",# iter(x) is not always the same as iter(x.keys())
]
target-version = "py37"
typing-modules = ["scikit_build_core._compat.typing"]
src = ["src"]
unfixable = ["T20"]
exclude = []
line-length = 120
isort.known-first-party = ["env", "pybind11_cross_module_tests", "pybind11_tests"]
[tool.ruff.per-file-ignores]
"tests/**" = ["EM", "N"]

View File

@ -40,11 +40,3 @@ project_urls =
[options]
python_requires = >=3.6
zip_safe = False
[flake8]
max-line-length = 120
show_source = True
exclude = .git, __pycache__, build, dist, docs, tools, venv
extend-ignore = E203, E722
extend-select = B902, B904

View File

@ -83,9 +83,8 @@ class Output:
b = _strip_and_dedent(other).splitlines()
if a == b:
return True
else:
self.explanation = _make_explanation(a, b)
return False
self.explanation = _make_explanation(a, b)
return False
class Unordered(Output):
@ -96,9 +95,8 @@ class Unordered(Output):
b = _split_and_sort(other)
if a == b:
return True
else:
self.explanation = _make_explanation(a, b)
return False
self.explanation = _make_explanation(a, b)
return False
class Capture:
@ -119,9 +117,8 @@ class Capture:
b = other
if a == b:
return True
else:
self.explanation = a.explanation
return False
self.explanation = a.explanation
return False
def __str__(self):
return self.out
@ -138,7 +135,7 @@ class Capture:
return Output(self.err)
@pytest.fixture
@pytest.fixture()
def capture(capsys):
"""Extended `capsys` with context manager and custom equality operators"""
return Capture(capsys)
@ -159,25 +156,22 @@ class SanitizedString:
b = _strip_and_dedent(other)
if a == b:
return True
else:
self.explanation = _make_explanation(a.splitlines(), b.splitlines())
return False
self.explanation = _make_explanation(a.splitlines(), b.splitlines())
return False
def _sanitize_general(s):
s = s.strip()
s = s.replace("pybind11_tests.", "m.")
s = _long_marker.sub(r"\1", s)
return s
return _long_marker.sub(r"\1", s)
def _sanitize_docstring(thing):
s = thing.__doc__
s = _sanitize_general(s)
return s
return _sanitize_general(s)
@pytest.fixture
@pytest.fixture()
def doc():
"""Sanitize docstrings and add custom failure explanation"""
return SanitizedString(_sanitize_docstring)
@ -186,30 +180,20 @@ def doc():
def _sanitize_message(thing):
s = str(thing)
s = _sanitize_general(s)
s = _hexadecimal.sub("0", s)
return s
return _hexadecimal.sub("0", s)
@pytest.fixture
@pytest.fixture()
def msg():
"""Sanitize messages and add custom failure explanation"""
return SanitizedString(_sanitize_message)
# noinspection PyUnusedLocal
def pytest_assertrepr_compare(op, left, right):
def pytest_assertrepr_compare(op, left, right): # noqa: ARG001
"""Hook to insert custom failure explanation"""
if hasattr(left, "explanation"):
return left.explanation
@contextlib.contextmanager
def suppress(exception):
"""Suppress the desired exception"""
try:
yield
except exception:
pass
return None
def gc_collect():
@ -220,7 +204,7 @@ def gc_collect():
def pytest_configure():
pytest.suppress = suppress
pytest.suppress = contextlib.suppress
pytest.gc_collect = gc_collect

View File

@ -24,5 +24,4 @@ def deprecated_call():
pytest_major_minor = (int(pieces[0]), int(pieces[1]))
if pytest_major_minor < (3, 9):
return pytest.warns((DeprecationWarning, PendingDeprecationWarning))
else:
return pytest.deprecated_call()
return pytest.deprecated_call()

View File

@ -4,7 +4,7 @@ asyncio = pytest.importorskip("asyncio")
m = pytest.importorskip("pybind11_tests.async_module")
@pytest.fixture
@pytest.fixture()
def event_loop():
loop = asyncio.new_event_loop()
yield loop
@ -16,7 +16,7 @@ async def get_await_result(x):
def test_await(event_loop):
assert 5 == event_loop.run_until_complete(get_await_result(m.SupportsAsync()))
assert event_loop.run_until_complete(get_await_result(m.SupportsAsync())) == 5
def test_await_missing(event_loop):

View File

@ -54,7 +54,8 @@ def test_to_python():
mat2 = np.array(mat, copy=False)
assert mat2.shape == (5, 4)
assert abs(mat2).sum() == 11
assert mat2[2, 3] == 4 and mat2[3, 2] == 7
assert mat2[2, 3] == 4
assert mat2[3, 2] == 7
mat2[2, 3] = 5
assert mat2[2, 3] == 5

View File

@ -126,8 +126,8 @@ def test_bytes_to_string():
assert m.strlen(b"hi") == 2
assert m.string_length(b"world") == 5
assert m.string_length("a\x00b".encode()) == 3
assert m.strlen("a\x00b".encode()) == 1 # C-string limitation
assert m.string_length(b"a\x00b") == 3
assert m.strlen(b"a\x00b") == 1 # C-string limitation
# passing in a utf8 encoded string should work
assert m.string_length("💩".encode()) == 4
@ -421,13 +421,15 @@ def test_reference_wrapper():
a2 = m.refwrap_list(copy=True)
assert [x.value for x in a1] == [2, 3]
assert [x.value for x in a2] == [2, 3]
assert not a1[0] is a2[0] and not a1[1] is a2[1]
assert a1[0] is not a2[0]
assert a1[1] is not a2[1]
b1 = m.refwrap_list(copy=False)
b2 = m.refwrap_list(copy=False)
assert [x.value for x in b1] == [1, 2]
assert [x.value for x in b2] == [1, 2]
assert b1[0] is b2[0] and b1[1] is b2[1]
assert b1[0] is b2[0]
assert b1[1] is b2[1]
assert m.refwrap_iiw(IncType(5)) == 5
assert m.refwrap_call_iiw(IncType(10), m.refwrap_iiw) == [10, 10, 10, 10]

View File

@ -6,10 +6,7 @@ from pybind11_tests import class_ as m
def test_obj_class_name():
if env.PYPY:
expected_name = "UserType"
else:
expected_name = "pybind11_tests.UserType"
expected_name = "UserType" if env.PYPY else "pybind11_tests.UserType"
assert m.obj_class_name(UserType(1)) == expected_name
assert m.obj_class_name(UserType) == expected_name
@ -32,7 +29,7 @@ def test_instance(msg):
assert cstats.alive() == 0
def test_instance_new(msg):
def test_instance_new():
instance = m.NoConstructorNew() # .__new__(m.NoConstructor.__class__)
cstats = ConstructorStats.get(m.NoConstructorNew)
assert cstats.alive() == 1
@ -221,7 +218,7 @@ def test_automatic_upcasting():
def test_isinstance():
objects = [tuple(), dict(), m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
objects = [(), {}, m.Pet("Polly", "parrot")] + [m.Dog("Molly")] * 4
expected = (True, True, True, True, True, False, False)
assert m.check_instances(objects) == expected
@ -427,7 +424,7 @@ def test_exception_rvalue_abort():
# https://github.com/pybind/pybind11/issues/1568
def test_multiple_instances_with_same_pointer(capture):
def test_multiple_instances_with_same_pointer():
n = 100
instances = [m.SamePointer() for _ in range(n)]
for i in range(n):

View File

@ -3,9 +3,9 @@ import pytest
from pybind11_tests import const_name as m
@pytest.mark.parametrize("func", (m.const_name_tests, m.underscore_tests))
@pytest.mark.parametrize("func", [m.const_name_tests, m.underscore_tests])
@pytest.mark.parametrize(
"selector, expected",
("selector", "expected"),
enumerate(
(
"",

View File

@ -100,7 +100,8 @@ def test_custom_caster_destruction():
cstats = m.destruction_tester_cstats()
# This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
z = m.custom_caster_no_destroy()
assert cstats.alive() == 1 and cstats.default_constructions == 1
assert cstats.alive() == 1
assert cstats.default_constructions == 1
assert z
# take_ownership applied: this constructs a new object, casts it, then destroys it:

View File

@ -7,7 +7,7 @@ import env # noqa: F401
from pybind11_tests import custom_type_setup as m
@pytest.fixture
@pytest.fixture()
def gc_tester():
"""Tests that an object is garbage collected.

View File

@ -263,79 +263,96 @@ def test_eigen_return_references():
primary = np.ones((10, 10))
a = m.ReturnTester()
a_get1 = a.get()
assert not a_get1.flags.owndata and a_get1.flags.writeable
assert not a_get1.flags.owndata
assert a_get1.flags.writeable
assign_both(a_get1, primary, 3, 3, 5)
a_get2 = a.get_ptr()
assert not a_get2.flags.owndata and a_get2.flags.writeable
assert not a_get2.flags.owndata
assert a_get2.flags.writeable
assign_both(a_get1, primary, 2, 3, 6)
a_view1 = a.view()
assert not a_view1.flags.owndata and not a_view1.flags.writeable
assert not a_view1.flags.owndata
assert not a_view1.flags.writeable
with pytest.raises(ValueError):
a_view1[2, 3] = 4
a_view2 = a.view_ptr()
assert not a_view2.flags.owndata and not a_view2.flags.writeable
assert not a_view2.flags.owndata
assert not a_view2.flags.writeable
with pytest.raises(ValueError):
a_view2[2, 3] = 4
a_copy1 = a.copy_get()
assert a_copy1.flags.owndata and a_copy1.flags.writeable
assert a_copy1.flags.owndata
assert a_copy1.flags.writeable
np.testing.assert_array_equal(a_copy1, primary)
a_copy1[7, 7] = -44 # Shouldn't affect anything else
c1want = array_copy_but_one(primary, 7, 7, -44)
a_copy2 = a.copy_view()
assert a_copy2.flags.owndata and a_copy2.flags.writeable
assert a_copy2.flags.owndata
assert a_copy2.flags.writeable
np.testing.assert_array_equal(a_copy2, primary)
a_copy2[4, 4] = -22 # Shouldn't affect anything else
c2want = array_copy_but_one(primary, 4, 4, -22)
a_ref1 = a.ref()
assert not a_ref1.flags.owndata and a_ref1.flags.writeable
assert not a_ref1.flags.owndata
assert a_ref1.flags.writeable
assign_both(a_ref1, primary, 1, 1, 15)
a_ref2 = a.ref_const()
assert not a_ref2.flags.owndata and not a_ref2.flags.writeable
assert not a_ref2.flags.owndata
assert not a_ref2.flags.writeable
with pytest.raises(ValueError):
a_ref2[5, 5] = 33
a_ref3 = a.ref_safe()
assert not a_ref3.flags.owndata and a_ref3.flags.writeable
assert not a_ref3.flags.owndata
assert a_ref3.flags.writeable
assign_both(a_ref3, primary, 0, 7, 99)
a_ref4 = a.ref_const_safe()
assert not a_ref4.flags.owndata and not a_ref4.flags.writeable
assert not a_ref4.flags.owndata
assert not a_ref4.flags.writeable
with pytest.raises(ValueError):
a_ref4[7, 0] = 987654321
a_copy3 = a.copy_ref()
assert a_copy3.flags.owndata and a_copy3.flags.writeable
assert a_copy3.flags.owndata
assert a_copy3.flags.writeable
np.testing.assert_array_equal(a_copy3, primary)
a_copy3[8, 1] = 11
c3want = array_copy_but_one(primary, 8, 1, 11)
a_copy4 = a.copy_ref_const()
assert a_copy4.flags.owndata and a_copy4.flags.writeable
assert a_copy4.flags.owndata
assert a_copy4.flags.writeable
np.testing.assert_array_equal(a_copy4, primary)
a_copy4[8, 4] = 88
c4want = array_copy_but_one(primary, 8, 4, 88)
a_block1 = a.block(3, 3, 2, 2)
assert not a_block1.flags.owndata and a_block1.flags.writeable
assert not a_block1.flags.owndata
assert a_block1.flags.writeable
a_block1[0, 0] = 55
primary[3, 3] = 55
a_block2 = a.block_safe(2, 2, 3, 2)
assert not a_block2.flags.owndata and a_block2.flags.writeable
assert not a_block2.flags.owndata
assert a_block2.flags.writeable
a_block2[2, 1] = -123
primary[4, 3] = -123
a_block3 = a.block_const(6, 7, 4, 3)
assert not a_block3.flags.owndata and not a_block3.flags.writeable
assert not a_block3.flags.owndata
assert not a_block3.flags.writeable
with pytest.raises(ValueError):
a_block3[2, 2] = -44444
a_copy5 = a.copy_block(2, 2, 2, 3)
assert a_copy5.flags.owndata and a_copy5.flags.writeable
assert a_copy5.flags.owndata
assert a_copy5.flags.writeable
np.testing.assert_array_equal(a_copy5, primary[2:4, 2:5])
a_copy5[1, 1] = 777
c5want = array_copy_but_one(primary[2:4, 2:5], 1, 1, 777)
a_corn1 = a.corners()
assert not a_corn1.flags.owndata and a_corn1.flags.writeable
assert not a_corn1.flags.owndata
assert a_corn1.flags.writeable
a_corn1 *= 50
a_corn1[1, 1] = 999
primary[0, 0] = 50
@ -343,7 +360,8 @@ def test_eigen_return_references():
primary[9, 0] = 50
primary[9, 9] = 999
a_corn2 = a.corners_const()
assert not a_corn2.flags.owndata and not a_corn2.flags.writeable
assert not a_corn2.flags.owndata
assert not a_corn2.flags.writeable
with pytest.raises(ValueError):
a_corn2[1, 0] = 51
@ -503,10 +521,14 @@ def test_numpy_ref_mutators():
assert [zc[1, 2], zcro[1, 2], zr[1, 2], zrro[1, 2]] == [23] * 4
assert not zc.flags.owndata and zc.flags.writeable
assert not zr.flags.owndata and zr.flags.writeable
assert not zcro.flags.owndata and not zcro.flags.writeable
assert not zrro.flags.owndata and not zrro.flags.writeable
assert not zc.flags.owndata
assert zc.flags.writeable
assert not zr.flags.owndata
assert zr.flags.writeable
assert not zcro.flags.owndata
assert not zcro.flags.writeable
assert not zrro.flags.owndata
assert not zrro.flags.writeable
zc[1, 2] = 99
expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]])
@ -530,7 +552,8 @@ def test_numpy_ref_mutators():
# the const should drop away)
y1 = np.array(m.get_cm_const_ref())
assert y1.flags.owndata and y1.flags.writeable
assert y1.flags.owndata
assert y1.flags.writeable
# We should get copies of the eigen data, which was modified above:
assert y1[1, 2] == 99
y1[1, 2] += 12
@ -603,38 +626,38 @@ def test_nocopy_wrapper():
# All but the second should fail with m.get_elem_nocopy:
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(int_matrix_colmajor)
assert "get_elem_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.f_contiguous" in str(excinfo.value)
assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
assert ", flags.f_contiguous" in str(excinfo.value)
assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(int_matrix_rowmajor)
assert "get_elem_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.f_contiguous" in str(excinfo.value)
assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
assert ", flags.f_contiguous" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(dbl_matrix_rowmajor)
assert "get_elem_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.f_contiguous" in str(excinfo.value)
assert "get_elem_nocopy(): incompatible function arguments." in str(excinfo.value)
assert ", flags.f_contiguous" in str(excinfo.value)
# For the row-major test, we take a long matrix in row-major, so only the third is allowed:
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(int_matrix_colmajor)
assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.c_contiguous" in str(excinfo.value)
)
assert ", flags.c_contiguous" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(dbl_matrix_colmajor)
assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.c_contiguous" in str(excinfo.value)
)
assert ", flags.c_contiguous" in str(excinfo.value)
assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(dbl_matrix_rowmajor)
assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
excinfo.value
) and ", flags.c_contiguous" in str(excinfo.value)
)
assert ", flags.c_contiguous" in str(excinfo.value)
def test_eigen_ref_life_support():

View File

@ -11,14 +11,15 @@ try:
submodules += [avoid.c_style, avoid.f_style]
except ImportError as e:
# Ensure config, build, toolchain, etc. issues are not masked here:
raise RuntimeError(
msg = (
"import eigen_tensor_avoid_stl_array FAILED, while "
"import pybind11_tests.eigen_tensor succeeded. "
"Please ensure that "
"test_eigen_tensor.cpp & "
"eigen_tensor_avoid_stl_array.cpp "
"are built together (or both are not built if Eigen is not available)."
) from e
)
raise RuntimeError(msg) from e
tensor_ref = np.empty((3, 5, 2), dtype=np.int64)
@ -147,10 +148,7 @@ def test_bad_python_to_cpp_casts(m):
m.round_trip_tensor_noconvert(tensor_ref.astype(np.float64))
)
if m.needed_options == "F":
bad_options = "C"
else:
bad_options = "F"
bad_options = "C" if m.needed_options == "F" else "F"
# Shape, dtype and the order need to be correct for a TensorMap cast
with pytest.raises(
TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
@ -173,19 +171,19 @@ def test_bad_python_to_cpp_casts(m):
np.zeros((3, 5), dtype=np.float64, order=m.needed_options)
)
temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
with pytest.raises(
TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
):
temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
m.round_trip_view_tensor(
temp[:, ::-1, :],
)
temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
temp.setflags(write=False)
with pytest.raises(
TypeError, match=r"^round_trip_view_tensor\(\): incompatible function arguments"
):
temp = np.zeros((3, 5, 2), dtype=np.float64, order=m.needed_options)
temp.setflags(write=False)
m.round_trip_view_tensor(temp)
@ -282,9 +280,9 @@ def test_doc_string(m, doc):
order_flag = f"flags.{m.needed_options.lower()}_contiguous"
assert doc(m.round_trip_view_tensor) == (
f"round_trip_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}])"
+ f" -> numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}]"
f" -> numpy.ndarray[numpy.float64[?, ?, ?], flags.writeable, {order_flag}]"
)
assert doc(m.round_trip_const_view_tensor) == (
f"round_trip_const_view_tensor(arg0: numpy.ndarray[numpy.float64[?, ?, ?], {order_flag}])"
+ " -> numpy.ndarray[numpy.float64[?, ?, ?]]"
" -> numpy.ndarray[numpy.float64[?, ?, ?]]"
)

View File

@ -1,3 +1,5 @@
# ruff: noqa: SIM201 SIM300 SIM202
import pytest
from pybind11_tests import enums as m

View File

@ -94,8 +94,7 @@ def ignore_pytest_unraisable_warning(f):
if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
return dec(f)
else:
return f
return f
# TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
@ -183,7 +182,7 @@ def test_custom(msg):
m.throws5_1()
assert msg(excinfo.value) == "MyException5 subclass"
with pytest.raises(m.MyException5) as excinfo:
with pytest.raises(m.MyException5) as excinfo: # noqa: PT012
try:
m.throws5()
except m.MyException5_1 as err:
@ -212,7 +211,7 @@ def test_nested_throws(capture):
m.try_catch(m.MyException5, throw_myex)
assert str(excinfo.value) == "nested error"
def pycatch(exctype, f, *args):
def pycatch(exctype, f, *args): # noqa: ARG001
try:
f(*args)
except m.MyException as e:
@ -303,12 +302,12 @@ class FlakyException(Exception):
@pytest.mark.parametrize(
"exc_type, exc_value, expected_what",
(
("exc_type", "exc_value", "expected_what"),
[
(ValueError, "plain_str", "ValueError: plain_str"),
(ValueError, ("tuple_elem",), "ValueError: tuple_elem"),
(FlakyException, ("happy",), "FlakyException: FlakyException.__str__"),
),
],
)
def test_error_already_set_what_with_happy_exceptions(
exc_type, exc_value, expected_what
@ -342,10 +341,7 @@ def test_flaky_exception_failure_point_str():
)
assert not py_err_set_after_what
lines = what.splitlines()
if env.PYPY and len(lines) == 3:
n = 3 # Traceback is missing.
else:
n = 5
n = 3 if env.PYPY and len(lines) == 3 else 5
assert (
lines[:n]
== [

View File

@ -96,7 +96,7 @@ def test_init_factory_signature(msg):
3. __init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.pointer_tag) -> None
4. __init__(self: m.factory_constructors.TestFactory1, arg0: handle, arg1: int, arg2: handle) -> None
""" # noqa: E501 line too long
"""
)

View File

@ -148,10 +148,7 @@ ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_dead
def _run_in_process(target, *args, **kwargs):
if len(args) == 0:
test_fn = target
else:
test_fn = args[0]
test_fn = target if len(args) == 0 else args[0]
# Do not need to wait much, 10s should be more than enough.
timeout = 0.1 if test_fn is _intentional_deadlock else 10
process = multiprocessing.Process(target=target, args=args, kwargs=kwargs)
@ -178,7 +175,8 @@ def _run_in_process(target, *args, **kwargs):
elif test_fn is _intentional_deadlock:
assert process.exitcode is None
return 0
elif process.exitcode is None:
if process.exitcode is None:
assert t_delta > 0.9 * timeout
msg = "DEADLOCK, most likely, exactly what this test is meant to detect."
if env.PYPY and env.WIN:

View File

@ -224,9 +224,8 @@ def test_redirect(capfd):
assert stream.getvalue() == ""
stream = StringIO()
with redirect_stdout(stream):
with m.ostream_redirect():
m.raw_output(msg)
with redirect_stdout(stream), m.ostream_redirect():
m.raw_output(msg)
stdout, stderr = capfd.readouterr()
assert stdout == ""
assert stream.getvalue() == msg
@ -244,10 +243,9 @@ def test_redirect_err(capfd):
msg2 = "StdErr"
stream = StringIO()
with redirect_stderr(stream):
with m.ostream_redirect(stdout=False):
m.raw_output(msg)
m.raw_err(msg2)
with redirect_stderr(stream), m.ostream_redirect(stdout=False):
m.raw_output(msg)
m.raw_err(msg2)
stdout, stderr = capfd.readouterr()
assert stdout == msg
assert stderr == ""
@ -260,11 +258,9 @@ def test_redirect_both(capfd):
stream = StringIO()
stream2 = StringIO()
with redirect_stdout(stream):
with redirect_stderr(stream2):
with m.ostream_redirect():
m.raw_output(msg)
m.raw_err(msg2)
with redirect_stdout(stream), redirect_stderr(stream2), m.ostream_redirect():
m.raw_output(msg)
m.raw_err(msg2)
stdout, stderr = capfd.readouterr()
assert stdout == ""
assert stderr == ""

View File

@ -25,7 +25,7 @@ def test_function_signatures(doc):
)
def test_named_arguments(msg):
def test_named_arguments():
assert m.kw_func0(5, 10) == "x=5, y=10"
assert m.kw_func1(5, 10) == "x=5, y=10"
@ -43,8 +43,7 @@ def test_named_arguments(msg):
# noinspection PyArgumentList
m.kw_func2(x=5, y=10, z=12)
assert excinfo.match(
r"(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))"
+ "{3}$"
r"(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$)){3}$"
)
assert m.kw_func4() == "{13 17}"
@ -59,7 +58,7 @@ def test_arg_and_kwargs():
assert m.args_function(*args) == args
args = "a1", "a2"
kwargs = dict(arg3="a3", arg4=4)
kwargs = {"arg3": "a3", "arg4": 4}
assert m.args_kwargs_function(*args, **kwargs) == (args, kwargs)
@ -177,7 +176,7 @@ def test_mixed_args_and_kwargs(msg):
assert (
m.args_kwonly_kwargs_defaults.__doc__
== "args_kwonly_kwargs_defaults(i: int = 1, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n" # noqa: E501 line too long
== "args_kwonly_kwargs_defaults(i: int = 1, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n"
)
assert m.args_kwonly_kwargs_defaults() == (1, 3.14159, (), 42, {})
assert m.args_kwonly_kwargs_defaults(2) == (2, 3.14159, (), 42, {})
@ -233,15 +232,15 @@ def test_keyword_only_args(msg):
x.method(i=1, j=2)
assert (
m.first_arg_kw_only.__init__.__doc__
== "__init__(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 0) -> None\n" # noqa: E501 line too long
== "__init__(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 0) -> None\n"
)
assert (
m.first_arg_kw_only.method.__doc__
== "method(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 1, j: int = 2) -> None\n" # noqa: E501 line too long
== "method(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 1, j: int = 2) -> None\n"
)
def test_positional_only_args(msg):
def test_positional_only_args():
assert m.pos_only_all(1, 2) == (1, 2)
assert m.pos_only_all(2, 1) == (2, 1)
@ -283,7 +282,7 @@ def test_positional_only_args(msg):
# Mix it with args and kwargs:
assert (
m.args_kwonly_full_monty.__doc__
== "args_kwonly_full_monty(arg0: int = 1, arg1: int = 2, /, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n" # noqa: E501 line too long
== "args_kwonly_full_monty(arg0: int = 1, arg1: int = 2, /, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n"
)
assert m.args_kwonly_full_monty() == (1, 2, 3.14159, (), 42, {})
assert m.args_kwonly_full_monty(8) == (8, 2, 3.14159, (), 42, {})
@ -326,18 +325,18 @@ def test_positional_only_args(msg):
# https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
assert (
m.first_arg_kw_only.pos_only.__doc__
== "pos_only(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, /, i: int, j: int) -> None\n" # noqa: E501 line too long
== "pos_only(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, /, i: int, j: int) -> None\n"
)
def test_signatures():
assert "kw_only_all(*, i: int, j: int) -> tuple\n" == m.kw_only_all.__doc__
assert "kw_only_mixed(i: int, *, j: int) -> tuple\n" == m.kw_only_mixed.__doc__
assert "pos_only_all(i: int, j: int, /) -> tuple\n" == m.pos_only_all.__doc__
assert "pos_only_mix(i: int, /, j: int) -> tuple\n" == m.pos_only_mix.__doc__
assert m.kw_only_all.__doc__ == "kw_only_all(*, i: int, j: int) -> tuple\n"
assert m.kw_only_mixed.__doc__ == "kw_only_mixed(i: int, *, j: int) -> tuple\n"
assert m.pos_only_all.__doc__ == "pos_only_all(i: int, j: int, /) -> tuple\n"
assert m.pos_only_mix.__doc__ == "pos_only_mix(i: int, /, j: int) -> tuple\n"
assert (
"pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n"
== m.pos_kw_only_mix.__doc__
m.pos_kw_only_mix.__doc__
== "pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n"
)

View File

@ -183,9 +183,9 @@ def test_static_properties():
# Only static attributes can be deleted
del m.TestPropertiesOverride.def_readonly_static
assert hasattr(m.TestPropertiesOverride, "def_readonly_static")
assert (
hasattr(m.TestPropertiesOverride, "def_readonly_static")
and m.TestPropertiesOverride.def_readonly_static
m.TestPropertiesOverride.def_readonly_static
is m.TestProperties.def_readonly_static
)
assert "def_readonly_static" not in m.TestPropertiesOverride.__dict__
@ -256,10 +256,7 @@ def test_no_mixed_overloads():
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
def test_property_return_value_policies(access):
if not access.startswith("static"):
obj = m.TestPropRVP()
else:
obj = m.TestPropRVP
obj = m.TestPropRVP() if not access.startswith("static") else m.TestPropRVP
ref = getattr(obj, access + "_ref")
assert ref.value == 1

View File

@ -1,3 +1,5 @@
import builtins
import pytest
import env
@ -86,12 +88,7 @@ def test_builtin_key_type():
Previous versions of pybind11 would add a unicode key in python 2.
"""
if hasattr(__builtins__, "keys"):
keys = __builtins__.keys()
else: # this is to make pypy happy since builtins is different there.
keys = __builtins__.__dict__.keys()
assert {type(k) for k in keys} == {str}
assert all(type(k) == str for k in dir(builtins))
@pytest.mark.xfail("env.PYPY", reason="PyModule_GetName()")

View File

@ -22,7 +22,7 @@ def test_dtypes():
)
@pytest.fixture(scope="function")
@pytest.fixture()
def arr():
return np.array([[1, 2, 3], [4, 5, 6]], "=u2")
@ -67,7 +67,7 @@ def test_array_attributes():
@pytest.mark.parametrize(
"args, ret", [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]
("args", "ret"), [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]
)
def test_index_offset(arr, args, ret):
assert m.index_at(arr, *args) == ret
@ -93,7 +93,7 @@ def test_dim_check_fail(arr):
@pytest.mark.parametrize(
"args, ret",
("args", "ret"),
[
([], [1, 2, 3, 4, 5, 6]),
([1], [4, 5, 6]),
@ -211,12 +211,14 @@ def test_wrap():
assert b[0, 0] == 1234
a1 = np.array([1, 2], dtype=np.int16)
assert a1.flags.owndata and a1.base is None
assert a1.flags.owndata
assert a1.base is None
a2 = m.wrap(a1)
assert_references(a1, a2)
a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="F")
assert a1.flags.owndata and a1.base is None
assert a1.flags.owndata
assert a1.base is None
a2 = m.wrap(a1)
assert_references(a1, a2)
@ -451,13 +453,15 @@ def test_array_resize():
try:
m.array_resize3(a, 3, True)
except ValueError as e:
assert str(e).startswith("cannot resize an array")
assert str(e).startswith("cannot resize an array") # noqa: PT017
# transposed array doesn't own data
b = a.transpose()
try:
m.array_resize3(b, 3, False)
except ValueError as e:
assert str(e).startswith("cannot resize this array: it does not own its data")
assert str(e).startswith( # noqa: PT017
"cannot resize this array: it does not own its data"
)
# ... but reshape should be fine
m.array_reshape2(b)
assert b.shape == (8, 8)

View File

@ -130,14 +130,10 @@ def test_dtype(simple_dtype):
partial_nested_fmt(),
"[('a','S3'),('b','S3')]",
(
"{{'names':['a','b','c','d'],"
+ "'formats':[('S4',(3,)),('"
+ e
+ "i4',(2,)),('u1',(3,)),('"
+ e
+ "f4',(4,2))],"
+ "'offsets':[0,12,20,24],'itemsize':56}}"
).format(e=e),
"{'names':['a','b','c','d'],"
f"'formats':[('S4',(3,)),('{e}i4',(2,)),('u1',(3,)),('{e}f4',(4,2))],"
"'offsets':[0,12,20,24],'itemsize':56}"
),
"[('e1','" + e + "i8'),('e2','u1')]",
"[('x','i1'),('y','" + e + "u8')]",
"[('cflt','" + e + "c8'),('cdbl','" + e + "c16')]",
@ -291,19 +287,17 @@ def test_array_array():
arr = m.create_array_array(3)
assert str(arr.dtype).replace(" ", "") == (
"{{'names':['a','b','c','d'],"
+ "'formats':[('S4',(3,)),('"
+ e
+ "i4',(2,)),('u1',(3,)),('{e}f4',(4,2))],"
+ "'offsets':[0,12,20,24],'itemsize':56}}"
).format(e=e)
"{'names':['a','b','c','d'],"
f"'formats':[('S4',(3,)),('{e}i4',(2,)),('u1',(3,)),('{e}f4',(4,2))],"
"'offsets':[0,12,20,24],'itemsize':56}"
)
assert m.print_array_array(arr) == [
"a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1},"
+ "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
"c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
"a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001},"
+ "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
"c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
"a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001},"
+ "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
"c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
]
assert arr["a"].tolist() == [
[b"ABCD", b"KLMN", b"UVWX"],

View File

@ -149,7 +149,7 @@ def test_docs(doc):
doc(m.vectorized_func)
== """
vectorized_func(arg0: numpy.ndarray[numpy.int32], arg1: numpy.ndarray[numpy.float32], arg2: numpy.ndarray[numpy.float64]) -> object
""" # noqa: E501 line too long
"""
)

View File

@ -15,7 +15,7 @@ def test_obj_class_name():
assert m.obj_class_name([]) == "list"
def test_handle_from_move_only_type_with_operator_PyObject(): # noqa: N802
def test_handle_from_move_only_type_with_operator_PyObject():
assert m.handle_from_move_only_type_with_operator_PyObject_ncnst()
assert m.handle_from_move_only_type_with_operator_PyObject_const()
@ -33,7 +33,7 @@ def test_iterator(doc):
@pytest.mark.parametrize(
"pytype, from_iter_func",
("pytype", "from_iter_func"),
[
(frozenset, m.get_frozenset_from_iterable),
(list, m.get_list_from_iterable),
@ -87,7 +87,7 @@ def test_list(capture, doc):
assert doc(m.print_list) == "print_list(arg0: list) -> None"
def test_none(capture, doc):
def test_none(doc):
assert doc(m.get_none) == "get_none() -> None"
assert doc(m.print_none) == "print_none(arg0: None) -> None"
@ -182,10 +182,10 @@ class CustomContains:
@pytest.mark.parametrize(
"arg,func",
("arg", "func"),
[
(set(), m.anyset_contains),
(dict(), m.dict_contains),
({}, m.dict_contains),
(CustomContains(), m.obj_contains),
],
)
@ -273,7 +273,7 @@ def test_bytes(doc):
assert doc(m.bytes_from_str) == "bytes_from_str() -> bytes"
def test_bytearray(doc):
def test_bytearray():
assert m.bytearray_from_char_ssize_t().decode() == "$%"
assert m.bytearray_from_char_size_t().decode() == "@$!"
assert m.bytearray_from_string().decode() == "foo"
@ -385,7 +385,7 @@ def test_accessors():
assert d["implicit_list"] == [1, 2, 3]
assert all(x in TestObject.__dict__ for x in d["implicit_dict"])
assert m.tuple_accessor(tuple()) == (0, 1, 2)
assert m.tuple_accessor(()) == (0, 1, 2)
d = m.accessor_assignment()
assert d["get"] == 0
@ -593,7 +593,7 @@ def test_issue2361():
@pytest.mark.parametrize(
"method, args, fmt, expected_view",
("method", "args", "fmt", "expected_view"),
[
(m.test_memoryview_object, (b"red",), "B", b"red"),
(m.test_memoryview_buffer_info, (b"green",), "B", b"green"),
@ -651,7 +651,7 @@ def test_memoryview_from_memory():
def test_builtin_functions():
assert m.get_len([i for i in range(42)]) == 42
assert m.get_len(list(range(42))) == 42
with pytest.raises(TypeError) as exc_info:
m.get_len(i for i in range(42))
assert str(exc_info.value) in [
@ -695,7 +695,7 @@ def test_pass_bytes_or_unicode_to_string_types():
@pytest.mark.parametrize(
"create_weakref, create_weakref_with_callback",
("create_weakref", "create_weakref_with_callback"),
[
(m.weakref_from_handle, m.weakref_from_handle_and_function),
(m.weakref_from_object, m.weakref_from_object_and_function),
@ -710,7 +710,7 @@ def test_weakref(create_weakref, create_weakref_with_callback):
callback_called = False
def callback(wr):
def callback(_):
nonlocal callback_called
callback_called = True
@ -730,7 +730,7 @@ def test_weakref(create_weakref, create_weakref_with_callback):
@pytest.mark.parametrize(
"create_weakref, has_callback",
("create_weakref", "has_callback"),
[
(m.weakref_from_handle, False),
(m.weakref_from_object, False),
@ -748,10 +748,7 @@ def test_weakref_err(create_weakref, has_callback):
ob = C()
# Should raise TypeError on CPython
with pytest.raises(TypeError) if not env.PYPY else contextlib.nullcontext():
if has_callback:
_ = create_weakref(ob, callback)
else:
_ = create_weakref(ob)
_ = create_weakref(ob, callback) if has_callback else create_weakref(ob)
def test_cpp_iterators():
@ -814,33 +811,36 @@ def test_populate_obj_str_attrs():
@pytest.mark.parametrize(
"a,b", [("foo", "bar"), (1, 2), (1.0, 2.0), (list(range(3)), list(range(3, 6)))]
("a", "b"),
[("foo", "bar"), (1, 2), (1.0, 2.0), (list(range(3)), list(range(3, 6)))],
)
def test_inplace_append(a, b):
expected = a + b
assert m.inplace_append(a, b) == expected
@pytest.mark.parametrize("a,b", [(3, 2), (3.0, 2.0), (set(range(3)), set(range(2)))])
@pytest.mark.parametrize(
("a", "b"), [(3, 2), (3.0, 2.0), (set(range(3)), set(range(2)))]
)
def test_inplace_subtract(a, b):
expected = a - b
assert m.inplace_subtract(a, b) == expected
@pytest.mark.parametrize("a,b", [(3, 2), (3.0, 2.0), ([1], 3)])
@pytest.mark.parametrize(("a", "b"), [(3, 2), (3.0, 2.0), ([1], 3)])
def test_inplace_multiply(a, b):
expected = a * b
assert m.inplace_multiply(a, b) == expected
@pytest.mark.parametrize("a,b", [(6, 3), (6.0, 3.0)])
@pytest.mark.parametrize(("a", "b"), [(6, 3), (6.0, 3.0)])
def test_inplace_divide(a, b):
expected = a / b
assert m.inplace_divide(a, b) == expected
@pytest.mark.parametrize(
"a,b",
("a", "b"),
[
(False, True),
(
@ -857,7 +857,7 @@ def test_inplace_or(a, b):
@pytest.mark.parametrize(
"a,b",
("a", "b"),
[
(True, False),
(
@ -873,13 +873,13 @@ def test_inplace_and(a, b):
assert m.inplace_and(a, b) == expected
@pytest.mark.parametrize("a,b", [(8, 1), (-3, 2)])
@pytest.mark.parametrize(("a", "b"), [(8, 1), (-3, 2)])
def test_inplace_lshift(a, b):
expected = a << b
assert m.inplace_lshift(a, b) == expected
@pytest.mark.parametrize("a,b", [(8, 1), (-2, 2)])
@pytest.mark.parametrize(("a", "b"), [(8, 1), (-2, 2)])
def test_inplace_rshift(a, b):
expected = a >> b
assert m.inplace_rshift(a, b) == expected

View File

@ -1,5 +1,5 @@
import pytest
from pytest import approx
from pytest import approx # noqa: PT013
from pybind11_tests import ConstructorStats
from pybind11_tests import sequences_and_iterators as m
@ -103,7 +103,8 @@ def test_sequence():
assert "Sequence" in repr(s)
assert len(s) == 5
assert s[0] == 0 and s[3] == 0
assert s[0] == 0
assert s[3] == 0
assert 12.34 not in s
s[0], s[3] = 12.34, 56.78
assert 12.34 in s
@ -245,7 +246,7 @@ def test_iterator_rvp():
def test_carray_iterator():
"""#4100: Check for proper iterator overload with C-Arrays"""
args_gt = list(float(i) for i in range(3))
args_gt = [float(i) for i in range(3)]
arr_h = m.CArrayHolder(*args_gt)
args = list(arr_h)
assert args_gt == args

View File

@ -14,7 +14,7 @@ def test_vector(doc):
assert m.cast_bool_vector() == [True, False]
assert m.load_bool_vector([True, False])
assert m.load_bool_vector(tuple([True, False]))
assert m.load_bool_vector((True, False))
assert doc(m.cast_vector) == "cast_vector() -> List[int]"
assert doc(m.load_vector) == "load_vector(arg0: List[int]) -> bool"
@ -23,7 +23,7 @@ def test_vector(doc):
assert m.cast_ptr_vector() == ["lvalue", "lvalue"]
def test_deque(doc):
def test_deque():
"""std::deque <-> list"""
lst = m.cast_deque()
assert lst == [1]
@ -95,7 +95,8 @@ def test_recursive_casting():
# Issue #853 test case:
z = m.cast_unique_ptr_vector()
assert z[0].value == 7 and z[1].value == 42
assert z[0].value == 7
assert z[1].value == 42
def test_move_out_container():

View File

@ -186,9 +186,9 @@ def test_map_string_double():
um["ua"] = 1.1
um["ub"] = 2.6
assert sorted(list(um)) == ["ua", "ub"]
assert sorted(um) == ["ua", "ub"]
assert list(um.keys()) == list(um)
assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
assert sorted(um.items()) == [("ua", 1.1), ("ub", 2.6)]
assert list(zip(um.keys(), um.values())) == list(um.items())
assert "UnorderedMapStringDouble" in str(um)
@ -304,11 +304,11 @@ def test_map_delitem():
um["ua"] = 1.1
um["ub"] = 2.6
assert sorted(list(um)) == ["ua", "ub"]
assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
assert sorted(um) == ["ua", "ub"]
assert sorted(um.items()) == [("ua", 1.1), ("ub", 2.6)]
del um["ua"]
assert sorted(list(um)) == ["ub"]
assert sorted(list(um.items())) == [("ub", 2.6)]
assert sorted(um) == ["ub"]
assert sorted(um.items()) == [("ub", 2.6)]
def test_map_view_types():

View File

@ -192,8 +192,7 @@ def test_move_support():
class NCVirtExt(m.NCVirt):
def get_noncopyable(self, a, b):
# Constructs and returns a new instance:
nc = m.NonCopyable(a * a, b * b)
return nc
return m.NonCopyable(a * a, b * b)
def get_movable(self, a, b):
# Return a referenced copy
@ -256,7 +255,7 @@ def test_dispatch_issue(msg):
assert m.dispatch_issue_go(b) == "Yay.."
def test_recursive_dispatch_issue(msg):
def test_recursive_dispatch_issue():
"""#3357: Recursive dispatch fails to find python function override"""
class Data(m.Data):
@ -269,7 +268,7 @@ def test_recursive_dispatch_issue(msg):
# lambda is a workaround, which adds extra frame to the
# current CPython thread. Removing lambda reveals the bug
# [https://github.com/pybind/pybind11/issues/3357]
(lambda: visitor(Data(first.value + second.value)))()
(lambda: visitor(Data(first.value + second.value)))() # noqa: PLC3002
class StoreResultVisitor:
def __init__(self):

View File

@ -17,14 +17,18 @@ def run(args: List[str]) -> None:
assert len(args) == 1, "codespell_errors.txt"
cache = {}
done = set()
for line in sorted(open(args[0]).read().splitlines()):
with open(args[0]) as f:
lines = f.read().splitlines()
for line in sorted(lines):
i = line.find(" ==> ")
if i > 0:
flds = line[:i].split(":")
if len(flds) >= 2:
filename, line_num = flds[:2]
if filename not in cache:
cache[filename] = open(filename).read().splitlines()
with open(filename) as f:
cache[filename] = f.read().splitlines()
supp = cache[filename][int(line_num) - 1]
if supp not in done:
print(supp)