Skip to content

More callables should be usable as Exception Group predicates #105730

@SlaushVunter

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

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