Deprecation cleanup, decorator-dependency removal, and startup-time fixes - #15310
Merged
Conversation
Carreau
force-pushed
the
claude/deprecated-modernization-review-frdfap
branch
from
July 16, 2026 12:46
c1adcf1 to
e1aef2e
Compare
- Import jedi (and parso, which compiles grammars on import) lazily on first completion instead of at IPython import time; this removes ~50ms (warm) from 'import IPython'. JEDI_INSTALLED now uses importlib.util.find_spec, and jedi configuration happens in the new cached _get_jedi() helper. - Hoist regexes compiled inside functions to module level: the snake-case matcher in IPCompleter.global_matches (recompiled on every completion request), two colder completer regexes, and the five format_latex regexes in magic.py. - Replace the class-level @lru_cache(1024) on Pdb._cachable_skip and Pdb._cached_one_parent_frame_debuggerskip with per-instance, size-bounded caches cleared on each interaction. The lru_cache kept every Pdb instance and up to 1024 frames (with their locals and whole back-chains) alive for the lifetime of the process. - Bound the count_lines_in_py_file cache in tbtools (was unbounded, keyed by filename). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GEyCEHEuB6vN85jweKvQU7
…s branch - Rewrite catch_format_error (formatters), only_when_enabled and catch_corrupt_db (history) as plain functools.wraps closures; remove the 'decorator' runtime dependency and the types-decorator stubs from the extras and the mypy CI install. The two history.py decorators are typed as signature-preserving with ParamSpec, matching what the types-decorator stubs gave them, so disallow_untyped_decorators stays clean and every decorated HistoryAccessor method keeps its inferred type. - completer.py: import TypedDict/Protocol/NotRequired/TypeAlias/ TypeGuard from typing unconditionally - all are in the 3.11 stdlib, which is the minimum supported version. typing_extensions remains only for TypeAliasType in guarded_eval on 3.11. - Delete setup.cfg: its [tool.black] section was written in INI syntax that black never reads; move the exclusion to pyproject.toml. - splitinput.py: align the LineInfo.ofind() docstring with the warning (deprecated in 9.9, per the whatsnew entry for #15057). - setupbase.py: drop a stale Python-2-era comment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GEyCEHEuB6vN85jweKvQU7
- IPCompleter.limit_to__all__ config option (deprecated 5.0): completion on object.<tab> now always uses dir()-based discovery. - IPCompleter.python_matches (deprecated 8.27): superseded by python_matcher, and was no longer part of the active matcher set. - OInfo.get() (deprecated 8.13, transitional helper from when OInfo stopped being a dict in 8.12): access dataclass fields directly. - pylabtools module-level backends/backend2gui __getattr__ shim (deprecated 8.24). The underlying dicts remain: they still back the find_gui_and_backend fallback for Matplotlib < 3.9. - run_cell_async/should_run_async now raise TypeError instead of transforming the cell themselves when transformed_cell is not passed (DeprecationWarning since 7.17; ipykernel >= 6 always passes it). run_cell is unaffected. - test_oinspect no longer needs the decorator package: the find_file wrapper-chain tests use functools.wraps, which sets the same __wrapped__ chain. Completer.greedy (deprecated 8.8) was evaluated for removal and kept: downstream projects (pyflyby's test suite, run in this repo's downstream CI) still set it via %config, and removing it makes traitlets print "Config option not recognized", breaking their expected-output tests. The 8.6-era matcher-v1 methods (magic_config_matches, python_func_kw_matches, dict_key_matches, dispatch_custom_completer) were deliberately kept too: they are the implementations their v2 matcher wrappers delegate to. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GEyCEHEuB6vN85jweKvQU7
While investigating making IPython.embed/InteractiveShell/Application lazy top-level attributes (reverted - see below), found a latent cycle inside the terminal package: interactiveshell -> debugger -> embed -> interactiveshell. It only worked because IPython/__init__.py happened to import terminal.embed before anything reached terminal.debugger; removing that ordering constraint made it a real ImportError. terminal/debugger.py now imports terminal.embed inside do_interact, the only place it's used, instead of at module level. The lazy-attribute idea itself doesn't ship here: pyflyby's downstream CI (green on main) broke because its _interactive.py does `import IPython` and then accesses attribute chains like IPython.terminal.ipapp.TerminalIPythonApp and IPython.core.application.BaseIPythonApplication, which only resolve through these imports' transitive side effects (its except AttributeError path turns a missing attribute into a hard RuntimeError, so `py` dies with EOF in their interactive tests). Left a comment explaining the constraint; other downstreams likely have the same pattern. A patch making pyflyby import those submodules explicitly has been prepared for upstream, after which this is worth revisiting - warm import time would drop from ~270ms to ~17ms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GEyCEHEuB6vN85jweKvQU7
Summary of this cleanup batch: the deprecated APIs removed, the modernization changes, and the performance fixes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GEyCEHEuB6vN85jweKvQU7
Carreau
force-pushed
the
claude/deprecated-modernization-review-frdfap
branch
from
July 17, 2026 06:30
e1aef2e to
c694a2d
Compare
Carreau
force-pushed
the
claude/deprecated-modernization-review-frdfap
branch
from
July 17, 2026 07:50
c694a2d to
bd96ba1
Compare
lyskov
pushed a commit
to RosettaCommons/rosetta
that referenced
this pull request
Aug 4, 2026
This PR patches a nascent bug in the `pyrosetta.distributed` required dependencies: `source/src/python/PyRosetta/src/pyrosetta/distributed/utility/log.py` imports the `decorator` package, although it's not explicitly declared as a dependency in either the unit tests or the [`pyrosetta-distributed`](https://www.piwheels.org/project/pyrosetta-distributed/) meta-package. Currently, the PyRosetta unit tests indirectly rely on the `decorator` package to be installed via the `jupyter` -> `ipykernel` -> `ipython` -> `decorator` dependency chain, and `ipython` seems to have removed it as a dependency in their latest 9.16.0 version (see the following PR: ipython/ipython#15310).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deprecation, modernization, and performance cleanup batch for the IPython codebase, in 5 commits (see
docs/modernization_triage_2026-07.md, added by the last commit, for a standalone changelog).Deprecated APIs removed
IPCompleter.limit_to__all__config option (deprecated 5.0)IPCompleter.python_matchesmethod (deprecated 8.27; superseded bypython_matcher, wasn't in the active matcher set)OInfo.get()(deprecated 8.13; a transitional shim from whenOInfostopped being a dict)pylabtools' module-levelbackends/backend2gui__getattr__shim (deprecated 8.24)InteractiveShell.run_cell_async/should_run_async's implicittransform_cellfallback (deprecated 7.17; now raisesTypeErrorinstead of silently transforming;run_cellitself is unaffected)Completer.greedy(deprecated 8.8) is kept: pyflyby's test suite, exercised by this repo's downstream CI, still sets it via%config, and removing it breaks their expected-output tests on an unrecognized-option warning.Modernization
decoratorruntime dependency (andtypes-decoratorstub package): the three uses informatters.py/history.pyare rewritten as plainfunctools.wrapsclosures, typed withParamSpecso they stay signature-preserving under mypy'sdisallow_untyped_decorators.typing_extensionsconditional import incompleter.py— everything it imported is in the 3.11 stdlib, which is the minimum supported version.setup.cfg(its[tool.black]section was in INI syntax, which black never reads); move the exclusion intopyproject.toml.Performance
jedi(andparso, which compiles grammars on import) lazily on first completion instead of atIPythonimport time.IPCompleter.global_matches,Magics.format_latex) to module level.Pdb._cachable_skip/_cached_one_parent_frame_debuggerskipused a class-level@lru_cache(1024)keyed by frame objects, which kept everyPdbinstance and up to 1024 frames (with their locals and back-chains) alive for the process lifetime. Now per-instance, size-bounded, cleared on eachinteraction.count_lines_in_py_filecache intbtools.IPython.terminal(interactiveshell → debugger → embed → interactiveshell):terminal/debugger.pynow importsterminal.embedinsidedo_interact, the only place it's used, instead of at module level.