Skip to content

Commit d7eebae

Browse files
authored
crashhandler: Cast rptdir to Path (ipython#14578)
Previously `self.app.ipython_dir` is a string, which makes `Path.is_dir(<object>)` fail. Note that the argument is `self` i.e. should be a `Path` instance. If `ipython_dir` is `None` then this code would just catch it in the `except:` branch, which makes it be set to `Path.cwd()` anyway.
2 parents a336a98 + 17f17d1 commit d7eebae

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

IPython/core/crashhandler.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@
2424
from pprint import pformat
2525
from pathlib import Path
2626

27+
import builtins as builtin_mod
28+
2729
from IPython.core import ultratb
30+
from IPython.core.application import Application
2831
from IPython.core.release import author_email
2932
from IPython.utils.sysinfo import sys_info
30-
from IPython.utils.py3compat import input
3133

3234
from IPython.core.release import __version__ as version
3335

34-
from typing import Optional
36+
from typing import Optional, Dict
37+
import types
3538

3639
#-----------------------------------------------------------------------------
3740
# Code
@@ -84,7 +87,7 @@
8487
"""
8588

8689

87-
class CrashHandler(object):
90+
class CrashHandler:
8891
"""Customizable crash handlers for IPython applications.
8992
9093
Instances of this class provide a :meth:`__call__` method which can be
@@ -95,10 +98,11 @@ def __call__(self, etype, evalue, etb)
9598

9699
message_template = _default_message_template
97100
section_sep = '\n\n'+'*'*75+'\n\n'
101+
info: Dict[str, Optional[str]]
98102

99103
def __init__(
100104
self,
101-
app,
105+
app: Application,
102106
contact_name: Optional[str] = None,
103107
contact_email: Optional[str] = None,
104108
bug_tracker: Optional[str] = None,
@@ -142,10 +146,14 @@ def __init__(
142146
bug_tracker = bug_tracker,
143147
crash_report_fname = self.crash_report_fname)
144148

145-
146-
def __call__(self, etype, evalue, etb):
149+
def __call__(
150+
self,
151+
etype: type[BaseException],
152+
evalue: BaseException,
153+
etb: types.TracebackType,
154+
) -> None:
147155
"""Handle an exception, call for compatible with sys.excepthook"""
148-
156+
149157
# do not allow the crash handler to be called twice without reinstalling it
150158
# this prevents unlikely errors in the crash handling from entering an
151159
# infinite loop.
@@ -155,21 +163,23 @@ def __call__(self, etype, evalue, etb):
155163
color_scheme = 'NoColor'
156164

157165
# Use this ONLY for developer debugging (keep commented out for release)
158-
#color_scheme = 'Linux' # dbg
159-
try:
160-
rptdir = self.app.ipython_dir
161-
except:
166+
# color_scheme = 'Linux' # dbg
167+
ipython_dir = getattr(self.app, "ipython_dir", None)
168+
if ipython_dir is not None:
169+
assert isinstance(ipython_dir, str)
170+
rptdir = Path(ipython_dir)
171+
else:
162172
rptdir = Path.cwd()
163-
if rptdir is None or not Path.is_dir(rptdir):
173+
if not rptdir.is_dir():
164174
rptdir = Path.cwd()
165175
report_name = rptdir / self.crash_report_fname
166176
# write the report filename into the instance dict so it can get
167177
# properly expanded out in the user message template
168-
self.crash_report_fname = report_name
169-
self.info['crash_report_fname'] = report_name
178+
self.crash_report_fname = str(report_name)
179+
self.info["crash_report_fname"] = str(report_name)
170180
TBhandler = ultratb.VerboseTB(
171181
color_scheme=color_scheme,
172-
long_header=1,
182+
long_header=True,
173183
call_pdb=self.call_pdb,
174184
)
175185
if self.call_pdb:
@@ -195,11 +205,11 @@ def __call__(self, etype, evalue, etb):
195205
print(self.message_template.format(**self.info), file=sys.stderr)
196206

197207
# Construct report on disk
198-
report.write(self.make_report(traceback))
208+
report.write(self.make_report(str(traceback)))
199209

200-
input("Hit <Enter> to quit (your terminal may close):")
210+
builtin_mod.input("Hit <Enter> to quit (your terminal may close):")
201211

202-
def make_report(self,traceback):
212+
def make_report(self, traceback: str) -> str:
203213
"""Return a string containing a crash report."""
204214

205215
sec_sep = self.section_sep
@@ -211,8 +221,8 @@ def make_report(self,traceback):
211221
try:
212222
config = pformat(self.app.config)
213223
rpt_add(sec_sep)
214-
rpt_add('Application name: %s\n\n' % self.app_name)
215-
rpt_add('Current user configuration structure:\n\n')
224+
rpt_add("Application name: %s\n\n" % self.app.name)
225+
rpt_add("Current user configuration structure:\n\n")
216226
rpt_add(config)
217227
except:
218228
pass
@@ -221,7 +231,9 @@ def make_report(self,traceback):
221231
return ''.join(report)
222232

223233

224-
def crash_handler_lite(etype, evalue, tb):
234+
def crash_handler_lite(
235+
etype: type[BaseException], evalue: BaseException, tb: types.TracebackType
236+
) -> None:
225237
"""a light excepthook, adding a small message to the usual traceback"""
226238
traceback.print_exception(etype, evalue, tb)
227239

IPython/utils/sysinfo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def get_sys_info() -> dict:
9999
path = Path(__file__, "..").resolve().parent
100100
return pkg_info(str(path))
101101

102-
def sys_info():
102+
def sys_info() -> str:
103103
"""Return useful information about IPython and the system, as a string.
104104
105105
Examples

pyproject.toml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,27 @@ exclude = [
137137
'IPython/utils/_process_win32.py',
138138
'IPython/utils/path.py',
139139
]
140-
disallow_untyped_defs = true
140+
# check_untyped_defs = true
141+
# disallow_untyped_calls = true
142+
# disallow_untyped_decorators = true
141143
# ignore_errors = false
142144
# ignore_missing_imports = false
143-
# disallow_untyped_calls = true
144145
disallow_incomplete_defs = true
145-
# check_untyped_defs = true
146-
# disallow_untyped_decorators = true
146+
disallow_untyped_defs = true
147147
warn_redundant_casts = true
148148

149+
[[tool.mypy.overrides]]
150+
module = [
151+
"IPython.core.crashhandler",
152+
]
153+
check_untyped_defs = true
154+
disallow_incomplete_defs = true
155+
disallow_untyped_calls = true
156+
disallow_untyped_decorators = true
157+
disallow_untyped_defs = true
158+
ignore_errors = false
159+
ignore_missing_imports = false
160+
149161
[[tool.mypy.overrides]]
150162
module = [
151163
"IPython.utils.text",
@@ -165,6 +177,7 @@ disallow_incomplete_defs = false
165177
check_untyped_defs = false
166178
disallow_untyped_decorators = false
167179

180+
168181
# gloabl ignore error
169182
[[tool.mypy.overrides]]
170183
module = [
@@ -177,7 +190,6 @@ module = [
177190
"IPython.core.compilerop",
178191
"IPython.core.completer",
179192
"IPython.core.completerlib",
180-
"IPython.core.crashhandler",
181193
"IPython.core.debugger",
182194
"IPython.core.display",
183195
"IPython.core.display_functions",

0 commit comments

Comments
 (0)