diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0c5fda16e..1b77249e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,6 +46,7 @@ jobs: "ubuntu-py39", "ubuntu-py310", "ubuntu-py311", + "ubuntu-py311-exceptiongroup", "ubuntu-pypy3", "macos-py37", @@ -114,6 +115,10 @@ jobs: python: "3.11-dev" os: ubuntu-latest tox_env: "py311" + - name: "ubuntu-py311-exceptiongroup" + python: "3.11-dev" + os: ubuntu-latest + tox_env: "py311-exceptiongroup" - name: "ubuntu-pypy3" python: "pypy-3.7" os: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb26b74f5..68d1e3cc0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -68,6 +68,7 @@ repos: - packaging - tomli - types-pkg_resources + # for python>=3.11 - exceptiongroup>=1.0.0rc8 - repo: local hooks: diff --git a/setup.cfg b/setup.cfg index 3545a9503..38f50556c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -47,6 +47,7 @@ install_requires = pluggy>=0.12,<2.0 py>=1.8.2 colorama;sys_platform=="win32" + exceptiongroup>=1.0.0rc8;python_version<"3.11" importlib-metadata>=0.12;python_version<"3.8" tomli>=1.0.0;python_version<"3.11" python_requires = >=3.7 diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 34bf7bce8..bd7fac634 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -56,14 +56,11 @@ if TYPE_CHECKING: _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] -BaseExceptionGroup: Optional[Type[BaseException]] +BaseExceptionGroup: Type[BaseException] try: BaseExceptionGroup = BaseExceptionGroup # type: ignore except NameError: - try: - from exceptiongroup import BaseExceptionGroup - except ModuleNotFoundError: - BaseExceptionGroup = None + from exceptiongroup import BaseExceptionGroup class Code: @@ -936,7 +933,7 @@ class FormattedExcinfo: # Fall back to native traceback as a temporary workaround until # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 - if BaseExceptionGroup is not None and isinstance(e, BaseExceptionGroup): + if isinstance(e, BaseExceptionGroup): reprtraceback: Union[ ReprTracebackNative, ReprTraceback ] = ReprTracebackNative( diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 2e5cc03e5..e428b9c5c 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1478,8 +1478,8 @@ def _exceptiongroup_common( inner_chain: str, native: bool, ) -> None: - pre = "exceptiongroup." if not native else "" - pre2 = pre if sys.version_info < (3, 11) else "" + pre_raise = "exceptiongroup." if not native else "" + pre_catch = pre_raise if sys.version_info < (3, 11) else "" filestr = f""" {"import exceptiongroup" if not native else ""} import pytest @@ -1496,19 +1496,19 @@ def _exceptiongroup_common( excs.append(err) if excs: if inner_chain == "none": - raise {pre}BaseExceptionGroup("Oops", excs) + raise {pre_raise}BaseExceptionGroup("Oops", excs) try: raise SyntaxError() except SyntaxError as e: if inner_chain == "from": - raise {pre}BaseExceptionGroup("Oops", excs) from e + raise {pre_raise}BaseExceptionGroup("Oops", excs) from e else: - raise {pre}BaseExceptionGroup("Oops", excs) + raise {pre_raise}BaseExceptionGroup("Oops", excs) def outer(outer_chain, inner_chain): try: inner(inner_chain) - except {pre2}BaseExceptionGroup as e: + except {pre_catch}BaseExceptionGroup as e: if outer_chain == "none": raise if outer_chain == "from": @@ -1528,7 +1528,7 @@ def _exceptiongroup_common( match_lines += [ r" + Exception Group Traceback (most recent call last):", - rf" \| {pre2}BaseExceptionGroup: Oops \(2 sub-exceptions\)", + rf" \| {pre_catch}BaseExceptionGroup: Oops \(2 sub-exceptions\)", r" \| ValueError: From f\(\)", r" \| BaseException: From g\(\)", r"=* short test summary info =*", @@ -1537,7 +1537,7 @@ def _exceptiongroup_common( match_lines.append(r"FAILED test_excgroup.py::test - IndexError") else: match_lines.append( - rf"FAILED test_excgroup.py::test - {pre2}BaseExceptionGroup: Oops \(2 su.*" + rf"FAILED test_excgroup.py::test - {pre_catch}BaseExceptionGroup: Oops \(2.*" ) result.stdout.re_match_lines(match_lines) @@ -1554,5 +1554,6 @@ def test_native_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> @pytest.mark.parametrize("outer_chain", ["none", "from", "another"]) @pytest.mark.parametrize("inner_chain", ["none", "from", "another"]) def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None: + # with py>=3.11 does not depend on exceptiongroup, though there is a toxenv for it pytest.importorskip("exceptiongroup") _exceptiongroup_common(pytester, outer_chain, inner_chain, native=False)