Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/magics/basic.py: 22%

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

303 statements  

1"""Implementation of basic magic functions.""" 

2from __future__ import annotations 

3 

4 

5from logging import error 

6import io 

7import os 

8import platform 

9from pprint import pformat 

10import sys 

11from warnings import warn 

12 

13from traitlets.utils.importstring import import_item 

14from IPython.core import magic_arguments, page 

15from IPython.core.error import UsageError 

16from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes 

17from IPython.utils.text import format_screen, dedent, indent 

18from IPython.testing.skipdoctest import skip_doctest 

19from IPython.utils.ipstruct import Struct 

20 

21 

22class MagicsDisplay: 

23 def __init__(self, magics_manager, ignore=None): 

24 self.ignore = ignore if ignore else [] 

25 self.magics_manager = magics_manager 

26 

27 def _lsmagic(self): 

28 """The main implementation of the %lsmagic""" 

29 mesc = magic_escapes['line'] 

30 cesc = magic_escapes['cell'] 

31 mman = self.magics_manager 

32 magics = mman.lsmagic() 

33 out = ['Available line magics:', 

34 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])), 

35 '', 

36 'Available cell magics:', 

37 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])), 

38 '', 

39 mman.auto_status()] 

40 return '\n'.join(out) 

41 

42 def _repr_pretty_(self, p, cycle): 

43 p.text(self._lsmagic()) 

44 

45 def __repr__(self): 

46 return self.__str__() 

47 

48 def __str__(self): 

49 return self._lsmagic() 

50 

51 def _jsonable(self): 

52 """turn magics dict into jsonable dict of the same structure 

53 

54 replaces object instances with their class names as strings 

55 """ 

56 magic_dict = {} 

57 mman = self.magics_manager 

58 magics = mman.lsmagic() 

59 for key, subdict in magics.items(): 

60 d = {} 

61 magic_dict[key] = d 

62 for name, obj in subdict.items(): 

63 try: 

64 classname = obj.__self__.__class__.__name__ 

65 except AttributeError: 

66 classname = 'Other' 

67 

68 d[name] = classname 

69 return magic_dict 

70 

71 def _repr_json_(self): 

72 return self._jsonable() 

73 

74 

75@magics_class 

76class BasicMagics(Magics): 

77 """Magics that provide central IPython functionality. 

78 

79 These are various magics that don't fit into specific categories but that 

80 are all part of the base 'IPython experience'.""" 

81 

82 @skip_doctest 

83 @magic_arguments.magic_arguments() 

84 @magic_arguments.argument( 

85 '-l', '--line', action='store_true', 

86 help="""Create a line magic alias.""" 

87 ) 

88 @magic_arguments.argument( 

89 '-c', '--cell', action='store_true', 

90 help="""Create a cell magic alias.""" 

91 ) 

92 @magic_arguments.argument( 

93 'name', 

94 help="""Name of the magic to be created.""" 

95 ) 

96 @magic_arguments.argument( 

97 'target', 

98 help="""Name of the existing line or cell magic.""" 

99 ) 

100 @magic_arguments.argument( 

101 '-p', '--params', default=None, 

102 help="""Parameters passed to the magic function.""" 

103 ) 

104 @line_magic 

105 def alias_magic(self, line=''): 

106 """Create an alias for an existing line or cell magic. 

107 

108 Examples 

109 -------- 

110 :: 

111 

112 In [1]: %alias_magic t timeit 

113 Created `%t` as an alias for `%timeit`. 

114 Created `%%t` as an alias for `%%timeit`. 

115 

116 In [2]: %t -n1 pass 

117 107 ns ± 43.6 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) 

118 

119 In [3]: %%t -n1 

120 ...: pass 

121 ...: 

122 107 ns ± 58.3 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) 

123 

124 In [4]: %alias_magic --cell whereami pwd 

125 UsageError: Cell magic function `%%pwd` not found. 

126 In [5]: %alias_magic --line whereami pwd 

127 Created `%whereami` as an alias for `%pwd`. 

128 

129 In [6]: %whereami 

130 Out[6]: '/home/testuser' 

131 

132 In [7]: %alias_magic h history -p "-l 30" --line 

133 Created `%h` as an alias for `%history -l 30`. 

134 """ 

135 

136 args = magic_arguments.parse_argstring(self.alias_magic, line) 

137 shell = self.shell 

138 mman = self.shell.magics_manager 

139 escs = ''.join(magic_escapes.values()) 

140 

141 target = args.target.lstrip(escs) 

142 name = args.name.lstrip(escs) 

143 

144 params = args.params 

145 if (params and 

146 ((params.startswith('"') and params.endswith('"')) 

147 or (params.startswith("'") and params.endswith("'")))): 

148 params = params[1:-1] 

149 

150 # Find the requested magics. 

151 m_line = shell.find_magic(target, 'line') 

152 m_cell = shell.find_magic(target, 'cell') 

153 if args.line and m_line is None: 

154 raise UsageError('Line magic function `%s%s` not found.' % 

155 (magic_escapes['line'], target)) 

156 if args.cell and m_cell is None: 

157 raise UsageError('Cell magic function `%s%s` not found.' % 

158 (magic_escapes['cell'], target)) 

159 

160 # If --line and --cell are not specified, default to the ones 

161 # that are available. 

162 if not args.line and not args.cell: 

163 if not m_line and not m_cell: 

164 raise UsageError( 

165 'No line or cell magic with name `%s` found.' % target 

166 ) 

167 args.line = bool(m_line) 

168 args.cell = bool(m_cell) 

169 

170 params_str = "" if params is None else " " + params 

171 

172 if args.line: 

173 mman.register_alias(name, target, 'line', params) 

174 print('Created `{}{}` as an alias for `{}{}{}`.'.format( 

175 magic_escapes['line'], name, 

176 magic_escapes['line'], target, params_str)) 

177 

178 if args.cell: 

179 mman.register_alias(name, target, 'cell', params) 

180 print('Created `{}{}` as an alias for `{}{}{}`.'.format( 

181 magic_escapes['cell'], name, 

182 magic_escapes['cell'], target, params_str)) 

183 

184 @magic_arguments.magic_arguments() 

185 @magic_arguments.argument( 

186 "-j", "--json", action="store_true", help="Return the magic list as JSON." 

187 ) 

188 @line_magic 

189 def lsmagic(self, parameter_s=''): 

190 """List currently available magic functions. 

191 

192 Use ``--json`` to return a JSON-compatible dictionary instead of text. 

193 """ 

194 args = magic_arguments.parse_argstring(self.lsmagic, parameter_s) 

195 display = MagicsDisplay(self.shell.magics_manager, ignore=[]) 

196 if args.json: 

197 return display._jsonable() 

198 return str(display) 

199 

200 def _magic_docs(self, brief=False, rest=False): 

201 """Return docstrings from magic functions.""" 

202 mman = self.shell.magics_manager 

203 docs = mman.lsmagic_docs(brief, missing='No documentation') 

204 

205 if rest: 

206 format_string = '**%s%s**::\n\n%s\n\n' 

207 else: 

208 format_string = '%s%s:\n%s\n' 

209 

210 return ''.join( 

211 [format_string % (magic_escapes['line'], fname, 

212 indent(dedent(fndoc))) 

213 for fname, fndoc in sorted(docs['line'].items())] 

214 + 

215 [format_string % (magic_escapes['cell'], fname, 

216 indent(dedent(fndoc))) 

217 for fname, fndoc in sorted(docs['cell'].items())] 

218 ) 

219 

220 @line_magic 

221 def magic(self, parameter_s=''): 

222 """Print information about the magic function system. 

223 

224 Supported formats: -latex, -brief, -rest 

225 """ 

226 

227 mode = '' 

228 try: 

229 mode = parameter_s.split()[0][1:] 

230 except IndexError: 

231 pass 

232 

233 brief = (mode == 'brief') 

234 rest = (mode == 'rest') 

235 magic_docs = self._magic_docs(brief, rest) 

236 

237 if mode == 'latex': 

238 print(self.format_latex(magic_docs)) 

239 return 

240 else: 

241 magic_docs = format_screen(magic_docs) 

242 

243 out = [""" 

244IPython's 'magic' functions 

245=========================== 

246 

247The magic function system provides a series of functions which allow you to 

248control the behavior of IPython itself, plus a lot of system-type 

249features. There are two kinds of magics, line-oriented and cell-oriented. 

250 

251Line magics are prefixed with the % character and work much like OS 

252command-line calls: they get as an argument the rest of the line, where 

253arguments are passed without parentheses or quotes. For example, this will 

254time the given statement:: 

255 

256 %timeit range(1000) 

257 

258Cell magics are prefixed with a double %%, and they are functions that get as 

259an argument not only the rest of the line, but also the lines below it in a 

260separate argument. These magics are called with two arguments: the rest of the 

261call line and the body of the cell, consisting of the lines below the first. 

262For example:: 

263 

264 %%timeit x = numpy.random.randn((100, 100)) 

265 numpy.linalg.svd(x) 

266 

267will time the execution of the numpy svd routine, running the assignment of x 

268as part of the setup phase, which is not timed. 

269 

270In a line-oriented client (the terminal or Qt console IPython), starting a new 

271input with %% will automatically enter cell mode, and IPython will continue 

272reading input until a blank line is given. In the notebook, simply type the 

273whole cell as one entity, but keep in mind that the %% escape can only be at 

274the very start of the cell. 

275 

276NOTE: If you have 'automagic' enabled (via the command line option or with the 

277%automagic function), you don't need to type in the % explicitly for line 

278magics; cell magics always require an explicit '%%' escape. By default, 

279IPython ships with automagic on, so you should only rarely need the % escape. 

280 

281Example: typing '%cd mydir' (without the quotes) changes your working directory 

282to 'mydir', if it exists. 

283 

284For a list of the available magic functions, use %lsmagic. For a description 

285of any of them, type %magic_name?, e.g. '%cd?'. 

286 

287Currently the magic system has the following functions:""", 

288 magic_docs, 

289 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'], 

290 str(self.lsmagic()), 

291 ] 

292 page.page('\n'.join(out)) 

293 

294 

295 @line_magic 

296 def page(self, parameter_s=''): 

297 """Pretty print the object and display it through a pager. 

298 

299 %page [options] OBJECT 

300 

301 If no object is given, use _ (last output). 

302 

303 Options: 

304 

305 -r: page str(object), don't pretty-print it.""" 

306 

307 # After a function contributed by Olivier Aubert, slightly modified. 

308 

309 # Process options/args 

310 opts, args = self.parse_options(parameter_s, 'r') 

311 raw = 'r' in opts 

312 

313 oname = args and args or '_' 

314 info = self.shell._ofind(oname) 

315 if info.found: 

316 if raw: 

317 txt = str(info.obj) 

318 else: 

319 txt = pformat(info.obj) 

320 page.page(txt) 

321 else: 

322 print('Object `%s` not found' % oname) 

323 

324 @line_magic 

325 def pprint(self, parameter_s=''): 

326 """Toggle pretty printing on/off.""" 

327 ptformatter = self.shell.display_formatter.formatters['text/plain'] 

328 ptformatter.pprint = bool(1 - ptformatter.pprint) 

329 print('Pretty printing has been turned', 

330 ['OFF','ON'][ptformatter.pprint]) 

331 

332 @line_magic 

333 def colors(self, parameter_s=''): 

334 """Switch color scheme/theme globally for IPython 

335 

336 Examples 

337 -------- 

338 To get a plain black and white terminal:: 

339 

340 %colors nocolor 

341 """ 

342 

343 

344 new_theme = parameter_s.strip() 

345 if not new_theme: 

346 from IPython.utils.PyColorize import theme_table 

347 

348 raise UsageError( 

349 "%colors: you must specify a color theme. See '%colors?'." 

350 f" Available themes: {list(theme_table.keys())}" 

351 ) 

352 

353 self.shell.colors = new_theme 

354 

355 @line_magic 

356 def xmode(self, parameter_s=''): 

357 """Switch modes for the exception handlers. 

358 

359 Valid modes: Plain, Context, Verbose, Minimal, Docs, and Doctest. 

360 

361 - ``Plain``: similar to Python's default traceback. 

362 - ``Context``: shows several lines of surrounding context for each 

363 frame in the traceback. 

364 - ``Verbose``: like Context, but also displays local variable values 

365 in each frame. 

366 - ``Minimal``: shows only the exception type and message, without 

367 a traceback. 

368 - ``Docs``: a stripped-down version of Verbose, designed for use 

369 when running doctests. 

370 - ``Doctest``: shows only the traceback header, an ellipsis, and the 

371 exception line, for easy copy-paste into Python doctests. 

372 

373 If called without arguments, cycles through the available modes. 

374 

375 When in verbose mode the value ``--show`` (and ``--hide``) 

376 will respectively show (or hide) frames with ``__tracebackhide__ = 

377 True`` value set. 

378 """ 

379 

380 def xmode_switch_err(name): 

381 warn('Error changing %s exception modes.\n%s' % 

382 (name,sys.exc_info()[1])) 

383 

384 shell = self.shell 

385 if parameter_s.strip() == "--show": 

386 shell.InteractiveTB.skip_hidden = False 

387 return 

388 if parameter_s.strip() == "--hide": 

389 shell.InteractiveTB.skip_hidden = True 

390 return 

391 

392 new_mode = parameter_s.strip().capitalize() 

393 try: 

394 shell.InteractiveTB.set_mode(mode=new_mode) 

395 print('Exception reporting mode:',shell.InteractiveTB.mode) 

396 except Exception: 

397 xmode_switch_err('user') 

398 

399 @line_magic 

400 def quickref(self, arg): 

401 """ Show a quick reference sheet """ 

402 from IPython.core.usage import quick_reference 

403 qr = quick_reference + self._magic_docs(brief=True) 

404 page.page(qr) 

405 

406 @line_magic 

407 def doctest_mode(self, parameter_s=''): 

408 """Toggle doctest mode on and off. 

409 

410 This mode is intended to make IPython behave as much as possible like a 

411 plain Python shell, from the perspective of how its prompts, exceptions 

412 and output look. This makes it easy to copy and paste parts of a 

413 session into doctests. It does so by: 

414 

415 - Changing the prompts to the classic ``>>>`` ones. 

416 - Changing the exception reporting mode to 'Plain'. 

417 - Disabling pretty-printing of output. 

418 

419 Note that IPython also supports the pasting of code snippets that have 

420 leading '>>>' and '...' prompts in them. This means that you can paste 

421 doctests from files or docstrings (even if they have leading 

422 whitespace), and the code will execute correctly. You can then use 

423 '%history -t' to see the translated history; this will give you the 

424 input after removal of all the leading prompts and whitespace, which 

425 can be pasted back into an editor. 

426 

427 With these features, you can switch into this mode easily whenever you 

428 need to do testing and changes to doctests, without having to leave 

429 your existing IPython session. 

430 """ 

431 

432 # Shorthands 

433 shell = self.shell 

434 meta = shell.meta 

435 disp_formatter = self.shell.display_formatter 

436 ptformatter = disp_formatter.formatters['text/plain'] 

437 # dstore is a data store kept in the instance metadata bag to track any 

438 # changes we make, so we can undo them later. 

439 dstore = meta.setdefault('doctest_mode',Struct()) 

440 save_dstore = dstore.setdefault 

441 

442 # save a few values we'll need to recover later 

443 mode = save_dstore('mode',False) 

444 save_dstore('rc_pprint',ptformatter.pprint) 

445 save_dstore('xmode',shell.InteractiveTB.mode) 

446 save_dstore('rc_separate_out',shell.separate_out) 

447 save_dstore('rc_separate_out2',shell.separate_out2) 

448 save_dstore('rc_separate_in',shell.separate_in) 

449 save_dstore('rc_active_types',disp_formatter.active_types) 

450 

451 if not mode: 

452 # turn on 

453 

454 # Prompt separators like plain python 

455 shell.separate_in = '' 

456 shell.separate_out = '' 

457 shell.separate_out2 = '' 

458 

459 

460 ptformatter.pprint = False 

461 disp_formatter.active_types = ['text/plain'] 

462 

463 shell.run_line_magic("xmode", "Plain") 

464 else: 

465 # turn off 

466 shell.separate_in = dstore.rc_separate_in 

467 

468 shell.separate_out = dstore.rc_separate_out 

469 shell.separate_out2 = dstore.rc_separate_out2 

470 

471 ptformatter.pprint = dstore.rc_pprint 

472 disp_formatter.active_types = dstore.rc_active_types 

473 

474 shell.run_line_magic("xmode", dstore.xmode) 

475 

476 # mode here is the state before we switch; switch_doctest_mode takes 

477 # the mode we're switching to. 

478 shell.switch_doctest_mode(not mode) 

479 

480 # Store new mode and inform 

481 dstore.mode = bool(not mode) 

482 mode_label = ['OFF','ON'][dstore.mode] 

483 print('Doctest mode is:', mode_label) 

484 

485 @line_magic 

486 def gui(self, parameter_s=''): 

487 """Enable or disable IPython GUI event loop integration. 

488 

489 %gui [GUINAME] 

490 

491 This magic replaces IPython's threaded shells that were activated 

492 using the (pylab/wthread/etc.) command line flags. GUI toolkits 

493 can now be enabled at runtime and keyboard 

494 interrupts should work without any problems. The following toolkits 

495 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX):: 

496 

497 %gui wx # enable wxPython event loop integration 

498 %gui qt # enable PyQt/PySide event loop integration 

499 # with the latest version available. 

500 %gui qt6 # enable PyQt6/PySide6 event loop integration 

501 %gui qt5 # enable PyQt5/PySide2 event loop integration 

502 %gui gtk # enable PyGTK event loop integration 

503 %gui gtk3 # enable Gtk3 event loop integration 

504 %gui gtk4 # enable Gtk4 event loop integration 

505 %gui tk # enable Tk event loop integration 

506 %gui osx # enable Cocoa event loop integration 

507 # (requires %matplotlib 1.1) 

508 %gui # disable all event loop integration 

509 

510 WARNING: after any of these has been called you can simply create 

511 an application object, but DO NOT start the event loop yourself, as 

512 we have already handled that. 

513 """ 

514 opts, arg = self.parse_options(parameter_s, '') 

515 if arg=='': arg = None 

516 try: 

517 return self.shell.enable_gui(arg) 

518 except Exception as e: 

519 # print simple error message, rather than traceback if we can't 

520 # hook up the GUI 

521 error(str(e)) 

522 

523 @skip_doctest 

524 @line_magic 

525 def precision(self, s=''): 

526 """Set floating point precision for pretty printing. 

527 

528 Can set either integer precision or a format string. 

529 

530 If numpy has been imported and precision is an int, 

531 numpy display precision will also be set, via ``numpy.set_printoptions``. 

532 

533 If no argument is given, defaults will be restored. 

534 

535 Examples 

536 -------- 

537 :: 

538 

539 In [1]: from math import pi 

540 

541 In [2]: %precision 3 

542 Out[2]: '%.3f' 

543 

544 In [3]: pi 

545 Out[3]: 3.142 

546 

547 In [4]: %precision %i 

548 Out[4]: '%i' 

549 

550 In [5]: pi 

551 Out[5]: 3 

552 

553 In [6]: %precision %e 

554 Out[6]: '%e' 

555 

556 In [7]: pi**10 

557 Out[7]: 9.364805e+04 

558 

559 In [8]: %precision 

560 Out[8]: '%r' 

561 

562 In [9]: pi**10 

563 Out[9]: 93648.047476082982 

564 """ 

565 ptformatter = self.shell.display_formatter.formatters['text/plain'] 

566 ptformatter.float_precision = s 

567 return ptformatter.float_format 

568 

569 @magic_arguments.magic_arguments() 

570 @magic_arguments.argument( 

571 'filename', type=str, 

572 help='Notebook name or filename' 

573 ) 

574 @line_magic 

575 def notebook(self, s): 

576 """Export and convert IPython notebooks. 

577 

578 This function can export the current IPython history to a notebook file. 

579 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb". 

580 """ 

581 args = magic_arguments.parse_argstring(self.notebook, s) 

582 outfname = os.path.expanduser(args.filename) 

583 

584 from nbformat import write, v4 

585 from nbformat.sign import NotebookNotary 

586 

587 cells = [] 

588 hist = list(self.shell.history_manager.get_range()) 

589 outputs = self.shell.history_manager.outputs 

590 exceptions = self.shell.history_manager.exceptions 

591 

592 if(len(hist)<=1): 

593 raise ValueError('History is empty, cannot export') 

594 

595 for session, execution_count, source in hist[:-1]: 

596 cell = v4.new_code_cell(execution_count=execution_count, source=source) 

597 

598 for output in outputs[execution_count]: 

599 if output.output_type in {"out_stream", "err_stream"}: 

600 text_data = [] 

601 for mime_type, data in output.bundle.items(): 

602 if isinstance(data, list): 

603 text_data.extend(data) 

604 else: 

605 text_data.append(data) 

606 full_text = "".join(text_data) 

607 # Replace literal \n with actual newlines 

608 full_text = full_text.replace("\\n", "\n") 

609 normalized_text = [] 

610 lines = full_text.split("\n") 

611 for i, line in enumerate(lines): 

612 if i < len(lines) - 1: 

613 normalized_text.append(line + "\n") 

614 elif line: # Last line only if it's not empty 

615 normalized_text.append(line + "\n") 

616 stream_output = v4.new_output("stream", text=normalized_text) 

617 if output.output_type == "err_stream": 

618 stream_output.name = "stderr" 

619 cell.outputs.append(stream_output) 

620 

621 elif output.output_type == "execute_result": 

622 data_dict = {} 

623 for mime_type, data in output.bundle.items(): 

624 data_dict[mime_type] = data 

625 cell.outputs.append( 

626 v4.new_output( 

627 "execute_result", 

628 data=data_dict, 

629 execution_count=execution_count, 

630 ) 

631 ) 

632 

633 elif output.output_type == "display_data": 

634 # Collect all MIME types for this display_data into a single output 

635 data_dict = {} 

636 for mime_type, data in output.bundle.items(): 

637 data_dict[mime_type] = data 

638 cell.outputs.append( 

639 v4.new_output( 

640 "display_data", 

641 data=data_dict, 

642 ) 

643 ) 

644 else: 

645 raise ValueError(f"Unknown output type: {output.output_type}") 

646 

647 # Check if this execution_count is in exceptions (current session) 

648 if execution_count in exceptions: 

649 cell.outputs.append( 

650 v4.new_output("error", **exceptions[execution_count]) 

651 ) 

652 cells.append(cell) 

653 

654 kernel_language_info = self._get_kernel_language_info() 

655 

656 nb = v4.new_notebook( 

657 cells=cells, 

658 metadata={ 

659 "kernelspec": { 

660 "display_name": "Python 3 (ipykernel)", 

661 "language": "python", 

662 "name": "python3", 

663 }, 

664 "language_info": kernel_language_info 

665 or { 

666 "codemirror_mode": { 

667 "name": "ipython", 

668 "version": sys.version_info[0], 

669 }, 

670 "file_extension": ".py", 

671 "mimetype": "text/x-python", 

672 "name": "python", 

673 "nbconvert_exporter": "python", 

674 "pygments_lexer": "ipython3", 

675 "version": platform.python_version(), 

676 }, 

677 }, 

678 ) 

679 # Sign the notebook to make it trusted 

680 notary = NotebookNotary() 

681 notary.update_config(self.shell.config) 

682 try: 

683 notary.sign(nb) 

684 finally: 

685 # Close the signature store's SQLite connection. NotebookNotary 

686 # opens it eagerly but never closes it on its own, so leaving it 

687 # open lets the connection be garbage collected unclosed, raising a 

688 # spurious "ResourceWarning: unclosed database" in whatever code 

689 # happens to be running at collection time (a source of flaky test 

690 # failures, notably on the Windows / Python 3.14 CI job). 

691 notary.store.close() 

692 with open(outfname, "w", encoding="utf-8") as f: 

693 write(nb, f, version=4) 

694 

695 def _get_kernel_language_info(self) -> dict | None: 

696 """Get language info from kernel, useful when used in Jupyter Console where kernels exist.""" 

697 if not hasattr(self.shell, "kernel"): 

698 return 

699 if not hasattr(self.shell.kernel, "language_info"): 

700 return 

701 if not isinstance(self.shell.kernel.language_info, dict): 

702 return 

703 return self.shell.kernel.language_info 

704 

705@magics_class 

706class AsyncMagics(BasicMagics): 

707 

708 @line_magic 

709 def autoawait(self, parameter_s): 

710 """ 

711 Allow to change the status of the autoawait option. 

712 

713 This allow you to set a specific asynchronous code runner. 

714 

715 If no value is passed, print the currently used asynchronous integration 

716 and whether it is activated. 

717 

718 It can take a number of value evaluated in the following order: 

719 

720 - False/false/off deactivate autoawait integration 

721 - True/true/on activate autoawait integration using configured default 

722 loop 

723 - asyncio/curio/trio activate autoawait integration and use integration 

724 with said library. 

725 

726 - `sync` turn on the pseudo-sync integration (mostly used for 

727 `IPython.embed()` which does not run IPython with a real eventloop and 

728 deactivate running asynchronous code. Turning on Asynchronous code with 

729 the pseudo sync loop is undefined behavior and may lead IPython to crash. 

730 

731 If the passed parameter does not match any of the above and is a python 

732 identifier, get said object from user namespace and set it as the 

733 runner, and activate autoawait. 

734 

735 If the object is a fully qualified object name, attempt to import it and 

736 set it as the runner, and activate autoawait. 

737 

738 The exact behavior of autoawait is experimental and subject to change 

739 across version of IPython and Python. 

740 """ 

741 

742 param = parameter_s.strip() 

743 d = {True: "on", False: "off"} 

744 

745 if not param: 

746 print("IPython autoawait is `{}`, and set to use `{}`".format( 

747 d[self.shell.autoawait], 

748 self.shell.loop_runner 

749 )) 

750 return None 

751 

752 if param.lower() in ('false', 'off'): 

753 self.shell.autoawait = False 

754 return None 

755 if param.lower() in ('true', 'on'): 

756 self.shell.autoawait = True 

757 return None 

758 

759 if param in self.shell.loop_runner_map: 

760 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param] 

761 return None 

762 

763 if param in self.shell.user_ns : 

764 self.shell.loop_runner = self.shell.user_ns[param] 

765 self.shell.autoawait = True 

766 return None 

767 

768 runner = import_item(param) 

769 

770 self.shell.loop_runner = runner 

771 self.shell.autoawait = True