Repository: agronholm/exceptiongroup

Issue:
Needs update for 3.11.1
3.11.1 merged a fix to https://github.com/python/cpython/issues/99553 (PR: https://github.com/python/cpython/pull/99572) which included a change in behaviour.

Currently `test_EG_subclass_wraps_anything` is broken, when run on 3.11.1.

Comments:

Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 038c6c8..14901c8 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -21,13 +21,13 @@ repos:
   - id: isort
 
 - repo: https://github.com/asottile/pyupgrade
-  rev: v3.3.0
+  rev: v3.3.1
   hooks:
   - id: pyupgrade
     args: ["--py37-plus", "--keep-runtime-typing"]
 
 - repo: https://github.com/psf/black
-  rev: 22.10.0
+  rev: 22.12.0
   hooks:
   - id: black
     exclude: "tests/test_catch_py311.py"
diff --git a/CHANGES.rst b/CHANGES.rst
index c2af7ae..ee46dfd 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,6 +3,11 @@ Version history
 
 This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.
 
+**UNRELEASED**
+
+- Backported upstream fix for gh-99553 (custom subclasses of ``BaseExceptionGroup`` that
+  also inherit from ``Exception`` should not be able to wrap base exceptions)
+
 **1.0.4**
 
 - Fixed regression introduced in v1.0.3 where the code computing the suggestions would
diff --git a/src/exceptiongroup/_exceptions.py b/src/exceptiongroup/_exceptions.py
index ebdd172..a2ca092 100644
--- a/src/exceptiongroup/_exceptions.py
+++ b/src/exceptiongroup/_exceptions.py
@@ -67,6 +67,18 @@ class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]):
             if all(isinstance(exc, Exception) for exc in __exceptions):
                 cls = ExceptionGroup
 
+        if issubclass(cls, Exception):
+            for exc in __exceptions:
+                if not isinstance(exc, Exception):
+                    if cls is ExceptionGroup:
+                        raise TypeError(
+                            "Cannot nest BaseExceptions in an ExceptionGroup"
+                        )
+                    else:
+                        raise TypeError(
+                            f"Cannot nest BaseExceptions in {cls.__name__!r}"
+                        )
+
         return super().__new__(cls, __message, __exceptions)
 
     def __init__(
@@ -219,15 +231,7 @@ class BaseExceptionGroup(BaseException, Generic[_BaseExceptionT_co]):
 
 class ExceptionGroup(BaseExceptionGroup[_ExceptionT_co], Exception):
     def __new__(cls, __message: str, __exceptions: Sequence[_ExceptionT_co]) -> Self:
-        instance: ExceptionGroup[_ExceptionT_co] = super().__new__(
-            cls, __message, __exceptions
-        )
-        if cls is ExceptionGroup:
-            for exc in __exceptions:
-                if not isinstance(exc, Exception):
-                    raise TypeError("Cannot nest BaseExceptions in an ExceptionGroup")
-
-        return instance
+        return super().__new__(cls, __message, __exceptions)
 
     if TYPE_CHECKING:
 


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 77d65b2..311aec4 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -40,7 +40,7 @@ jobs:
         path: ~/.cache/pip
         key: pip-test-${{ matrix.python-version }}-${{ matrix.os }}
     - name: Install dependencies
-      run: pip install .[test] coverage[toml] coveralls
+      run: pip install .[test] coveralls coverage[toml]
     - name: Test with pytest
       run: coverage run -m pytest
     - name: Upload Coverage
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index d0d33cd..9a0e39b 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -3,6 +3,8 @@ import collections.abc
 import sys
 import unittest
 
+import pytest
+
 from exceptiongroup import BaseExceptionGroup, ExceptionGroup
 
 
@@ -90,19 +92,35 @@ class InstanceCreation(unittest.TestCase):
         beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
         self.assertIs(type(beg), BaseExceptionGroup)
 
-    def test_EG_subclass_wraps_anything(self):
+    def test_EG_subclass_wraps_non_base_exceptions(self):
         class MyEG(ExceptionGroup):
             pass
 
         self.assertIs(type(MyEG("eg", [ValueError(12), TypeError(42)])), MyEG)
-        self.assertIs(type(MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])), MyEG)
 
-    def test_BEG_subclass_wraps_anything(self):
-        class MyBEG(BaseExceptionGroup):
+    @pytest.mark.skipif(
+        sys.version_info[:3] == (3, 11, 0),
+        reason="Behavior was made stricter in 3.11.1",
+    )
+    def test_EG_subclass_does_not_wrap_base_exceptions(self):
+        class MyEG(ExceptionGroup):
+            pass
+
+        msg = "Cannot nest BaseExceptions in 'MyEG'"
+        with self.assertRaisesRegex(TypeError, msg):
+            MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])
+
+    @pytest.mark.skipif(
+        sys.version_info[:3] == (3, 11, 0),
+        reason="Behavior was made stricter in 3.11.1",
+    )
+    def test_BEG_and_E_subclass_does_not_wrap_base_exceptions(self):
+        class MyEG(BaseExceptionGroup, ValueError):
             pass
 
-        self.assertIs(type(MyBEG("eg", [ValueError(12), TypeError(42)])), MyBEG)
-        self.assertIs(type(MyBEG("eg", [ValueError(12), KeyboardInterrupt(42)])), MyBEG)
+        msg = "Cannot nest BaseExceptions in 'MyEG'"
+        with self.assertRaisesRegex(TypeError, msg):
+            MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])
 
 
 def create_simple_eg():