On Wed, Mar 3, 2021 at 6:57 PM Paul Moore <p.f.moore@gmail.com> wrote:
Sorry, I keep thinking I've finished and you keep making interesting points :-)

On Wed, 3 Mar 2021 at 17:01, Irit Katriel <iritkatriel@googlemail.com> wrote:

> Raising an ExceptionGroup is an API change.  If you call APIs that say they will raise ExceptionGroups you need to update your code accordingly. If a library doesn't document that it raises ExceptionGroups and then one of those escapes, then that library has a bug. Just like with any other exception type.

In my experience, libraries don't document what exceptions they raise
very well. You can call that a bug, but it's a fact of life, I'm
afraid. The problem here isn't so much that the library code now
raises an exception that it used not to raise, but rather that *the
user hitting Ctrl-C* can now result in a different exception surfacing
in my code than it used to. Libraries don't re-wrap KeyboardInterrupt,
as you pointed out in a previous response, so I can currently write
code that traps KeyboardInterrupt, safe in the knowledge that by doing
so I'll handle that user action properly. But with PEP 654, libraries
might well (indeed, some libraries almost certainly will) start
wrapping KeyboardInterrupt in an exception group. That's a backward
incompatible change from the perspective of my code's interaction with
the user, and I need to re-code my application to deal with it (and
worse still, writing that new code in a way that is portable between
versions is not particularly straightforward).

This is also true for MemoryError, and many other errors. What makes KeyboardInterrupt special?

> For older Pythons you would have to do something like
> except KeyboardInterrupt:
>    ...
> except BaseExceptionGroup:  # some stub type in old versions
>    # inspect the contents
>    # if there's a KeyboardInterrupt do what you need to do
>    # reraise the rest

I'd be inclined to suggest that a complete version of this should be
included in the "Backward compatibility" part of the PEP, as I
honestly don't really know how I'd write that without doing more
research. But such an example would make the KeyboardInterrupt case
seem more important than it is. Maybe if it's framed as "how to write
calling code that's compatible with older versions of Python but still
able to handle called code potentially raising exceptions that you
need to trap as part of a group", that would be a useful general

Or maybe it's not actually something that will be needed that often.
I'm not sure - I'm trying to think in terms of pip, where we can't use
new features in our own code until we drop support for older versions,
but we might potentially rely on a library that uses exception
grouping internally on versions where it's available (and that code
lets those exception groups escape). It feels like a stretch to claim
this is particularly likely, but conversely it's something I can
easily imagine *could* happen...

If a library starts raising ExceptionGroups from version 3.X it should probably do that from a new API so people won't have to worry about it just because they are bumping Python version. So I think the cross-version issue is in the case of "I'm calling a user function and I don't know what it is or what it raises", or the "I just want to write all exceptions to the log and ignore them". So this is the "except Exception" case, which will work.