Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/terminal/ipapp.py: 57%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

150 statements  

1# encoding: utf-8 

2""" 

3The :class:`~traitlets.config.application.Application` object for the command 

4line :command:`ipython` program. 

5""" 

6 

7# Copyright (c) IPython Development Team. 

8# Distributed under the terms of the Modified BSD License. 

9 

10 

11import logging 

12import os 

13import sys 

14import warnings 

15 

16from traitlets.config.loader import Config 

17from traitlets.config.application import boolean_flag, catch_config_error 

18from IPython.core import release 

19from IPython.core import usage 

20from IPython.core.completer import IPCompleter 

21from IPython.core.crashhandler import CrashHandler 

22from IPython.core.formatters import PlainTextFormatter 

23from IPython.core.history import HistoryManager 

24from IPython.core.application import ( 

25 ProfileDir, BaseIPythonApplication, base_flags, base_aliases 

26) 

27from IPython.core.magic import MagicsManager 

28from IPython.core.magics import ( 

29 ScriptMagics, LoggingMagics 

30) 

31from IPython.core.shellapp import ( 

32 InteractiveShellApp, shell_flags, shell_aliases 

33) 

34from IPython.extensions.storemagic import StoreMagics 

35from .interactiveshell import TerminalInteractiveShell 

36from IPython.paths import get_ipython_dir 

37from traitlets import ( 

38 Bool, List, default, observe, Type 

39) 

40 

41#----------------------------------------------------------------------------- 

42# Globals, utilities and helpers 

43#----------------------------------------------------------------------------- 

44 

45_examples = """ 

46ipython --matplotlib # enable matplotlib integration 

47ipython --matplotlib=qt # enable matplotlib integration with qt4 backend 

48 

49ipython --log-level=DEBUG # set logging to DEBUG 

50ipython --profile=foo # start with profile foo 

51 

52ipython profile create foo # create profile foo w/ default config files 

53ipython help profile # show the help for the profile subcmd 

54 

55ipython locate # print the path to the IPython directory 

56ipython locate profile foo # print the path to the directory for profile `foo` 

57""" 

58 

59#----------------------------------------------------------------------------- 

60# Crash handler for this application 

61#----------------------------------------------------------------------------- 

62 

63class IPAppCrashHandler(CrashHandler): 

64 """sys.excepthook for IPython itself, leaves a detailed report on disk.""" 

65 

66 def __init__(self, app): 

67 contact_name = release.author 

68 contact_email = release.author_email 

69 bug_tracker = 'https://github.com/ipython/ipython/issues' 

70 super(IPAppCrashHandler,self).__init__( 

71 app, contact_name, contact_email, bug_tracker 

72 ) 

73 

74 def make_report(self,traceback): 

75 """Return a string containing a crash report.""" 

76 

77 sec_sep = self.section_sep 

78 # Start with parent report 

79 report = [super(IPAppCrashHandler, self).make_report(traceback)] 

80 # Add interactive-specific info we may have 

81 rpt_add = report.append 

82 try: 

83 rpt_add(sec_sep+"History of session input:") 

84 for line in self.app.shell.user_ns['_ih']: 

85 rpt_add(line) 

86 rpt_add('\n*** Last line of input (may not be in above history):\n') 

87 rpt_add(self.app.shell._last_input_line+'\n') 

88 except: 

89 pass 

90 

91 return ''.join(report) 

92 

93#----------------------------------------------------------------------------- 

94# Aliases and Flags 

95#----------------------------------------------------------------------------- 

96flags = dict(base_flags) 

97flags.update(shell_flags) 

98frontend_flags = {} 

99addflag = lambda *args: frontend_flags.update(boolean_flag(*args)) 

100addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax', 

101 'Turn on auto editing of files with syntax errors.', 

102 'Turn off auto editing of files with syntax errors.' 

103) 

104addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', 

105 "Force simple minimal prompt using `raw_input`", 

106 "Use a rich interactive prompt with prompt_toolkit", 

107) 

108 

109addflag('banner', 'TerminalIPythonApp.display_banner', 

110 "Display a banner upon starting IPython.", 

111 "Don't display a banner upon starting IPython." 

112) 

113addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit', 

114 """Set to confirm when you try to exit IPython with an EOF (Control-D 

115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', 

116 you can force a direct exit without any confirmation.""", 

117 "Don't prompt the user when exiting." 

118) 

119addflag( 

120 "tip", 

121 "TerminalInteractiveShell.enable_tip", 

122 """Shows a tip when IPython starts.""", 

123 "Don't show tip when IPython starts.", 

124) 

125addflag('term-title', 'TerminalInteractiveShell.term_title', 

126 "Enable auto setting the terminal title.", 

127 "Disable auto setting the terminal title." 

128) 

129classic_config = Config() 

130classic_config.InteractiveShell.cache_size = 0 

131classic_config.PlainTextFormatter.pprint = False 

132classic_config.TerminalInteractiveShell.prompts_class = ( 

133 "IPython.terminal.prompts.ClassicPrompts" 

134) 

135classic_config.InteractiveShell.separate_in = "" 

136classic_config.InteractiveShell.separate_out = "" 

137classic_config.InteractiveShell.separate_out2 = "" 

138classic_config.InteractiveShell.colors = "nocolor" 

139classic_config.InteractiveShell.xmode = "Plain" 

140 

141frontend_flags['classic']=( 

142 classic_config, 

143 "Gives IPython a similar feel to the classic Python prompt." 

144) 

145# # log doesn't make so much sense this way anymore 

146# paa('--log','-l', 

147# action='store_true', dest='InteractiveShell.logstart', 

148# help="Start logging to the default log file (./ipython_log.py).") 

149# 

150# # quick is harder to implement 

151frontend_flags['quick']=( 

152 {'TerminalIPythonApp' : {'quick' : True}}, 

153 "Enable quick startup with no config files." 

154) 

155 

156frontend_flags['i'] = ( 

157 {'TerminalIPythonApp' : {'force_interact' : True}}, 

158 """If running code from the command line, become interactive afterwards. 

159 It is often useful to follow this with `--` to treat remaining flags as 

160 script arguments. 

161 """ 

162) 

163flags.update(frontend_flags) 

164 

165aliases = dict(base_aliases) 

166aliases.update(shell_aliases) # type: ignore[arg-type] 

167 

168#----------------------------------------------------------------------------- 

169# Main classes and functions 

170#----------------------------------------------------------------------------- 

171 

172 

173class LocateIPythonApp(BaseIPythonApplication): 

174 description = """print the path to the IPython dir""" 

175 subcommands = dict( 

176 profile=('IPython.core.profileapp.ProfileLocate', 

177 "print the path to an IPython profile directory", 

178 ), 

179 ) 

180 def start(self): 

181 if self.subapp is not None: 

182 return self.subapp.start() 

183 else: 

184 print(self.ipython_dir) 

185 

186 

187class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): 

188 name = "ipython" 

189 description = usage.cl_usage 

190 crash_handler_class = IPAppCrashHandler # typing: ignore[assignment] 

191 examples = _examples 

192 

193 flags = flags 

194 aliases = aliases 

195 classes = List() 

196 

197 interactive_shell_class = Type( 

198 klass=object, # use default_value otherwise which only allow subclasses. 

199 default_value=TerminalInteractiveShell, 

200 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends" 

201 ).tag(config=True) 

202 

203 @default('classes') 

204 def _classes_default(self): 

205 """This has to be in a method, for TerminalIPythonApp to be available.""" 

206 return [ 

207 InteractiveShellApp, # ShellApp comes before TerminalApp, because 

208 self.__class__, # it will also affect subclasses (e.g. QtConsole) 

209 TerminalInteractiveShell, 

210 HistoryManager, 

211 MagicsManager, 

212 ProfileDir, 

213 PlainTextFormatter, 

214 IPCompleter, 

215 ScriptMagics, 

216 LoggingMagics, 

217 StoreMagics, 

218 ] 

219 

220 subcommands = dict( 

221 profile = ("IPython.core.profileapp.ProfileApp", 

222 "Create and manage IPython profiles." 

223 ), 

224 kernel = ("ipykernel.kernelapp.IPKernelApp", 

225 "Start a kernel without an attached frontend." 

226 ), 

227 locate=('IPython.terminal.ipapp.LocateIPythonApp', 

228 LocateIPythonApp.description 

229 ), 

230 history=('IPython.core.historyapp.HistoryApp', 

231 "Manage the IPython history database." 

232 ), 

233 ) 

234 

235 # *do* autocreate requested profile, but don't create the config file. 

236 auto_create = Bool(True).tag(config=True) 

237 

238 # configurables 

239 quick = Bool(False, 

240 help="""Start IPython quickly by skipping the loading of config files.""" 

241 ).tag(config=True) 

242 @observe('quick') 

243 def _quick_changed(self, change): 

244 if change['new']: 

245 self.load_config_file = lambda *a, **kw: None 

246 

247 display_banner = Bool(True, 

248 help="Whether to display a banner upon starting IPython." 

249 ).tag(config=True) 

250 

251 # if there is code of files to run from the cmd line, don't interact 

252 # unless the --i flag (App.force_interact) is true. 

253 force_interact = Bool(False, 

254 help="""If a command or file is given via the command-line, 

255 e.g. 'ipython foo.py', start an interactive shell after executing the 

256 file or command.""" 

257 ).tag(config=True) 

258 @observe('force_interact') 

259 def _force_interact_changed(self, change): 

260 if change['new']: 

261 self.interact = True 

262 

263 @observe('file_to_run', 'code_to_run', 'module_to_run') 

264 def _file_to_run_changed(self, change): 

265 new = change['new'] 

266 if new: 

267 self.something_to_run = True 

268 if new and not self.force_interact: 

269 self.interact = False 

270 

271 # internal, not-configurable 

272 something_to_run=Bool(False) 

273 

274 @catch_config_error 

275 def initialize(self, argv=None): 

276 """Do actions after construct, but before starting the app.""" 

277 super(TerminalIPythonApp, self).initialize(argv) 

278 if self.subapp is not None: 

279 # don't bother initializing further, starting subapp 

280 return 

281 # print(self.extra_args) 

282 if self.extra_args and not self.something_to_run: 

283 self.file_to_run = self.extra_args[0] 

284 self.init_path() 

285 # create the shell 

286 self.init_shell() 

287 # and draw the banner 

288 self.init_banner() 

289 # Now a variety of things that happen after the banner is printed. 

290 self.init_gui_pylab() 

291 self.init_extensions() 

292 self.init_code() 

293 

294 def init_shell(self): 

295 """initialize the InteractiveShell instance""" 

296 # Create an InteractiveShell instance. 

297 # shell.display_banner should always be False for the terminal 

298 # based app, because we call shell.show_banner() by hand below 

299 # so the banner shows *before* all extension loading stuff. 

300 self.shell = self.interactive_shell_class.instance(parent=self, 

301 profile_dir=self.profile_dir, 

302 ipython_dir=self.ipython_dir, user_ns=self.user_ns) 

303 self.shell.configurables.append(self) 

304 

305 def init_banner(self): 

306 """optionally display the banner""" 

307 if self.display_banner and self.interact: 

308 self.shell.show_banner() 

309 # Make sure there is a space below the banner. 

310 if self.log_level <= logging.INFO: print() 

311 

312 def _pylab_changed(self, name, old, new): 

313 """Replace --pylab='inline' with --pylab='auto'""" 

314 if new == 'inline': 

315 warnings.warn("'inline' not available as pylab backend, " 

316 "using 'auto' instead.") 

317 self.pylab = 'auto' 

318 

319 def start(self): 

320 if self.subapp is not None: 

321 return self.subapp.start() 

322 # perform any prexec steps: 

323 if self.interact: 

324 self.log.debug("Starting IPython's mainloop...") 

325 self.shell.mainloop() 

326 else: 

327 self.log.debug("IPython not interactive...") 

328 self.shell.restore_term_title() 

329 if not self.shell.last_execution_succeeded: 

330 sys.exit(1) 

331 

332def load_default_config(ipython_dir=None): 

333 """Load the default config file from the default ipython_dir. 

334 

335 This is useful for embedded shells. 

336 """ 

337 if ipython_dir is None: 

338 ipython_dir = get_ipython_dir() 

339 

340 profile_dir = os.path.join(ipython_dir, 'profile_default') 

341 app = TerminalIPythonApp() 

342 app.config_file_paths.append(profile_dir) 

343 app.load_config_file() 

344 return app.config 

345 

346launch_new_instance = TerminalIPythonApp.launch_instance