[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Jelle Zijlstra


New submission from Jelle Zijlstra :

With Irit's recent changes (bpo-45711), the (typ, exc, tb) tuple is now always 
redundant with just exc. As a result, `__exit__` methods now should only need 
to accept a single argument. If we were designing the context manager protocol 
from scratch, we could do:

class CM:
def __enter__(self):
return self
def __exit__(self, exc: BaseException | None, /):
if exc is not None:
   print("an exception occurred")

Instead of the current cumbersome three-parameter `__exit__`.

But we're not designing it from scratch, and we need to deal with lots of 
existing code with three-parameter `__exit__` methods.

One possible decision is that we keep the existing signature, because the cost 
of changing it is too high. However, this would needlessly complicate learning 
Python for all future new users.

Here's a possible migration approach:
- When the interpreter encounters a `with` statement, it does `getattr(cm, 
"__enable_single_parameter_exit__", False)` on the context manager. If this 
attribute exists and is truthy, `__exit__` is called with a single parameter; 
otherwise we keep the current behavior.
- After a few releases, we flip the default, so you have to explicitly set 
`__enable_single_parameter_exit__ = False` to keep three-parameter `__exit__`. 
Libraries that still wish to support Python 3.10 and older can use this.
- Eventually, after Python 3.10 reaches EOL, we always use one-parameter 
`__exit__`.

To help the migration, we can do a few things:
- Linters and type checkers can check for discrepancies in the __exit__ 
signature.
- In the interpreter, we can provide a custom error message if the number of 
parameters to `__exit__` is not as expected, nudging the user towards setting 
`__enable_single_parameter_exit__`.
- In the compiler, we can likely warn if a class body contains three-parameter 
`__exit__` but doesn't set `__enable_single_parameter_exit__ = False`, or 
similar discrepancies.

Everything here should apply equally to `__aexit__`.

This will require a PEP if implemented, but I want to first see whether other 
people think this is worth pursuing at all.

--
messages: 410210
nosy: Jelle Zijlstra, iritkatriel
priority: normal
severity: normal
status: open
title: Simplify the signature of __exit__

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Irit Katriel


Irit Katriel  added the comment:

I've outlined a different approach here:
https://gist.github.com/iritkatriel/3927147548b10a7929cb0b680e3adc52

Basically, to add introspection capabilities in the C API so that the 
interpreter can find out whether __exit__ expects one or three args.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Jelle Zijlstra


Jelle Zijlstra  added the comment:

Thanks, that would work in normal cases but can cause issues if __exit__ takes 
*args. Still, that may be enough of an edge case that we can get it to work.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Irit Katriel


Irit Katriel  added the comment:

If it takes *args we should assume that it expects the triplet rather than a 
single exception.  It's not an edge case, it's very common to write __exit__ 
like that.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

Implementation and transition issues aside, I like this idea.  People can 
mostly just use isinstance() checks to match one or more exception types.  
Also, the single argument form would work well with structural pattern matching:

def __exit__(self, exc):
match exc:
case IOError():
...

That said, there will be some cases that are worse off.  If the code actually 
needs "exctype", perhaps for logging or for an exact match, then the new single 
argument form will just shift complexity away from the signature and into the 
main body of the code.  This may be the common case.  During code reviews, I 
see the "exctype" argument used more frequently than "excinst".

--
nosy: +rhettinger

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-10 Thread Alex Waygood


Change by Alex Waygood :


--
nosy: +AlexWaygood

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46330] Simplify the signature of __exit__

2022-01-11 Thread Barry A. Warsaw


Change by Barry A. Warsaw :


--
nosy: +barry

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com