On 28 June 2017 at 06:03, Chris Angelico email@example.com wrote:
On Wed, Jun 28, 2017 at 5:49 AM, Sven R. Kunze firstname.lastname@example.org wrote:
I would agree with you here but this "refactoring principle in Python" doesn't work for control flow.
Just look at "return", "break", "continue" etc. Exceptions are another way of handling control flow. So, this doesn't apply here IMO.
The ability to safely refactor control flow is part of why 'yield from' exists, and why PEP 479 changed how StopIteration bubbles. Local control flow is hard to refactor, but exceptions are global control flow, and most certainly CAN be refactored safely.
And PEP 479 establishes a precedent for how we handle the cases where we decide we don't want a particular exception type to propagate normally: create a boundary on the stack that converts the otherwise ambiguous exception type to RuntimeError.
While generator functions now do that implicitly for StopIteration, and "raise X from Y" lets people write suitable exception handlers themselves, we don't offer an easy way to do it with a context manager (with statement as stack boundary), asynchronous context manager (async with statement as stack boundary), or a function decorator (execution frame as stack boundary).
So while I prefer "contextlib.convert_exception" as the name (rather than the "exception_guard" Steven used in his recipe), I'd definitely be open to a bugs.python.org RFE and a PR against contextlib to add such a construct to Python 3.7.
We'd have a few specific API details to work out (e.g. whether or not to accept arbitrary conversion functions as conversion targets in addition to accepting exception types and iterables of exception types, whether or not to allow "None" as the conversion target to get the same behaviour as "contextlib.suppress"), but I'm already sold on the general concept.
-- Nick Coghlan | email@example.com | Brisbane, Australia