diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 27474f2f7..2255f2e4d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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 diff --git a/docs/conf.py b/docs/conf.py index cdb9f6306..6e24751e9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -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() diff --git a/pybind11/__init__.py b/pybind11/__init__.py index 4fbb17079..7c10b3057 100644 --- a/pybind11/__init__.py +++ b/pybind11/__init__.py @@ -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) diff --git a/pybind11/commands.py b/pybind11/commands.py index 152fa20ce..b11690f46 100644 --- a/pybind11/commands.py +++ b/pybind11/commands.py @@ -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. diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py index b9b433b65..0fb4679e4 100644 --- a/pybind11/setup_helpers.py +++ b/pybind11/setup_helpers.py @@ -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. diff --git a/pyproject.toml b/pyproject.toml index 3ba1b4b22..96cf84265 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"] diff --git a/setup.cfg b/setup.cfg index 8b3361981..c35dd07ae 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/tests/conftest.py b/tests/conftest.py index c24d51d4d..b60d3c956 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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 diff --git a/tests/env.py b/tests/env.py index 0345df65d..7eea5a3b3 100644 --- a/tests/env.py +++ b/tests/env.py @@ -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() diff --git a/tests/test_async.py b/tests/test_async.py index b9ff9514d..83a4c5036 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -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): diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 8354b68cd..eb58c4675 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -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 diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index d38ae6802..b1f57bdd9 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -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] diff --git a/tests/test_class.py b/tests/test_class.py index 64abac133..ee7467cf8 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -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): diff --git a/tests/test_const_name.py b/tests/test_const_name.py index 10b0caee2..a145f0bbb 100644 --- a/tests/test_const_name.py +++ b/tests/test_const_name.py @@ -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( ( "", diff --git a/tests/test_custom_type_casters.py b/tests/test_custom_type_casters.py index 731380e46..3a00ea964 100644 --- a/tests/test_custom_type_casters.py +++ b/tests/test_custom_type_casters.py @@ -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: diff --git a/tests/test_custom_type_setup.py b/tests/test_custom_type_setup.py index 19b44c9de..e63ff5758 100644 --- a/tests/test_custom_type_setup.py +++ b/tests/test_custom_type_setup.py @@ -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. diff --git a/tests/test_eigen_matrix.py b/tests/test_eigen_matrix.py index 4407fa6ae..b2e76740b 100644 --- a/tests/test_eigen_matrix.py +++ b/tests/test_eigen_matrix.py @@ -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(): diff --git a/tests/test_eigen_tensor.py b/tests/test_eigen_tensor.py index cd54efa06..3e7ee6b7f 100644 --- a/tests/test_eigen_tensor.py +++ b/tests/test_eigen_tensor.py @@ -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[?, ?, ?]]" ) diff --git a/tests/test_enum.py b/tests/test_enum.py index f14a72398..4e85d29c3 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -1,3 +1,5 @@ +# ruff: noqa: SIM201 SIM300 SIM202 + import pytest from pybind11_tests import enums as m diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 8bcefe3de..7f80a5da5 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -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] == [ diff --git a/tests/test_factory_constructors.py b/tests/test_factory_constructors.py index 120a587c4..04df80260 100644 --- a/tests/test_factory_constructors.py +++ b/tests/test_factory_constructors.py @@ -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 + """ ) diff --git a/tests/test_gil_scoped.py b/tests/test_gil_scoped.py index 6af6a472d..fc8af9b77 100644 --- a/tests/test_gil_scoped.py +++ b/tests/test_gil_scoped.py @@ -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: diff --git a/tests/test_iostream.py b/tests/test_iostream.py index 5bbdf6955..79b2a2b8c 100644 --- a/tests/test_iostream.py +++ b/tests/test_iostream.py @@ -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 == "" diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py index ab7017886..7174726fc 100644 --- a/tests/test_kwargs_and_defaults.py +++ b/tests/test_kwargs_and_defaults.py @@ -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" ) diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py index 0a2ae1239..a85468575 100644 --- a/tests/test_methods_and_attributes.py +++ b/tests/test_methods_and_attributes.py @@ -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 diff --git a/tests/test_modules.py b/tests/test_modules.py index c3e8cea6e..3d73e3fbd 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -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()") diff --git a/tests/test_numpy_array.py b/tests/test_numpy_array.py index cdec9ad60..070813d3a 100644 --- a/tests/test_numpy_array.py +++ b/tests/test_numpy_array.py @@ -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) diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index fcfd587b1..d10457eeb 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -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"], diff --git a/tests/test_numpy_vectorize.py b/tests/test_numpy_vectorize.py index 7e8c015c4..f1e8b6254 100644 --- a/tests/test_numpy_vectorize.py +++ b/tests/test_numpy_vectorize.py @@ -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 + """ ) diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index a1a80a293..946b94140 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -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 diff --git a/tests/test_sequences_and_iterators.py b/tests/test_sequences_and_iterators.py index de486e3e8..dc129f2bf 100644 --- a/tests/test_sequences_and_iterators.py +++ b/tests/test_sequences_and_iterators.py @@ -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 diff --git a/tests/test_stl.py b/tests/test_stl.py index d30c38211..b7a0d1c0d 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -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(): diff --git a/tests/test_stl_binders.py b/tests/test_stl_binders.py index 9eb906f06..7dca742a9 100644 --- a/tests/test_stl_binders.py +++ b/tests/test_stl_binders.py @@ -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(): diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py index 4d00d3690..c17af7df5 100644 --- a/tests/test_virtual_functions.py +++ b/tests/test_virtual_functions.py @@ -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): diff --git a/tools/codespell_ignore_lines_from_errors.py b/tools/codespell_ignore_lines_from_errors.py index 5403ec3ad..4ec9add12 100644 --- a/tools/codespell_ignore_lines_from_errors.py +++ b/tools/codespell_ignore_lines_from_errors.py @@ -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)