Skip to content

More callables should be usable as Exception Group predicates #105730

Description

@SlaushVunter

Bug report

If a bound method is used as the condition for BaseExceptionGroup.split the following exception is raised:

TypeError: expected a function, exception type or tuple of exception types

Consider the following example:

class HandleError:
    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_inst, exc_tb):
        if exc_type is None:
            return False
        if isinstance(exc_inst, ExceptionGroup):
            match, rest = exc_inst.split(self._log_and_ignore_error)
            if match is None:
                return False
            elif rest is None:
                return True
            raise rest
        else:
            return self._log_and_ignore_error(exc_inst)

    def _log_and_ignore_error(self, e: BaseException) -> bool:
        ...
        return True
    
    
with HandleError():
    raise ExceptionGroup('foo', [ValueError('bar')])

If we replace the bound method with a lambda (lambda e: self._log_and_ignore_error(e)) then no exception is raised.

I think it would be useful to accept any callable here. I guess the code update would be simple too, just replace PyFunction_Check with PyCallable_Check in

    if (PyFunction_Check(value)) {
        *type = EXCEPTION_GROUP_MATCH_BY_PREDICATE;
        return 0;
    }

Update the exception message to allow callables, and change the assert in

    case EXCEPTION_GROUP_MATCH_BY_PREDICATE: {
        assert(PyFunction_Check(matcher_value));
        PyObject *exc_matches = PyObject_CallOneArg(matcher_value, exc);

to call PyCallable_Check again.

Your environment

  • CPython versions tested on: 3.11.2

The c code snippets are from origin/main.

Linked PRs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions