Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make IO.name() generic #13624

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Make IO.name() generic #13624

wants to merge 1 commit into from

Conversation

srittau
Copy link
Collaborator

@srittau srittau commented Mar 14, 2025

Cf. #10737

@srittau srittau marked this pull request as draft March 14, 2025 11:19
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: str, errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: str, errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: str, user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: str, user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., *, universal_newlines: Literal[True], startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., *, universal_newlines: Literal[True], startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Literal[True], encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Literal[True], encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[str]
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[Literal[False]] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[Literal[False]] = ..., encoding: None = ..., errors: None = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[bytes]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[Literal[False]] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[Literal[False]] = ..., encoding: None = ..., errors: None = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[bytes]
- src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any], None] = ..., stdout: Union[int, IO[Any], None] = ..., stderr: Union[int, IO[Any], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[Any]
+ src/prefect/cli/shell.py:99: note:     def [AnyStr: (str, bytes)] __init__(self, args: Union[Union[str, bytes, PathLike[str], PathLike[bytes]], Sequence[Union[str, bytes, PathLike[str], PathLike[bytes]]]], bufsize: int = ..., executable: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., stdin: Union[int, IO[Any, str], None] = ..., stdout: Union[int, IO[Any, str], None] = ..., stderr: Union[int, IO[Any, str], None] = ..., preexec_fn: Optional[Callable[[], Any]] = ..., close_fds: bool = ..., shell: bool = ..., cwd: Union[str, bytes, PathLike[str], PathLike[bytes], None] = ..., env: Union[Mapping[bytes, Union[str, bytes, PathLike[str], PathLike[bytes]]], Mapping[str, Union[str, bytes, PathLike[str], PathLike[bytes]]], None] = ..., universal_newlines: Optional[bool] = ..., startupinfo: Optional[Any] = ..., creationflags: int = ..., restore_signals: bool = ..., start_new_session: bool = ..., pass_fds: Collection[int] = ..., *, text: Optional[bool] = ..., encoding: Optional[str] = ..., errors: Optional[str] = ..., user: Union[str, int, None] = ..., group: Union[str, int, None] = ..., extra_groups: Optional[Iterable[Union[str, int]]] = ..., umask: int = ...) -> Popen[Any]
- src/prefect/cli/shell.py:106: error: Incompatible types in assignment (expression has type "Callable[[IO[str], list[str]], None]", variable has type "Callable[[IO[str], Callable[[str], None]], None]")  [assignment]
+ src/prefect/cli/shell.py:106: error: Incompatible types in assignment (expression has type "Callable[[IO[str, str], list[str]], None]", variable has type "Callable[[IO[str, str], Callable[[str], None]], None]")  [assignment]

pytest-robotframework (https://github.com/detachhead/pytest-robotframework)
- pytest_robotframework/_internal/pytest/plugin.py:448: error: "_RedirectStream[IO[str]]" has no attribute "_stream"  [attr-defined]
+ pytest_robotframework/_internal/pytest/plugin.py:448: error: "_RedirectStream[IO[str, str]]" has no attribute "_stream"  [attr-defined]

werkzeug (https://github.com/pallets/werkzeug)
- tests/test_wsgi.py:261: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:261: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:265: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:265: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:270: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:270: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:274: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:274: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:280: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:280: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:288: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:288: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:297: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:297: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wsgi.py:305: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes]]"  [arg-type]
+ tests/test_wsgi.py:305: error: Argument 1 to "_RangeWrapper" has incompatible type "Union[Iterable[str], Iterable[bytes]]"; expected "Union[Iterable[bytes], IO[bytes, str]]"  [arg-type]
- tests/test_wrappers.py:465: error: Incompatible types in assignment (expression has type "LowercasingStream", variable has type "IO[bytes]")  [assignment]
+ tests/test_wrappers.py:465: error: Incompatible types in assignment (expression has type "LowercasingStream", variable has type "IO[bytes, str]")  [assignment]
- tests/test_test.py:166: error: Item "IO[bytes]" of "Optional[IO[bytes]]" has no attribute "getvalue"  [union-attr]
+ tests/test_test.py:166: error: Item "IO[bytes, str]" of "Optional[IO[bytes, str]]" has no attribute "getvalue"  [union-attr]
- tests/test_test.py:166: error: Item "None" of "Optional[IO[bytes]]" has no attribute "getvalue"  [union-attr]
+ tests/test_test.py:166: error: Item "None" of "Optional[IO[bytes, str]]" has no attribute "getvalue"  [union-attr]
- tests/test_test.py:168: error: Item "IO[bytes]" of "Optional[IO[bytes]]" has no attribute "getvalue"  [union-attr]
+ tests/test_test.py:168: error: Item "IO[bytes, str]" of "Optional[IO[bytes, str]]" has no attribute "getvalue"  [union-attr]
- tests/test_test.py:168: error: Item "None" of "Optional[IO[bytes]]" has no attribute "getvalue"  [union-attr]
+ tests/test_test.py:168: error: Item "None" of "Optional[IO[bytes, str]]" has no attribute "getvalue"  [union-attr]
- tests/test_test.py:438: error: Argument 2 to "add_file" of "FileMultiDict" has incompatible type "SpecialInput"; expected "Union[str, PathLike[str], IO[bytes], FileStorage]"  [arg-type]
+ tests/test_test.py:438: error: Argument 2 to "add_file" of "FileMultiDict" has incompatible type "SpecialInput"; expected "Union[str, PathLike[str], IO[bytes, str], FileStorage]"  [arg-type]
- tests/test_formparser.py:196: error: Non-overlapping equality check (left operand type: "tuple[IO[bytes], MultiDict[str, str], MultiDict[str, FileStorage]]", right operand type: "tuple[str, MultiDict[Never, Never], MultiDict[Never, Never]]")  [comparison-overlap]
+ tests/test_formparser.py:196: error: Non-overlapping equality check (left operand type: "tuple[IO[bytes, str], MultiDict[str, str], MultiDict[str, FileStorage]]", right operand type: "tuple[str, MultiDict[Never, Never], MultiDict[Never, Never]]")  [comparison-overlap]
- tests/test_formparser.py:196: error: Argument 1 to "parse" of "FormDataParser" has incompatible type "str"; expected "IO[bytes]"  [arg-type]
+ tests/test_formparser.py:196: error: Argument 1 to "parse" of "FormDataParser" has incompatible type "str"; expected "IO[bytes, str]"  [arg-type]

django-stubs (https://github.com/typeddjango/django-stubs)
+ django-stubs/db/models/fields/files.pyi:22: error: Incompatible types in assignment (expression has type "Optional[str]", base class "IO" defined the type as "str")  [assignment]
+ django-stubs/core/files/base.pyi:12: error: Incompatible types in assignment (expression has type "Optional[str]", base class "IO" defined the type as "str")  [assignment]

@srittau srittau added the topic: io I/O related issues label Mar 14, 2025
@srittau
Copy link
Collaborator Author

srittau commented Mar 14, 2025

Primer hits:

  • django-stubs (both hits): name field is annotated as str | None. I think having an explicit override here makes sense, as this is usually not an expected type by code accessing a name property.

This looks much better than I feared. I wish we had "kwonly" type vars, but I still think this is an improvement as it allows use to tighten the types to name fields of other I/O types in future PRs, which could lead to better type safety around this property with its rather unintuitive types.

@srittau srittau marked this pull request as ready for review March 14, 2025 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: io I/O related issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant