Fix oinspect TypeError with generic __getattr__ objects; fix test path quoting by Carreau · Pull Request #15237 · ipython/ipython · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
df99255
Fix oinspect TypeError with generic __getattr__ objects; fix test pat…
claude Jun 1, 2026
5d373be
Narrow bare except: clauses in oinspect and interactiveshell
claude Jun 1, 2026
b4a3ffd
Narrow remaining bare except: clauses in oinspect, completer, and page
claude Jun 1, 2026
30867e6
Fix flaky test_hist_file_config; narrow bare except in application/cr…
claude Jun 1, 2026
4b6b677
Narrow remaining bare except: in oinspect and shellapp
claude Jun 1, 2026
eaa176e
min_elide=0 disables path elision; narrow 3 interactiveshell bare exc…
claude Jun 1, 2026
356f98c
Rewrite test_ptutils.py using @pytest.mark.parametrize
claude Jun 2, 2026
4e246c8
Narrow bare except: clauses across magics, tbtools, utils, and lib
claude Jun 2, 2026
bf3f518
Narrow bare except: in autoreload, backgroundjobs, and path utils
claude Jun 2, 2026
e01b757
Complete bare except: elimination across remaining IPython modules
claude Jun 2, 2026
23bd6a0
Add missing type annotations to completer.py public/module-level func…
claude Jun 2, 2026
c57be4e
Remove no-op expandtabs() in oinspect string_form truncation; add test
claude Jun 2, 2026
dfad8b5
Add tests for IPython.core.display_functions (previously untested)
claude Jun 2, 2026
539f97c
Fix macro.py: add __setstate__, improve TypeError msg, add type hints…
claude Jun 2, 2026
be7aeb5
Fix timing.py assert→ValueError; add tests for error.py and timing.py
claude Jun 2, 2026
2b5665d
Remove dead _builtins_added flag from builtin_trap.py; add contexts t…
claude Jun 2, 2026
de71eed
Add tests for encoding.py and syspathcontext.py (both previously unte…
claude Jun 2, 2026
0d7d6a3
Add tests for sentinel.py and strdispatch.py (both previously untested)
claude Jun 2, 2026
dc3a208
Add tests for display_trap.py and payload.py (both previously untested)
claude Jun 2, 2026
418224b
Fix copy-paste comment in display_trap.py; add tests for data utils
claude Jun 2, 2026
aa0e7ae
Add type annotations to builtin_trap/hooks; expand hook tests to 11
claude Jun 2, 2026
22b7550
Modernize py3compat/logger; add 25 unit tests for Logger
claude Jun 2, 2026
696145f
Modernize type annotations in capture.py and compilerop.py
claude Jun 2, 2026
609e551
Modernize typing imports in tempdir, profiledir, lib/display
claude Jun 2, 2026
3d5bf7f
Modernize typing imports in tbtools.py and inputtransformer2.py
claude Jun 2, 2026
58a2a8c
Modernize typing imports in doctb and crashhandler
claude Jun 2, 2026
a68af5d
Modernize typing annotations in terminal/shortcuts/__init__ and filters
claude Jun 2, 2026
6399690
Modernize typing imports in ultratb.py and testing/tools.py
claude Jun 2, 2026
ead2313
Modernize typing annotations in utils/text.py
claude Jun 2, 2026
a46f023
Modernize typing annotations in magics, terminal, and testing files
claude Jun 2, 2026
50cf2a5
Modernize type annotations: replace deprecated typing imports with bu…
claude Jun 2, 2026
1db64ac
Modernize typing annotations in core/interactiveshell.py
claude Jun 2, 2026
cd7d323
Modernize typing annotations in external, sphinxext, terminal files
claude Jun 2, 2026
0668dda
Modernize typing in PyColorize.py: Type[Style] → type[Style]
claude Jun 5, 2026
fc3cd55
Add tests for ipstruct.Struct, frame utilities, and generics dispatch
claude Jun 5, 2026
752dddb
Remove trailing whitespace across 28 files (W293/W291)
claude Jun 5, 2026
3475563
Modernize typing in oinspect.py and embed.py
claude Jun 5, 2026
792f5ce
Remove remaining deprecated typing constructs from 5 files
claude Jun 5, 2026
9cd0287
Fix mypy error in history.py: restore traitlets List annotation
claude Jun 5, 2026
de1c6dd
Add parametrized tests for IPython.utils.py3compat
claude Jun 5, 2026
61864a7
Fix test_frame: use Mapping instead of dict for f.f_locals check
claude Jun 5, 2026
d54c5b3
Add tests for utils.terminal and utils.py3compat
claude Jun 5, 2026
f2ec799
Add parametrized tests for text utility functions
claude Jun 5, 2026
8876d08
Expand tests for importstring and text utility functions
claude Jun 5, 2026
733ce30
Expand sysinfo tests with parametrized key checks
claude Jun 5, 2026
0863961
Add from __future__ import annotations to 5 utils modules
claude Jun 5, 2026
745bb3c
Add from __future__ import annotations to 6 core modules
claude Jun 5, 2026
f41ab6d
Add from __future__ import annotations to 3 lib modules
claude Jun 5, 2026
935ac29
Add from __future__ import annotations to magic_arguments.py
claude Jun 5, 2026
0311094
Add from __future__ import annotations to 3 more utils modules
claude Jun 5, 2026
c25281f
Add from __future__ import annotations to pylabtools.py
claude Jun 5, 2026
c27ebf8
Modernize type annotations in completer.py: Optional -> X | None, Uni…
claude Jun 5, 2026
a7a0edb
Modernize type annotations in guarded_eval.py
claude Jun 5, 2026
83c0579
Modernize type annotations in pytest_ipdoctest.py
claude Jun 5, 2026
d6f7369
Add from __future__ import annotations to additional modules
claude Jun 5, 2026
f3b5b7c
Fix Tee.__del__ AttributeError and modernize test_io.py
claude Jun 5, 2026
2251661
Modernize test_tools.py: fix assertions, add parametrize, use plain p…
claude Jun 5, 2026
6f99e5b
Modernize test_compilerop.py with parametrize; add __future__ to _pro…
claude Jun 5, 2026
e918ac3
tests: convert test_events.py to pytest fixtures
claude Jun 5, 2026
65db6ef
tests: convert test_wildcard.py to pytest with parametrize
claude Jun 5, 2026
6ace84e
tests: convert test_completerlib.py to pytest with fixtures and param…
claude Jun 5, 2026
6824a41
refactor: modernize shellapp.py and convert test_path.py to pytest
claude Jun 5, 2026
5f615a7
tests: convert test_pretty.py TestsPretty to pytest with parametrize
claude Jun 5, 2026
0d959a6
tests: modernize test_display.py - replace self.assertRaises with pyt…
claude Jun 5, 2026
9791f7e
tests: parametrize test_inputtransformer2_line.py transformer tests
claude Jun 5, 2026
4d1c086
refactor: modernize docs/autogen_shortcuts.py annotations
claude Jun 5, 2026
acd1d1e
tests: parametrize more test loops in oinspect and inputtransformer2
claude Jun 5, 2026
daa4efe
tests: parametrize test_pylabtools.py figure format and backend tests
claude Jun 5, 2026
9823c39
tests: convert test_interactivshell.py to plain pytest functions
claude Jun 5, 2026
d79ce93
tests: convert TestMagicRunWithPackage to pytest fixture and parametrize
claude Jun 5, 2026
d6a6256
tests/test_ultratb.py: remove unittest.TestCase, use pytest fixtures …
claude Jun 5, 2026
3a524cd
tests/test_shellapp.py: remove unittest.TestCase, use pytest fixture
claude Jun 5, 2026
32b978c
tests/test_interactiveshell.py: convert TestCase classes to pytest
claude Jun 5, 2026
4997fc9
tests: fix test_naked_string_cells cross-test pollution + convert mor…
claude Jun 5, 2026
a0b994f
Convert test_async_helpers.py and test_magic_terminal.py to plain pytest
claude Jun 5, 2026
bcb8f23
Convert test_magic.py, test_profile.py, test_display.py to plain pytest
claude Jun 5, 2026
471b0b7
Convert test_zzz_autoreload.py to plain pytest
claude Jun 5, 2026
1fc0b93
Convert test_completer.py and test_deduperreload.py to plain pytest
claude Jun 5, 2026
e84934c
Convert test_run.py and test_magic.py TestXdel to plain pytest
claude Jun 5, 2026
1ef6eff
Use @pytest.mark.parametrize to consolidate duplicate test cases
claude Jun 5, 2026
bdff661
Use @pytest.mark.parametrize in test_completer.py
claude Jun 5, 2026
72ea14a
Use @pytest.mark.parametrize for test_script_defaults in test_magic.py
claude Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion IPython/__init__.py
9 changes: 4 additions & 5 deletions IPython/core/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Fernando Perez
* Brian Granger
"""
from __future__ import annotations

#-----------------------------------------------------------------------------
# Copyright (C) 2008-2011 The IPython Development Team
Expand All @@ -30,8 +31,6 @@
from traitlets import List, Instance
from logging import error

import typing as t


#-----------------------------------------------------------------------------
# Utilities
Expand All @@ -40,7 +39,7 @@
# This is used as the pattern for calls to split_user_input.
shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')

def default_aliases() -> t.List[t.Tuple[str, str]]:
def default_aliases() -> list[tuple[str, str]]:
"""Return list of shell aliases to auto-define.
"""
# Note: the aliases defined here should be safe to use on a kernel
Expand Down Expand Up @@ -156,7 +155,7 @@ def validate(self):
"got: %r" % self.cmd)

nargs = self.cmd.count('%s') - self.cmd.count('%%s')

if (nargs > 0) and (self.cmd.find('%l') >= 0):
raise InvalidAliasError('The %s and %l specifiers are mutually '
'exclusive in alias definitions.')
Expand All @@ -173,7 +172,7 @@ def __call__(self, rest=''):
if cmd.find('%l') >= 0:
cmd = cmd.replace('%l', rest)
rest = ''

if nargs==0:
if cmd.find('%%s') >= 1:
cmd = cmd.replace('%%s', '%s')
Expand Down
22 changes: 11 additions & 11 deletions IPython/core/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class BaseIPythonApplication(Application):
aliases = base_aliases
flags = base_flags
classes = List([ProfileDir])

# enable `load_subconfig('cfg.py', profile='name')`
python_config_loader_class = ProfileAwareConfigLoader

Expand All @@ -152,15 +152,15 @@ def _config_file_name_changed(self, change):
builtin_profile_dir = Unicode(
os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
)

config_file_paths = List(Unicode())
@default('config_file_paths')
def _config_file_paths_default(self):
return []

extra_config_file = Unicode(
help="""Path to an extra config file to load.

If specified, load this config file in addition to any other IPython config.
""").tag(config=True)
@observe('extra_config_file')
Expand All @@ -177,7 +177,7 @@ def _extra_config_file_changed(self, change):
profile = Unicode(u'default',
help="""The IPython profile to use."""
).tag(config=True)

@observe('profile')
def _profile_changed(self, change):
self.builtin_profile_dir = os.path.join(
Expand Down Expand Up @@ -212,7 +212,7 @@ def _ipython_dir_default(self):
'new': d,
})
return d

_in_init_profile_dir = False

profile_dir = Instance(ProfileDir, allow_none=True)
Expand Down Expand Up @@ -246,7 +246,7 @@ def _config_files_default(self):
profile, then they will be staged into the new directory. Otherwise,
default config files will be automatically generated.
""").tag(config=True)

verbose_crash = Bool(False,
help="""Create a massive crash report when IPython encounters what may be an
internal error. The default is to append a short message to the
Expand All @@ -261,30 +261,30 @@ def __init__(self, **kwargs):
# ensure current working directory exists
try:
os.getcwd()
except:
except OSError:
# exit if cwd doesn't exist
self.log.error("Current working directory doesn't exist.")
self.exit(1)

#-------------------------------------------------------------------------
# Various stages of Application creation
#-------------------------------------------------------------------------

def init_crash_handler(self):
"""Create a crash handler, typically setting sys.excepthook to it."""
self.crash_handler = self.crash_handler_class(self)
sys.excepthook = self.excepthook
def unset_crashhandler():
sys.excepthook = sys.__excepthook__
atexit.register(unset_crashhandler)

def excepthook(self, etype, evalue, tb):
"""this is sys.excepthook after init_crashhandler

set self.verbose_crash=True to use our full crashhandler, instead of
a regular traceback with a short message (crash_handler_lite)
"""

if self.verbose_crash:
return self.crash_handler(etype, evalue, tb)
else:
Expand Down Expand Up @@ -355,7 +355,7 @@ def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
pass
if suppress_errors is not None:
Application.raise_config_file_errors = old_value

for config_file_name in self.config_files:
if not config_file_name or config_file_name == base_config:
continue
Expand Down
1 change: 1 addition & 0 deletions IPython/core/async_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
explicitly to actually raise a SyntaxError and stay as close as possible to
Python semantics.
"""
from __future__ import annotations

import ast
import asyncio
Expand Down
10 changes: 5 additions & 5 deletions IPython/core/autocall.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@

class IPyAutocall:
""" Instances of this class are always autocalled

This happens regardless of 'autocall' variable state. Use this to
develop macro-like mechanisms.
"""
_ip = None
rewrite = True
def __init__(self, ip=None):
self._ip = ip

def set_ip(self, ip):
"""Will be used to set _ip point to current ipython instance b/f call

Expand All @@ -52,13 +52,13 @@ class ExitAutocall(IPyAutocall):
"""An autocallable object which will be added to the user namespace so that
exit, exit(), quit or quit() are all valid ways to close the shell."""
rewrite = False

def __call__(self):
self._ip.ask_exit()

class ZMQExitAutocall(ExitAutocall):
"""Exit IPython. Autocallable, so it needn't be explicitly called.

Parameters
----------
keep_kernel : bool
Expand Down
32 changes: 19 additions & 13 deletions IPython/core/builtin_trap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from __future__ import annotations

import builtins as builtin_mod
from typing import Any, TYPE_CHECKING

from traitlets.config.configurable import Configurable

from traitlets import Instance

if TYPE_CHECKING:
from types import TracebackType


class __BuiltinUndefined:
pass
Expand All @@ -29,35 +35,36 @@ class BuiltinTrap(Configurable):
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
allow_none=True)

def __init__(self, shell=None):
def __init__(self, shell: Any = None) -> None:
super(BuiltinTrap, self).__init__(shell=shell, config=None)
self._orig_builtins = {}
self._orig_builtins: dict[str, Any] = {}
# We define this to track if a single BuiltinTrap is nested.
# Only turn off the trap when the outermost call to __exit__ is made.
self._nested_level = 0
self.shell = shell
# builtins we always add - if set to HideBuiltin, they will just
# be removed instead of being replaced by something else
self.auto_builtins = {'exit': HideBuiltin,
'quit': HideBuiltin,
'get_ipython': self.shell.get_ipython,
}
self.auto_builtins: dict[str, Any] = {
'exit': HideBuiltin,
'quit': HideBuiltin,
'get_ipython': self.shell.get_ipython,
}

def __enter__(self):
def __enter__(self) -> BuiltinTrap:
if self._nested_level == 0:
self.activate()
self._nested_level += 1
# I return self, so callers can use add_builtin in a with clause.
return self

def __exit__(self, type, value, traceback):
def __exit__(self, type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None) -> bool:
if self._nested_level == 1:
self.deactivate()
self._nested_level -= 1
# Returning False will cause exceptions to propagate
return False

def add_builtin(self, key, value):
def add_builtin(self, key: str, value: Any) -> None:
"""Add a builtin and save the original."""
bdict = builtin_mod.__dict__
orig = bdict.get(key, BuiltinUndefined)
Expand All @@ -69,25 +76,24 @@ def add_builtin(self, key, value):
self._orig_builtins[key] = orig
bdict[key] = value

def remove_builtin(self, key, orig):
def remove_builtin(self, key: str, orig: Any) -> None:
"""Remove an added builtin and re-set the original."""
if orig is BuiltinUndefined:
del builtin_mod.__dict__[key]
else:
builtin_mod.__dict__[key] = orig

def activate(self):
def activate(self) -> None:
"""Store ipython references in the __builtin__ namespace."""

add_builtin = self.add_builtin
for name, func in self.auto_builtins.items():
add_builtin(name, func)

def deactivate(self):
def deactivate(self) -> None:
"""Remove any builtins which might have been added by add_builtins, or
restore overwritten ones to their previous values."""
remove_builtin = self.remove_builtin
for key, val in self._orig_builtins.items():
remove_builtin(key, val)
self._orig_builtins.clear()
self._builtins_added = False
22 changes: 13 additions & 9 deletions IPython/core/compilerop.py
Loading
Loading