Skip to content

More callables should be usable as Exception Group predicates #105730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
SlaushVunter opened this issue Jun 13, 2023 · 3 comments · Fixed by #106035
Closed

More callables should be usable as Exception Group predicates #105730

SlaushVunter opened this issue Jun 13, 2023 · 3 comments · Fixed by #106035
Labels
3.13 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement

Comments

@SlaushVunter
Copy link

SlaushVunter commented Jun 13, 2023

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

@SlaushVunter SlaushVunter added the type-bug An unexpected behavior, bug, or error label Jun 13, 2023
@sunmy2019
Copy link
Member

@iritkatriel

@iritkatriel iritkatriel added type-feature A feature request or enhancement and removed type-bug An unexpected behavior, bug, or error labels Jun 13, 2023
@iritkatriel
Copy link
Member

Thank you @SlaushVunter for the report. We could make more callables work with split(), but not all of them because that would be ambiguous - an Exception subclass is callable but it is matched by type and not as a predicate. Also, this would be a feature request rather than a bug report because the documentation says function, not callable. This means that it can only be changed in version 3.13.

That said, I don't think the code you provided above is a good motivating example for this. Iterating over leaf exceptions of an exception group like this gives you the leaf exceptions with truncated tracebacks (too see how to do this, look at the leaf_generator function in https://peps.python.org/pep-0654/#handling-exception-groups).

I would probably just split on some condition, log the matching subgroup (as a whole group) and then raise the non-matching part. The traceback of an exception group contains all the traceback information, laid out in a structured and concise manner.

@iritkatriel iritkatriel added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Jun 13, 2023
@iritkatriel iritkatriel added the 3.13 bugs and security fixes label Jun 21, 2023
@iritkatriel iritkatriel changed the title All callables should be usable as Exception Group predicates More callables should be usable as Exception Group predicates Jun 23, 2023
iritkatriel added a commit to iritkatriel/cpython that referenced this issue Jun 23, 2023
@SlaushVunter
Copy link
Author

Thank you for the quick reply, and the quick fix! And sorry for my late answer.

My example was the result of a simplification. In my original example I did not want to log the traceback for the matched leaf exceptions (communication errors), because they are not needed, the error message is enough. Anyway thank you for your suggestion also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants