Skip to content

Modernize type annotations: typing.Optional/Union/List/Dict/Tuple/Type → built-in generics#15291

Open
Carreau wants to merge 8 commits into
mainfrom
claude/type-annotation-modernization-y9tewe
Open

Modernize type annotations: typing.Optional/Union/List/Dict/Tuple/Type → built-in generics#15291
Carreau wants to merge 8 commits into
mainfrom
claude/type-annotation-modernization-y9tewe

Conversation

@Carreau

@Carreau Carreau commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Rebased on main after the run pyupgrade py311--plus on all but IPython/utils/text.py commit (b5119b4), which independently modernized almost everything this PR originally touched. Rather than force the old 27 commits through that history, this PR was rebuilt from scratch on top of current main, keeping only what pyupgrade did not already cover:

  • IPython/utils/text.py and docs/autogen_shortcuts.py — explicitly excluded from the pyupgrade run (the former due to list = property(...) shadowing the builtin), so still needed full Optional/Union/List/Dict/Tuple → built-in modernization + from __future__ import annotations.
  • 17 modules (macro.py, tips.py, autoreload.py, clipboard.py, ptutils.py, skipdoctest.py, data.py, importstring.py, ipstruct.py, sentinel.py, sysinfo.py, terminal.py, displaypub.py, magics/auto.py, magics/basic.py, paths.py, _process_posix.py) that pyupgrade didn't add from __future__ import annotations to.
  • A handful of leftover dotted/nested/bracket-less forms pyupgrade's pattern matching skipped: completer.py (4 Union[...] type aliases + missing annotations on 7 functions), pytest_ipdoctest.py (quoted forward refs + several Optional/Union), interactiveshell.py, history.py, guarded_eval.py, alias.py, terminal/shortcuts/auto_suggest.py.

Bug caught while rebuilding this: the original commits had inserted from __future__ import annotations before the module docstring in 8 files (autoreload.py, ptutils.py, skipdoctest.py, displaypub.py, magics/auto.py, magics/basic.py, paths.py, _process_posix.py). Per the future-statement placement rules, a statement before the docstring demotes it from __doc__ to a no-op expression — silently discarding the module docstring. Fixed by placing the import after the docstring in all cases, and verified ast.get_docstring() still returns non-None for each.

Everything else from the original 27-commit set (~50 files) is now byte-for-byte covered by the pyupgrade commit already on main and was dropped from this PR as redundant.

Test plan

  • python -m pytest tests/ — 1584 passed, 120 skipped, 3 xfailed (full suite)
  • import IPython and direct imports of every touched module succeed
  • ast.get_docstring() verified non-None on the 8 files where the future-import placement bug was fixed

claude added 8 commits July 7, 2026 09:20
…s.py

Replace Optional/Union/List/Dict/Tuple with built-in X | None, X | Y, list[...],
dict[...], tuple[...] and add from __future__ import annotations. These two
files were not touched by the recent pyupgrade py311-plus pass.
…upgrade

tips.py, clipboard.py, data.py, importstring.py, ipstruct.py, sentinel.py,
sysinfo.py, terminal.py were not touched by the pyupgrade py311-plus pass;
add the future import for consistency with the rest of the codebase.
…pub.py typing

Place the future import after each module's docstring (a prior version of
this change placed it before the docstring, which silently discarded
__doc__ for these 8 modules). Also replace displaypub.py's
'import typing as t' / 't.Dict' with the built-in 'dict', the only
remaining bracket-less deprecated typing usage found in these files.
…eter.py

Convert AnyMatcherCompletion/MatcherResult/MatcherAPIv1/Matcher type aliases
from Union[...] to X | Y (pyupgrade left these dotted-assignment forms
untouched). Add missing annotations to get__all__entries, _parse_tokens,
python_func_kw_matches, latex_name_matcher, custom_completer_matcher,
dispatch_custom_completer, and fwd_unicode_matcher.
…eshell.py and history.py

interactiveshell.py: cell_meta: Optional[dict] -> dict | None; drop now-unused
Optional/Tuple imports.
history.py: InOrInOut = typing.Union[str, tuple[str, Optional[str]]] -> str | tuple[str, str | None];
drop now-unused Tuple/Optional imports. pyupgrade's regex-based pass left this
dotted/nested form untouched.
…l.py, auto_suggest.py

alias.py: add from __future__ import annotations; default_aliases() return
type t.List[t.Tuple[str, str]] -> list[tuple[str, str]]; drop the now-unused
'import typing as t'.
guarded_eval.py: MayHaveGetattr = Union[...] -> X | Y (Union import kept,
still used at runtime for an 'origin is Union' check).
auto_suggest.py: Provider = Union[...] -> X | Y | None; drop the now-unused
List/Optional/Union/Tuple typing imports.
Add from __future__ import annotations (placed after the module docstring)
and remove now-unnecessary quotes from forward references, and drop the
now-unused Dict/List/Optional/Tuple/Type/Union typing imports. This file
was not touched by the recent pyupgrade py311-plus pass, though a few of
its Optional/Union usages had already been modernized by an earlier commit.
@Carreau Carreau force-pushed the claude/type-annotation-modernization-y9tewe branch from 4fee11c to 070a727 Compare July 7, 2026 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants