You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
logging.StreamHandler.stream is sys.stderr by default ; "SupportsWrite['str']" is too narrow #5680
This is a tradeoff. SupportsWrite[str] is the only thing needed by the implementation of StreamHandler and users are free to use any stream that fulfills this protocol. Therefore using any other method from a stream is potentially unsafe (although it's not in practice of setStream() is never used.
I was deliberating whether to make StreamHandler generic over the stream. I refrained from it, because in theory setStream() could change the type of stream. But it's probably the best solution.
because in theory setStream() could change the type of stream.
I agree that this is a good use case for an invariant TypeVar, since this is the same situation as with lists. For example, list_of_strings.append(None) can change the type of a list, similarly to textiowrapper_handler.setStream(io.StringIO()).
@srittau How does typehint the class now with this change?
❯ py
Python 3.10.1 (main, Dec 9 2021, 07:52:48) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from logging import StreamHandler
>>> StreamHandler[str]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
h: StreamHandler[MyProto] =StreamHandler()
This only works if the annotation is not evaluated 🤔
You could also submit a PR to CPython to add __class_getitem__ to StreamHandler. Previous PRs along those lines have been accepted, e.g. python/cpython#28714
In cases others did not notice it, the stream attribute of logging.StreamHandler is not part of the official API, so in my case we track stream separately, removing the issue.
Activity
srittau commentedon Jun 23, 2021
This is a tradeoff.
SupportsWrite[str]is the only thing needed by the implementation ofStreamHandlerand users are free to use any stream that fulfills this protocol. Therefore using any other method from a stream is potentially unsafe (although it's not in practice ofsetStream()is never used.I was deliberating whether to make
StreamHandlergeneric over the stream. I refrained from it, because in theorysetStream()could change the type of stream. But it's probably the best solution.Make logging.StreamHandler generic over stream
Make logging.StreamHandler generic over stream (#5681)
Akuli commentedon Jun 23, 2021
I agree that this is a good use case for an invariant TypeVar, since this is the same situation as with lists. For example,
list_of_strings.append(None)can change the type of a list, similarly totextiowrapper_handler.setStream(io.StringIO()).srittau commentedon Jun 23, 2021
Yes. In theory if someone would do the following, type checkers would warn:
But I think that's a good thing that users need to be explicit about this:
And the following is a bad idea anyway:
gaborbernat commentedon Jan 4, 2022
@srittau How does typehint the class now with this change?
This only works if the annotation is not evaluated 🤔
srittau commentedon Jan 4, 2022
Indeed. You have to either use
from __future__ import annotationsor quote the annotation.gaborbernat commentedon Jan 4, 2022
Sometimes you cannot do that, can we revert this in the meantime? 🤔 E.g. now impossible to write:
🤔 you need to add a type ignore to the inheritance line otherwise mypy will complain that is missing a generic parameter.
srittau commentedon Jan 4, 2022
The ultimate solution is to have defaults for generics (python/typing#307), but for now we unfortunately require
# type: ignore.AlexWaygood commentedon Jan 4, 2022
You could also submit a PR to CPython to add
__class_getitem__toStreamHandler. Previous PRs along those lines have been accepted, e.g. python/cpython#28714gaborbernat commentedon Jan 4, 2022
That wouldn't work for the older Python version though only the latest 3.11 or later 🤔
Akuli commentedon Jan 4, 2022
A bit annoying, but maybe better than making a pull request to CPython or using
# type: ignore:hauntsaninja commentedon Jan 5, 2022
In case it's useful for future reference, this section of the mypy documentation covers ways to work around this class of issue: https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-classes-that-are-generic-in-stubs-but-not-at-runtime
mr-c commentedon Jan 6, 2022
In cases others did not notice it, the
streamattribute oflogging.StreamHandleris not part of the official API, so in my case we trackstreamseparately, removing the issue.AlexWaygood commentedon May 1, 2022
I've opened python/cpython#92129 to add
__class_getitem__tologging.StreamHandlerin 3.11+.(Update: merged!)
vectro commentedon Jan 25, 2023
With this change, how would one type hint
handlerinBecause of the invariant generic, it seems that the only valid type for
handlerisStreamHandler[Any].