Removed continued parametrization of FilePathOrBuffer
State: closed

follow up to #27598 to simplify things a bit. I think it was a mistake to add `IO[AnyStr]` as `AnyStr` is a TypeVar and not something to actually parametrize with. The source for `IO` already does this:

https://github.com/python/cpython/blob/8990ac0ab0398bfb9c62031288030fe7c630c2c7/Lib/typing.py#L1452

 I'm not sure why mypy doesn't error on this. 

@simonjayhawkins 

Labels:
name: Typing
description: type annotations, mypy/pyright type checking

Comments:
i don't follow why we would want to reduce the strictness of the type checks and miss potential runtime errors

```python
from io import StringIO
from pathlib import Path
from typing import IO, Union

FilePathOrBuffer = Union[str, Path, IO]

reveal_type(FilePathOrBuffer)


def common_function(filepath_or_buf: FilePathOrBuffer) -> FilePathOrBuffer:
    return filepath_or_buf


buf = common_function(StringIO())
reveal_type(buf)

buf.write(b"foo")
```
```
$ mypy notypevar.py
notypevar.py:7: error: Revealed type is 'Any'
notypevar.py:7: error: The type alias to Union is invalid in runtime context
notypevar.py:15: error: Revealed type is 'Union[builtins.str, pathlib.Path, typing.IO[Any]]'
notypevar.py:17: error: Item "str" of "Union[str, Path, IO[Any]]" has no attribute "write"
notypevar.py:17: error: Item "Path" of "Union[str, Path, IO[Any]]" has no attribute "write"
(pandas-dev) 
```

```python
from io import StringIO
from pathlib import Path
from typing import IO, AnyStr, Union

FilePathOrBuffer = Union[str, Path, IO[AnyStr]]

reveal_type(FilePathOrBuffer)


def common_function(
    filepath_or_buf: FilePathOrBuffer[AnyStr]
) -> FilePathOrBuffer[AnyStr]:
    return filepath_or_buf


buf = common_function(StringIO())
reveal_type(buf)

buf.write(b"foo")
```
```
$ mypy typevar.py
typevar.py:7: error: Revealed type is 'Any'
typevar.py:7: error: The type alias to Union is invalid in runtime context
typevar.py:17: error: Revealed type is 'Union[builtins.str, pathlib.Path, typing.IO[builtins.str*]]'
typevar.py:19: error: Item "str" of "Union[str, Path, IO[str]]" has no attribute "write"
typevar.py:19: error: Item "Path" of "Union[str, Path, IO[str]]" has no attribute "write"
typevar.py:19: error: Argument 1 to "write" of "IO" has incompatible type "bytes"; expected "str"
(pandas-dev) 
```

Yea my main motivation here is that I think this only works as is because of potentially buggy Mypy behavior. For instance, this passes type checking:

```python
from typing import TypeVar

T = TypeVar("T", int, str)
X = TypeVar("X", float, dict)  # just picking random types here

def same_thing(obj: T) -> T:
    return obj

same_thing("a")  # passes as expected
same_thing(1)    # passes as expected
same_thing(X)    # passes?
```

Though I think it should fail since it's not parametrizing an int or a str in the last case. Seems like TypeVars (or anything with type `Any`) can be chained without impunity though also without a very obvious indication as to what is going on.

I brought it up on the mypy Gitter so will share any info I have. If it is in fact buggy I think better to just simplify.

Also thanks for the examples! Is there something you can think of in practice that would show up though? Since `FilePathOrBuffer` is a Union the returned type wouldn't match the type of the argument to these functions (noting the failures for `str` and `Path` not having a `write` attribute). I think the additional failure may just be coming from some deep parametrization of `AnyStr` but in a way that is not obvious
an example from typeshed where a alias to a union that includes a generic subscripted with a typevar. The continued use of the alias also includes subscription.

https://github.com/python/typeshed/blob/3c4141982e22aba6966daba5785d1ba959d7fc49/stdlib/3/asyncio/tasks.pyi#L18-L42
Thanks for the example, though I still think that is a more common case and not really intended for IO. In any case I think we always need to consider the complexity and readability of annotations versus incremental benefit. I personally think this current design is less readable and confusing to people not fully invested in annotations, hence the PR

In any case we have a rather large queue at the moment and this isn't a huge priority. Closing for now can come back at a later date