ronantakizawa/codereview-bench huggingface dataset:
Repository: pytest-dev/pytest
File: src/_pytest/unraisableexception.py (Python)

Code before:
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


_unraisable_exceptions: collections.deque[UnraisableMeta | BaseException] = (
    collections.deque()
)


def collect_unraisable() -> None:
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
            try:
                meta = _unraisable_exceptions.pop()
            except IndexError:
                break

            if isinstance(meta, BaseException):
                hook_error = RuntimeError("Failed to process unraisable exception")
                hook_error.__cause__ = meta
                errors.append(hook_error)
                continue

            msg = meta.msg
            try:
                warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
            except pytest.PytestUnraisableExceptionWarning as e:
                if meta.exc_value is not None:
                    # exceptions have a better way to show the traceback, but
                    # warnings do not, so hide the traceback from the msg and

Review comment (suggestion):
I'd use a dataclass; named tuples feel a bit outdated these days. But no problem if you want to keep it.

Code after:
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.nodes import Item
from _pytest.stash import StashKey
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


def gc_collect_harder() -> None:
    # A single collection doesn't necessarily collect everything.
    # Constant determined experimentally by the Trio project.
    for _ in range(5):
        gc.collect()


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


unraisable_exceptions: StashKey[collections.deque[UnraisableMeta | BaseException]] = (
    StashKey()
)


def collect_unraisable(config: Config) -> None:
    pop_unraisable = config.stash[unraisable_exceptions].pop
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
            try:
                meta = pop_unraisable()
            except IndexError:
                break

            if isinstance(meta, BaseException):
                hook_error = RuntimeError("Failed to process unraisable exception")
                hook_error.__cause__ = meta
Repository: pytest-dev/pytest
File: testing/test_unraisableexception.py (Python)

Code before:
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    assert result.parseoutcomes() == {"passed": 1, "failed": 1}


@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_warning_multiple_errors(pytester: Pytester) -> None:
    pytester.makepyfile(
        test_it=f"""
        class BrokenDel:
            def __init__(self, msg: str):
                self.msg = msg

            def __del__(self) -> None:
                raise ValueError(self.msg)

        def test_it() -> None:
            BrokenDel("del is broken 1")
            BrokenDel("del is broken 2")
            {"import gc; gc.collect()" * PYPY}

        def test_2(): pass
        """
    )
    result = pytester.runpytest()
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    assert result.parseoutcomes() == {"passed": 1, "failed": 1}
    result.stdout.fnmatch_lines(
        [
            "  | *ExceptionGroup: multiple unraisable exception warnings (2 sub-exceptions)"
        ]
    )


def test_unraisable_collection_failure(pytester: Pytester) -> None:
    pytester.makepyfile(
        test_it=f"""
        class BrokenDel:
            def __del__(self):
                raise ValueError("del is broken")

        def test_it():
            obj = BrokenDel()
            del obj
            {"import gc; gc.collect()" * PYPY}

        def test_2(): pass
        """
    )

    class MyError(BaseException):
        pass

Review comment (suggestion):
You can use `result.assertoutcomes` instead, slightly cleaner.

Code after:
        """
    )
    result = pytester.runpytest()
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    result.assert_outcomes(passed=1, failed=1)


@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning")
def test_unraisable_warning_multiple_errors(pytester: Pytester) -> None:
    pytester.makepyfile(
        test_it=f"""
        class BrokenDel:
            def __init__(self, msg: str):
                self.msg = msg

            def __del__(self) -> None:
                raise ValueError(self.msg)

        def test_it() -> None:
            BrokenDel("del is broken 1")
            BrokenDel("del is broken 2")
            {"import gc; gc.collect()" * PYPY}

        def test_2(): pass
        """
    )
    result = pytester.runpytest()
    assert result.ret == pytest.ExitCode.TESTS_FAILED
    result.assert_outcomes(passed=1, failed=1)
    result.stdout.fnmatch_lines(
        [
            "  | *ExceptionGroup: multiple unraisable exception warnings (2 sub-exceptions)"
        ]
    )


def test_unraisable_collection_failure(pytester: Pytester) -> None:
    pytester.makepyfile(
        test_it=f"""
        class BrokenDel:
            def __del__(self):
                raise ValueError("del is broken")

        def test_it():
            obj = BrokenDel()
            del obj
            {"import gc; gc.collect()" * PYPY}

        def test_2(): pass
        """
    )
Repository: pytest-dev/pytest
File: src/_pytest/unraisableexception.py (Python)

Code before:
from __future__ import annotations

import collections
import functools
import gc
import sys
import traceback
from typing import Callable
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


def gc_collect_harder() -> None:
    # constant determined experimentally by the Trio project
    for _ in range(5):
        gc.collect()


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


_unraisable_exceptions: collections.deque[UnraisableMeta | BaseException] = (
    collections.deque()
)


def collect_unraisable() -> None:
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
            try:
                meta = _unraisable_exceptions.pop()
            except IndexError:
                break

Review comment (suggestion):
```suggestion
    # Constant determined experimentally by the Trio project.
```

Code after:
from __future__ import annotations

import collections
from collections.abc import Callable
import functools
import gc
import sys
import traceback
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.nodes import Item
from _pytest.stash import StashKey
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


def gc_collect_harder() -> None:
    # A single collection doesn't necessarily collect everything.
    # Constant determined experimentally by the Trio project.
    for _ in range(5):
        gc.collect()


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


unraisable_exceptions: StashKey[collections.deque[UnraisableMeta | BaseException]] = (
    StashKey()
)


def collect_unraisable(config: Config) -> None:
    pop_unraisable = config.stash[unraisable_exceptions].pop
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
Repository: pytest-dev/pytest
File: src/_pytest/unraisableexception.py (Python)

Code before:
import functools
import gc
import sys
import traceback
from typing import Callable
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.nodes import Item
from _pytest.stash import StashKey
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


def gc_collect_harder() -> None:
    # Constant determined experimentally by the Trio project.
    for _ in range(5):
        gc.collect()


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


unraisable_exceptions: StashKey[collections.deque[UnraisableMeta | BaseException]] = (
    StashKey()
)


def collect_unraisable(config: Config) -> None:
    pop_unraisable = config.stash[unraisable_exceptions].pop
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
            try:
                meta = pop_unraisable()
            except IndexError:
                break

Review comment (suggestion):
```suggestion
    # A single collection doesn't necessarily collect everything.
    # Constant determined experimentally by the Trio project.
```

Code after:
from collections.abc import Callable
import functools
import gc
import sys
import traceback
from typing import NamedTuple
from typing import TYPE_CHECKING
import warnings

from _pytest.config import Config
from _pytest.nodes import Item
from _pytest.stash import StashKey
from _pytest.tracemalloc import tracemalloc_message
import pytest


if TYPE_CHECKING:
    pass

if sys.version_info < (3, 11):
    from exceptiongroup import ExceptionGroup


def gc_collect_harder() -> None:
    # A single collection doesn't necessarily collect everything.
    # Constant determined experimentally by the Trio project.
    for _ in range(5):
        gc.collect()


class UnraisableMeta(NamedTuple):
    msg: str
    cause_msg: str
    exc_value: BaseException | None


unraisable_exceptions: StashKey[collections.deque[UnraisableMeta | BaseException]] = (
    StashKey()
)


def collect_unraisable(config: Config) -> None:
    pop_unraisable = config.stash[unraisable_exceptions].pop
    errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = []
    meta = None
    hook_error = None
    try:
        while True:
            try:
                meta = pop_unraisable()
            except IndexError:
Repository: pytest-dev/pytest
File: testing/test_collection.py (Python)

Code before:
    )
    ensure_file(pytester.path / "test_ham.py").write_text(
        f"raise {exception_class.__name__}()", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_spam.py").write_text(
        f"print('{tail}')", encoding="UTF-8"
    )

    result = pytester.runpytest_subprocess("-s")
    result.stdout.fnmatch_lines([f"*{head}*"])
    result.stdout.fnmatch_lines([msg])
    result.stdout.no_fnmatch_line(f"*{tail}*")


def test_yield_disallowed_in_tests(pytester: Pytester):
    """Ensure generator test functions with 'yield' raise a RuntimeError."""
    pytester.makepyfile(
        """
        def test_with_yield():
            yield 1
        """
    )
    result = pytester.runpytest()
    assert result.ret == 2
    result.stdout.fnmatch_lines(
        ["*RuntimeError: 'yield' keyword is allowed in fixtures, but not in tests (*)*"]
    )
    result.stdout.fnmatch_lines(["*collected 0 items*"])


Review comment (bug):
Please make sure to match the test name in the message (there ia  bug in the original code which is not caught because of that).

Code after:
    )
    ensure_file(pytester.path / "test_ham.py").write_text(
        f"raise {exception_class.__name__}()", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_spam.py").write_text(
        f"print('{tail}')", encoding="UTF-8"
    )

    result = pytester.runpytest_subprocess("-s")
    result.stdout.fnmatch_lines([f"*{head}*"])
    result.stdout.fnmatch_lines([msg])
    result.stdout.no_fnmatch_line(f"*{tail}*")


def test_yield_disallowed_in_tests(pytester: Pytester):
    """Ensure generator test functions with 'yield' fail collection (#12960)."""
    pytester.makepyfile(
        """
        def test_with_yield():
            yield 1
        """
    )
    result = pytester.runpytest()
    assert result.ret == 2
    result.stdout.fnmatch_lines(
        ["*'yield' keyword is allowed in fixtures, but not in tests (test_with_yield)*"]
    )
    # Assert that no tests were collected
    result.stdout.fnmatch_lines(["*collected 0 items*"])
Repository: pytest-dev/pytest
File: testing/test_collection.py (Python)

Code before:
)
def test_respect_system_exceptions(
    pytester: Pytester,
    exception_class: type[BaseException],
    msg: str,
):
    head = "Before exception"
    tail = "After exception"
    ensure_file(pytester.path / "test_eggs.py").write_text(
        f"print('{head}')", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_ham.py").write_text(
        f"raise {exception_class.__name__}()", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_spam.py").write_text(
        f"print('{tail}')", encoding="UTF-8"
    )

    result = pytester.runpytest_subprocess("-s")
    result.stdout.fnmatch_lines([f"*{head}*"])
    result.stdout.fnmatch_lines([msg])
    result.stdout.no_fnmatch_line(f"*{tail}*")


def test_yield_disallowed_in_tests(pytester: Pytester):
    """Ensure generator test functions with 'yield' raise a RuntimeError."""
    pytester.makepyfile(
        """
        def test_with_yield():
            yield 1
        """
    )
    result = pytester.runpytest()
    assert result.ret == 2
    result.stdout.fnmatch_lines(
        ["*RuntimeError: 'yield' keyword is allowed in fixtures, but not in tests (*)*"]
    )
    result.stdout.fnmatch_lines(["*collected 0 items*"])


Review comment (bug):
```suggestion
    """Ensure generator test functions with 'yield' fail collection (#12960)."""
```

Code after:
)
def test_respect_system_exceptions(
    pytester: Pytester,
    exception_class: type[BaseException],
    msg: str,
):
    head = "Before exception"
    tail = "After exception"
    ensure_file(pytester.path / "test_eggs.py").write_text(
        f"print('{head}')", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_ham.py").write_text(
        f"raise {exception_class.__name__}()", encoding="UTF-8"
    )
    ensure_file(pytester.path / "test_spam.py").write_text(
        f"print('{tail}')", encoding="UTF-8"
    )

    result = pytester.runpytest_subprocess("-s")
    result.stdout.fnmatch_lines([f"*{head}*"])
    result.stdout.fnmatch_lines([msg])
    result.stdout.no_fnmatch_line(f"*{tail}*")


def test_yield_disallowed_in_tests(pytester: Pytester):
    """Ensure generator test functions with 'yield' fail collection (#12960)."""
    pytester.makepyfile(
        """
        def test_with_yield():
            yield 1
        """
    )
    result = pytester.runpytest()
    assert result.ret == 2
    result.stdout.fnmatch_lines(
        ["*'yield' keyword is allowed in fixtures, but not in tests (test_with_yield)*"]
    )
    # Assert that no tests were collected
    result.stdout.fnmatch_lines(["*collected 0 items*"])
Repository: pytest-dev/pytest
File: testing/python/fixtures.py (Python)

Code before:

            class TestClass(object):
                def test_one(self):
                    assert self.hello == "world"
                    assert len(values) == 1
                def test_two(self):
                    assert self.hello == "world"
                    assert len(values) == 1
            pytest.mark.usefixtures("myfix")(TestClass)
        """
        )
        reprec = pytester.inline_run()
        reprec.assertoutcome(passed=2)

    def test_empty_usefixtures_marker(self, pytester: Pytester) -> None:
        pytester.makepyfile(
            """
            import pytest

            @pytest.mark.usefixtures()
            def test_one():
                assert 1 == 1
        """
        )
        reprec = pytester.inline_run()
        reprec.assertoutcome(failed=1)

    def test_usefixtures_ini(self, pytester: Pytester) -> None:
        pytester.makeini(
            """
            [pytest]
            usefixtures = myfix
        """
        )
        pytester.makeconftest(
            """
            import pytest

            @pytest.fixture(scope="class")
            def myfix(request):
                request.cls.hello = "world"

        """
        )
        pytester.makepyfile(
            """
            class TestClass(object):
                def test_one(self):
                    assert self.hello == "world"
                def test_two(self):
                    assert self.hello == "world"

Review comment (suggestion):
This is good, but I feel we should test the actual message, using `pytest.runpytest()` and `fnmatch_lines()`.

Code after:

            class TestClass(object):
                def test_one(self):
                    assert self.hello == "world"
                    assert len(values) == 1
                def test_two(self):
                    assert self.hello == "world"
                    assert len(values) == 1
            pytest.mark.usefixtures("myfix")(TestClass)
        """
        )
        reprec = pytester.inline_run()
        reprec.assertoutcome(passed=2)

    def test_empty_usefixtures_marker(self, pytester: Pytester) -> None:
        """Empty usefixtures() marker issues a warning (#12439)."""
        pytester.makepyfile(
            """
            import pytest

            @pytest.mark.usefixtures()
            def test_one():
                assert 1 == 1
        """
        )
        result = pytester.runpytest()
        result.stdout.fnmatch_lines(
            "*PytestWarning: usefixtures() in test_empty_usefixtures_marker.py::test_one"
            " without arguments has no effect"
        )

    def test_usefixtures_ini(self, pytester: Pytester) -> None:
        pytester.makeini(
            """
            [pytest]
            usefixtures = myfix
        """
        )
        pytester.makeconftest(
            """
            import pytest

            @pytest.fixture(scope="class")
            def myfix(request):
                request.cls.hello = "world"

        """
        )
        pytester.makepyfile(
            """
            class TestClass(object):
Repository: pytest-dev/pytest
File: testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py (Python)

Code before:
from __future__ import annotations

from dataclasses import dataclass
from dataclasses import field


def test_dataclasses() -> None:
    @dataclass
    class SimpleDataObject:
        field_a: int = field()
        field_b: str = field()

        def __eq__(self, __o: object, /) -> bool:
            return super().__eq__(__o)

    left = SimpleDataObject(1, "b")
    right = SimpleDataObject(1, "c")

    assert left == right


Review comment (suggestion):
Now that we are using the positinal-only syntax we no longer need the double underscore:

```suggestion
        def __eq__(self, o: object, /) -> bool:
            return super().__eq__(o)
```

Code after:
from __future__ import annotations

from dataclasses import dataclass
from dataclasses import field


def test_dataclasses() -> None:
    @dataclass
    class SimpleDataObject:
        field_a: int = field()
        field_b: str = field()

        def __eq__(self, o: object, /) -> bool:
            return super().__eq__(o)

    left = SimpleDataObject(1, "b")
    right = SimpleDataObject(1, "c")

    assert left == right
Repository: pytest-dev/pytest
File: testing/test_mark.py (Python)

Code before:
        @pytest.fixture
        def add_attr1(request):
            request.instance.attr1 = object()


        @pytest.fixture
        def add_attr2(request):
            request.instance.attr2 = request.instance.attr1


        @pytest.mark.usefixtures('add_attr1')
        class Parent:
            pass


        @pytest.mark.usefixtures('add_attr2')
        class TestThings(Parent):
            def test_attrs(self):
                assert self.attr1 == self.attr2
        """
    )
    result = pytester.runpytest(foo)
    result.assert_outcomes(passed=1)


# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/12863")
def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None:
    foo = pytester.makepyfile(
        """
        import pytest

        class TestClass:
            @pytest.mark.parametrize("value", [1, 2])
            @classmethod
            def test_classmethod_wrapper(cls, value: int):
                assert value in [1, 2]

            @pytest.mark.parametrize("value", [1, 2])
            @staticmethod
            def test_staticmethod_wrapper(value: int):
                assert value in [1, 2]
        """
    )
    result = pytester.runpytest(foo)
    result.assert_outcomes(passed=4)


Review comment (suggestion):
```suggestion
def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None:
    """Check that applying marks works as intended on classmethods and staticmethods.
    
    Regression test for #12863.
    """
```

Code after:
        @pytest.fixture
        def add_attr1(request):
            request.instance.attr1 = object()


        @pytest.fixture
        def add_attr2(request):
            request.instance.attr2 = request.instance.attr1


        @pytest.mark.usefixtures('add_attr1')
        class Parent:
            pass


        @pytest.mark.usefixtures('add_attr2')
        class TestThings(Parent):
            def test_attrs(self):
                assert self.attr1 == self.attr2
        """
    )
    result = pytester.runpytest(foo)
    result.assert_outcomes(passed=1)


def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None:
    """Check that applying marks works as intended on classmethods and staticmethods.

    Regression test for #12863.
    """
    pytester.makepyfile(
        """
        import pytest

        class TestClass:
            @pytest.mark.parametrize("value", [1, 2])
            @classmethod
            def test_classmethod_wrapper(cls, value: int):
                assert value in [1, 2]

            @classmethod
            @pytest.mark.parametrize("value", [1, 2])
            def test_classmethod_wrapper_on_top(cls, value: int):
                assert value in [1, 2]

            @pytest.mark.parametrize("value", [1, 2])
            @staticmethod
            def test_staticmethod_wrapper(value: int):
                assert value in [1, 2]

            @staticmethod