On Mon, Sep 6, 2021 at 9:37 AM Finn Mason <finnjavie...@gmail.com> wrote:
>
> Hello all,
>
> In Python 3.10 and 3.11, exception tracebacks are being greatly improved. I 
> noticed that there's nothing related to a fairly common (in my personal 
> experience) cryptic traceback relating to the `with` statement:
>
> >>> with ContextManager as ctx:
> ...     # do something with `ctx`
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: __enter__

I'm seeing a different message, so it looks like something HAS been improved:

Python 3.11.0a0 (heads/main:ed524b4569, Aug 14 2021, 11:29:01) [GCC
8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import contextlib
>>> with contextlib.ExitStack: ...
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'ABCMeta' object does not support the context manager protocol


> This occurs when one forgets to use a instance of a context manager class and 
> uses the class itself. It's obviously not a very helpful traceback. ("Is it 
> not a context manager?" "Is it the wrong class?") Something like the 
> following would be better.
>
> >>> with ContextManager as ctx:
> ...     # do something with `ctx`
> ...
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: <type Context manager> is not a context manager. Did you mean 
> "with ContextManager()..."?
>
> The actual traceback message should probably be more specific than "<type 
> Context manager> is not a context manager".
> Thoughts?
>

The "did you mean" part depends on or assumes that it can figure out
that calling it would have given a viable context manager. This could
be done by probing whether thing.__enter__ exists, but I'm not sure
that'd be entirely safe. Also, it won't catch those made from
generators:

>>> @contextlib.contextmanager
... def foo(): yield
...
>>> with foo: ...
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object does not support the context manager protocol
>>> with foo(): ...
...
Ellipsis
>>> foo
<function foo at 0x7fdeb0321bc0>


In any case, the biggest advantage (IMO) comes from naming the type,
which will make it easy to distinguish the object from its type.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NGP5LQSRS2XPNHIRBN3O76UGMEB623TW/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to