Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/magic.py: 41%

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

278 statements  

1from __future__ import annotations 

2 

3"""Magic functions for InteractiveShell.""" 

4 

5# ----------------------------------------------------------------------------- 

6# Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and 

7# Copyright (C) 2001 Fernando Perez <fperez@colorado.edu> 

8# Copyright (C) 2008 The IPython Development Team 

9 

10# Distributed under the terms of the BSD License. The full license is in 

11# the file COPYING, distributed as part of this software. 

12# ----------------------------------------------------------------------------- 

13 

14import os 

15import re 

16import sys 

17from getopt import getopt, GetoptError 

18 

19from traitlets.config.configurable import Configurable 

20from . import oinspect 

21from .error import UsageError 

22from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2 

23from ..utils.ipstruct import Struct 

24from ..utils.process import arg_split 

25from ..utils.text import dedent 

26from traitlets import Bool, Dict, Instance, observe 

27from logging import error 

28 

29import typing as t 

30from typing import Any, Callable, Literal, TypeVar, overload 

31 

32if t.TYPE_CHECKING: 

33 from types import FrameType 

34 

35 from IPython.core.interactiveshell import InteractiveShell 

36 

37_F = TypeVar("_F", bound=Callable[..., Any]) 

38_MagicKind = Literal["line", "cell"] 

39_MagicSpec = Literal["line", "cell", "line_cell"] 

40 

41 

42# ----------------------------------------------------------------------------- 

43# Globals 

44# ----------------------------------------------------------------------------- 

45 

46# A dict we'll use for each class that has magics, used as temporary storage to 

47# pass information between the @line/cell_magic method decorators and the 

48# @magics_class class decorator, because the method decorators have no 

49# access to the class when they run. See for more details: 

50# http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class 

51 

52magics: dict[str, dict[str, str]] = dict(line={}, cell={}) 

53 

54magic_kinds: tuple[_MagicKind, ...] = ("line", "cell") 

55magic_spec: tuple[_MagicSpec, ...] = ("line", "cell", "line_cell") 

56magic_escapes: dict[_MagicKind, str] = dict(line=ESC_MAGIC, cell=ESC_MAGIC2) 

57 

58# ----------------------------------------------------------------------------- 

59# Utility classes and functions 

60# ----------------------------------------------------------------------------- 

61 

62 

63class Bunch: 

64 pass 

65 

66 

67def compress_dhist(dh: list[str]) -> list[str]: 

68 """Compress a directory history into a new one with at most 20 entries. 

69 

70 Return a new list made from the first and last 10 elements of dhist after 

71 removal of duplicates. 

72 """ 

73 head, tail = dh[:-10], dh[-10:] 

74 

75 newhead: list[str] = [] 

76 done: set[str] = set() 

77 for h in head: 

78 if h in done: 

79 continue 

80 newhead.append(h) 

81 done.add(h) 

82 

83 return newhead + tail 

84 

85 

86def needs_local_scope(func: _F) -> _F: 

87 """Decorator to mark magic functions which need to local scope to run.""" 

88 func.needs_local_scope = True # type: ignore[attr-defined] 

89 return func 

90 

91 

92# ----------------------------------------------------------------------------- 

93# Class and method decorators for registering magics 

94# ----------------------------------------------------------------------------- 

95 

96 

97_T = TypeVar("_T", bound=type["Magics"]) 

98 

99 

100def magics_class(cls: _T) -> _T: 

101 """Class decorator for all subclasses of the main Magics class. 

102 

103 Any class that subclasses Magics *must* also apply this decorator, to 

104 ensure that all the methods that have been decorated as line/cell magics 

105 get correctly registered in the class instance. This is necessary because 

106 when method decorators run, the class does not exist yet, so they 

107 temporarily store their information into a module global. Application of 

108 this class decorator copies that global data to the class instance and 

109 clears the global. 

110 

111 Obviously, this mechanism is not thread-safe, which means that the 

112 *creation* of subclasses of Magic should only be done in a single-thread 

113 context. Instantiation of the classes has no restrictions. Given that 

114 these classes are typically created at IPython startup time and before user 

115 application code becomes active, in practice this should not pose any 

116 problems. 

117 """ 

118 cls.registered = True 

119 cls.magics = dict(line=magics["line"], cell=magics["cell"]) 

120 magics["line"] = {} 

121 magics["cell"] = {} 

122 return cls 

123 

124 

125def record_magic( 

126 dct: dict[str, dict[str, Any]], 

127 magic_kind: _MagicSpec, 

128 magic_name: str, 

129 func: Any, 

130) -> None: 

131 """Utility function to store a function as a magic of a specific kind. 

132 

133 Parameters 

134 ---------- 

135 dct : dict 

136 A dictionary with 'line' and 'cell' subdicts. 

137 magic_kind : str 

138 Kind of magic to be stored. 

139 magic_name : str 

140 Key to store the magic as. 

141 func : function 

142 Callable object to store. 

143 """ 

144 if magic_kind == "line_cell": 

145 dct["line"][magic_name] = dct["cell"][magic_name] = func 

146 else: 

147 dct[magic_kind][magic_name] = func 

148 

149 

150def validate_type(magic_kind: str) -> None: 

151 """Ensure that the given magic_kind is valid. 

152 

153 Check that the given magic_kind is one of the accepted spec types (stored 

154 in the global `magic_spec`), raise ValueError otherwise. 

155 """ 

156 if magic_kind not in magic_spec: 

157 raise ValueError( 

158 "magic_kind must be one of %s, %s given" % magic_kinds, magic_kind 

159 ) 

160 

161 

162# The docstrings for the decorator below will be fairly similar for the two 

163# types (method and function), so we generate them here once and reuse the 

164# templates below. 

165_docstring_template = """Decorate the given {0} as {1} magic. 

166 

167The decorator can be used with or without arguments, as follows. 

168 

169i) without arguments: it will create a {1} magic named as the {0} being 

170decorated:: 

171 

172 @deco 

173 def foo(...) 

174 

175will create a {1} magic named `foo`. 

176 

177ii) with one string argument: which will be used as the actual name of the 

178resulting magic:: 

179 

180 @deco('bar') 

181 def foo(...) 

182 

183will create a {1} magic named `bar`. 

184 

185To register a class magic use ``Interactiveshell.register_magic(class or instance)``. 

186""" 

187 

188# These two are decorator factories. While they are conceptually very similar, 

189# there are enough differences in the details that it's simpler to have them 

190# written as completely standalone functions rather than trying to share code 

191# and make a single one with convoluted logic. 

192 

193 

194def _method_magic_marker( 

195 magic_kind: _MagicSpec, 

196) -> Callable[[_F | str], _F | Callable[[_F], _F]]: 

197 """Decorator factory for methods in Magics subclasses.""" 

198 

199 validate_type(magic_kind) 

200 

201 # This is a closure to capture the magic_kind. We could also use a class, 

202 # but it's overkill for just that one bit of state. 

203 def magic_deco(arg: _F | str) -> _F | Callable[[_F], _F]: 

204 retval: _F | Callable[[_F], _F] 

205 if callable(arg): 

206 # "Naked" decorator call (just @foo, no args) 

207 func = arg 

208 name = func.__name__ 

209 retval = arg 

210 record_magic(magics, magic_kind, name, name) 

211 elif isinstance(arg, str): 

212 # Decorator called with arguments (@foo('bar')) 

213 name = arg 

214 

215 def mark(func: _F, *a: Any, **kw: Any) -> _F: 

216 record_magic(magics, magic_kind, name, func.__name__) 

217 return func 

218 

219 retval = mark 

220 else: 

221 raise TypeError("Decorator can only be called with string or function") 

222 return retval 

223 

224 # Ensure the resulting decorator has a usable docstring 

225 magic_deco.__doc__ = _docstring_template.format("method", magic_kind) 

226 return magic_deco 

227 

228 

229def _function_magic_marker( 

230 magic_kind: _MagicSpec, 

231) -> Callable[[_F | str], _F | Callable[[_F], _F]]: 

232 """Decorator factory for standalone functions.""" 

233 validate_type(magic_kind) 

234 

235 # This is a closure to capture the magic_kind. We could also use a class, 

236 # but it's overkill for just that one bit of state. 

237 def magic_deco(arg: _F | str) -> _F | Callable[[_F], _F]: 

238 # Find get_ipython() in the caller's namespace 

239 caller: FrameType = sys._getframe(1) 

240 get_ipython: Callable[[], InteractiveShell] | None = None 

241 for ns in ["f_locals", "f_globals", "f_builtins"]: 

242 get_ipython = getattr(caller, ns).get("get_ipython") 

243 if get_ipython is not None: 

244 break 

245 else: 

246 raise NameError( 

247 "Decorator can only run in context where `get_ipython` exists" 

248 ) 

249 

250 ip: InteractiveShell = get_ipython() 

251 

252 retval: _F | Callable[[_F], _F] 

253 if callable(arg): 

254 # "Naked" decorator call (just @foo, no args) 

255 func = arg 

256 name = func.__name__ 

257 ip.register_magic_function(func, magic_kind, name) # type: ignore[arg-type] 

258 retval = arg 

259 elif isinstance(arg, str): 

260 # Decorator called with arguments (@foo('bar')) 

261 name = arg 

262 

263 def mark(func: _F, *a: Any, **kw: Any) -> _F: 

264 ip.register_magic_function(func, magic_kind, name) # type: ignore[arg-type] 

265 return func 

266 

267 retval = mark 

268 else: 

269 raise TypeError("Decorator can only be called with string or function") 

270 return retval 

271 

272 # Ensure the resulting decorator has a usable docstring 

273 ds = _docstring_template.format("function", magic_kind) 

274 

275 ds += dedent( 

276 """ 

277 Note: this decorator can only be used in a context where IPython is already 

278 active, so that the `get_ipython()` call succeeds. You can therefore use 

279 it in your startup files loaded after IPython initializes, but *not* in the 

280 IPython configuration file itself, which is executed before IPython is 

281 fully up and running. Any file located in the `startup` subdirectory of 

282 your configuration profile will be OK in this sense. 

283 """ 

284 ) 

285 

286 magic_deco.__doc__ = ds 

287 return magic_deco 

288 

289 

290MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand" 

291MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced" 

292 

293 

294def no_var_expand(magic_func: _F) -> _F: 

295 """Mark a magic function as not needing variable expansion 

296 

297 By default, IPython interprets `{a}` or `$a` in the line passed to magics 

298 as variables that should be interpolated from the interactive namespace 

299 before passing the line to the magic function. 

300 This is not always desirable, e.g. when the magic executes Python code 

301 (%timeit, %time, etc.). 

302 Decorate magics with `@no_var_expand` to opt-out of variable expansion. 

303 

304 .. versionadded:: 7.3 

305 """ 

306 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True) 

307 return magic_func 

308 

309 

310def output_can_be_silenced(magic_func: _F) -> _F: 

311 """Mark a magic function so its output may be silenced. 

312 

313 The output is silenced if the Python code used as a parameter of 

314 the magic ends in a semicolon, not counting a Python comment that can 

315 follow it. 

316 """ 

317 setattr(magic_func, MAGIC_OUTPUT_CAN_BE_SILENCED, True) 

318 return magic_func 

319 

320 

321# Create the actual decorators for public use 

322 

323# These three are used to decorate methods in class definitions 

324line_magic = _method_magic_marker("line") 

325cell_magic = _method_magic_marker("cell") 

326line_cell_magic = _method_magic_marker("line_cell") 

327 

328# These three decorate standalone functions and perform the decoration 

329# immediately. They can only run where get_ipython() works 

330register_line_magic = _function_magic_marker("line") 

331register_cell_magic = _function_magic_marker("cell") 

332register_line_cell_magic = _function_magic_marker("line_cell") 

333 

334# ----------------------------------------------------------------------------- 

335# Core Magic classes 

336# ----------------------------------------------------------------------------- 

337 

338 

339class MagicsManager(Configurable): 

340 """Object that handles all magic-related functionality for IPython.""" 

341 

342 # Non-configurable class attributes 

343 

344 # A two-level dict, first keyed by magic type, then by magic function, and 

345 # holding the actual callable object as value. This is the dict used for 

346 # magic function dispatch 

347 magics = Dict() 

348 lazy_magics = Dict( 

349 help=""" 

350 Mapping from magic names to modules to load. 

351 

352 This can be used in IPython/IPykernel configuration to declare lazy magics 

353 that will only be imported/registered on first use. 

354 

355 For example:: 

356 

357 c.MagicsManager.lazy_magics = { 

358 "my_magic": "slow.to.import", 

359 "my_other_magic": "also.slow", 

360 } 

361 

362 On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or 

363 `%%my_other_magic`, the corresponding module will be loaded as an ipython 

364 extensions as if you had previously done `%load_ext ipython`. 

365 

366 Magics names should be without percent(s) as magics can be both cell 

367 and line magics. 

368 

369 Lazy loading happen relatively late in execution process, and 

370 complex extensions that manipulate Python/IPython internal state or global state 

371 might not support lazy loading. 

372 """ 

373 ).tag( 

374 config=True, 

375 ) 

376 

377 # A registry of the original objects that we've been given holding magics. 

378 registry = Dict() 

379 

380 shell = Instance( 

381 "IPython.core.interactiveshell.InteractiveShellABC", allow_none=True 

382 ) 

383 

384 auto_magic = Bool( 

385 True, help="Automatically call line magics without requiring explicit % prefix" 

386 ).tag(config=True) 

387 

388 @observe("auto_magic") 

389 def _auto_magic_changed(self, change: dict[str, Any]) -> None: 

390 assert self.shell is not None 

391 self.shell.automagic = change["new"] 

392 

393 _auto_status = [ 

394 "Automagic is OFF, % prefix IS needed for line magics.", 

395 "Automagic is ON, % prefix IS NOT needed for line magics.", 

396 ] 

397 

398 user_magics = Instance("IPython.core.magics.UserMagics", allow_none=True) 

399 

400 def __init__( 

401 self, 

402 shell: InteractiveShell | None = None, 

403 config: Any = None, 

404 user_magics: Magics | None = None, 

405 **traits: Any, 

406 ) -> None: 

407 super(MagicsManager, self).__init__( 

408 shell=shell, config=config, user_magics=user_magics, **traits 

409 ) 

410 self.magics = dict(line={}, cell={}) 

411 # Let's add the user_magics to the registry for uniformity, so *all* 

412 # registered magic containers can be found there. 

413 if user_magics is not None: 

414 self.registry[user_magics.__class__.__name__] = user_magics 

415 

416 def auto_status(self) -> str: 

417 """Return descriptive string with automagic status.""" 

418 return self._auto_status[self.auto_magic] 

419 

420 def lsmagic(self) -> dict[str, dict[str, Any]]: 

421 """Return a dict of currently available magic functions. 

422 

423 The return dict has the keys 'line' and 'cell', corresponding to the 

424 two types of magics we support. Each value is a list of names. 

425 """ 

426 return self.magics 

427 

428 def lsmagic_docs( 

429 self, brief: bool = False, missing: str = "" 

430 ) -> dict[str, dict[str, str]]: 

431 """Return dict of documentation of magic functions. 

432 

433 The return dict has the keys 'line' and 'cell', corresponding to the 

434 two types of magics we support. Each value is a dict keyed by magic 

435 name whose value is the function docstring. If a docstring is 

436 unavailable, the value of `missing` is used instead. 

437 

438 If brief is True, only the first line of each docstring will be returned. 

439 """ 

440 docs: dict[str, dict[str, str]] = {} 

441 for m_type in self.magics: 

442 m_docs: dict[str, str] = {} 

443 for m_name, m_func in self.magics[m_type].items(): 

444 if m_func.__doc__: 

445 if brief: 

446 m_docs[m_name] = m_func.__doc__.split("\n", 1)[0] 

447 else: 

448 m_docs[m_name] = m_func.__doc__.rstrip() 

449 else: 

450 m_docs[m_name] = missing 

451 docs[m_type] = m_docs 

452 return docs 

453 

454 def register_lazy(self, name: str, fully_qualified_name: str) -> None: 

455 """ 

456 Lazily register a magic via an extension. 

457 

458 

459 Parameters 

460 ---------- 

461 name : str 

462 Name of the magic you wish to register. 

463 fully_qualified_name : 

464 Fully qualified name of the module/submodule that should be loaded 

465 as an extensions when the magic is first called. 

466 It is assumed that loading this extensions will register the given 

467 magic. 

468 """ 

469 

470 self.lazy_magics[name] = fully_qualified_name 

471 

472 def register(self, *magic_objects: type[Magics] | Magics) -> None: 

473 """Register one or more instances of Magics. 

474 

475 Take one or more classes or instances of classes that subclass the main 

476 `core.Magic` class, and register them with IPython to use the magic 

477 functions they provide. The registration process will then ensure that 

478 any methods that have decorated to provide line and/or cell magics will 

479 be recognized with the `%x`/`%%x` syntax as a line/cell magic 

480 respectively. 

481 

482 If classes are given, they will be instantiated with the default 

483 constructor. If your classes need a custom constructor, you should 

484 instanitate them first and pass the instance. 

485 

486 The provided arguments can be an arbitrary mix of classes and instances. 

487 

488 Parameters 

489 ---------- 

490 *magic_objects : one or more classes or instances 

491 """ 

492 # Start by validating them to ensure they have all had their magic 

493 # methods registered at the instance level 

494 for m in magic_objects: 

495 if not m.registered: 

496 raise ValueError( 

497 "Class of magics %r was constructed without " 

498 "the @register_magics class decorator" 

499 ) 

500 if isinstance(m, type): 

501 # If we're given an uninstantiated class 

502 m = m(shell=self.shell) 

503 

504 # Now that we have an instance, we can register it and update the 

505 # table of callables 

506 self.registry[m.__class__.__name__] = m 

507 for mtype in magic_kinds: 

508 self.magics[mtype].update(m.magics[mtype]) 

509 

510 def register_function( 

511 self, 

512 func: Callable[..., Any], 

513 magic_kind: _MagicSpec = "line", 

514 magic_name: str | None = None, 

515 ) -> None: 

516 """Expose a standalone function as magic function for IPython. 

517 

518 This will create an IPython magic (line, cell or both) from a 

519 standalone function. The functions should have the following 

520 signatures: 

521 

522 * For line magics: `def f(line)` 

523 * For cell magics: `def f(line, cell)` 

524 * For a function that does both: `def f(line, cell=None)` 

525 

526 In the latter case, the function will be called with `cell==None` when 

527 invoked as `%f`, and with cell as a string when invoked as `%%f`. 

528 

529 Parameters 

530 ---------- 

531 func : callable 

532 Function to be registered as a magic. 

533 magic_kind : str 

534 Kind of magic, one of 'line', 'cell' or 'line_cell' 

535 magic_name : optional str 

536 If given, the name the magic will have in the IPython namespace. By 

537 default, the name of the function itself is used. 

538 """ 

539 

540 # Create the new method in the user_magics and register it in the 

541 # global table 

542 validate_type(magic_kind) 

543 magic_name = func.__name__ if magic_name is None else magic_name 

544 assert self.user_magics is not None 

545 setattr(self.user_magics, magic_name, func) 

546 record_magic(self.magics, magic_kind, magic_name, func) 

547 

548 def register_alias( 

549 self, 

550 alias_name: str, 

551 magic_name: str, 

552 magic_kind: _MagicKind = "line", 

553 magic_params: str | None = None, 

554 ) -> None: 

555 """Register an alias to a magic function. 

556 

557 The alias is an instance of :class:`MagicAlias`, which holds the 

558 name and kind of the magic it should call. Binding is done at 

559 call time, so if the underlying magic function is changed the alias 

560 will call the new function. 

561 

562 Parameters 

563 ---------- 

564 alias_name : str 

565 The name of the magic to be registered. 

566 magic_name : str 

567 The name of an existing magic. 

568 magic_kind : str 

569 Kind of magic, one of 'line' or 'cell' 

570 """ 

571 

572 # `validate_type` is too permissive, as it allows 'line_cell' 

573 # which we do not handle. 

574 if magic_kind not in magic_kinds: 

575 raise ValueError( 

576 "magic_kind must be one of %s, %s given" % magic_kinds, magic_kind 

577 ) 

578 

579 assert self.shell is not None 

580 assert self.user_magics is not None 

581 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params) 

582 setattr(self.user_magics, alias_name, alias) 

583 record_magic(self.magics, magic_kind, alias_name, alias) 

584 

585 

586# Key base class that provides the central functionality for magics. 

587 

588 

589class Magics(Configurable): 

590 """Base class for implementing magic functions. 

591 

592 Shell functions which can be reached as %function_name. All magic 

593 functions should accept a string, which they can parse for their own 

594 needs. This can make some functions easier to type, eg `%cd ../` 

595 vs. `%cd("../")` 

596 

597 Classes providing magic functions need to subclass this class, and they 

598 MUST: 

599 

600 - Use the method decorators `@line_magic` and `@cell_magic` to decorate 

601 individual methods as magic functions, AND 

602 

603 - Use the class decorator `@magics_class` to ensure that the magic 

604 methods are properly registered at the instance level upon instance 

605 initialization. 

606 

607 See :mod:`magic_functions` for examples of actual implementation classes. 

608 """ 

609 

610 # Dict holding all command-line options for each magic. 

611 options_table: dict[str, t.Any] = {} 

612 # Dict for the mapping of magic names to methods, set by class decorator 

613 magics: dict[str, t.Any] = {} 

614 # Flag to check that the class decorator was properly applied 

615 registered: bool = False 

616 # Instance of IPython shell 

617 shell: None | InteractiveShell = None 

618 

619 def __init__( 

620 self, shell: InteractiveShell | None = None, **kwargs: Any 

621 ) -> None: 

622 if not (self.__class__.registered): 

623 raise ValueError( 

624 "Magics subclass without registration - " 

625 "did you forget to apply @magics_class?" 

626 ) 

627 if shell is not None: 

628 if hasattr(shell, "configurables"): 

629 shell.configurables.append(self) # type: ignore[arg-type] 

630 if hasattr(shell, "config"): 

631 kwargs.setdefault("parent", shell) 

632 

633 self.shell = shell 

634 self.options_table = {} 

635 # The method decorators are run when the instance doesn't exist yet, so 

636 # they can only record the names of the methods they are supposed to 

637 # grab. Only now, that the instance exists, can we create the proper 

638 # mapping to bound methods. So we read the info off the original names 

639 # table and replace each method name by the actual bound method. 

640 # But we mustn't clobber the *class* mapping, in case of multiple instances. 

641 class_magics = self.magics 

642 self.magics = {} 

643 for mtype in magic_kinds: 

644 self.magics[mtype] = {} 

645 tab: dict[str, Any] = self.magics[mtype] 

646 cls_tab: dict[str, Any] = class_magics[mtype] 

647 for magic_name, meth_name in cls_tab.items(): 

648 if isinstance(meth_name, str): 

649 # it's a method name, grab it 

650 tab[magic_name] = getattr(self, meth_name) 

651 else: 

652 # it's the real thing 

653 tab[magic_name] = meth_name 

654 # Configurable **needs** to be initiated at the end or the config 

655 # magics get screwed up. 

656 super(Magics, self).__init__(**kwargs) 

657 

658 def arg_err(self, func: Callable[..., Any]) -> None: 

659 """Print docstring if incorrect arguments were passed""" 

660 print("Error in arguments:") 

661 print(oinspect.getdoc(func)) 

662 

663 def format_latex(self, strng: str) -> str: 

664 """Format a string for latex inclusion.""" 

665 

666 # Characters that need to be escaped for latex: 

667 escape_re = re.compile(r"(%|_|\$|#|&)", re.MULTILINE) 

668 # Magic command names as headers: 

669 cmd_name_re = re.compile(r"^(%s.*?):" % ESC_MAGIC, re.MULTILINE) 

670 # Magic commands 

671 cmd_re = re.compile(r"(?P<cmd>%s.+?\b)(?!\}\}:)" % ESC_MAGIC, re.MULTILINE) 

672 # Paragraph continue 

673 par_re = re.compile(r"\\$", re.MULTILINE) 

674 

675 # The "\n" symbol 

676 newline_re = re.compile(r"\\n") 

677 

678 # Now build the string for output: 

679 # strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng) 

680 strng = cmd_name_re.sub(r"\n\\bigskip\n\\texttt{\\textbf{ \1}}:", strng) 

681 strng = cmd_re.sub(r"\\texttt{\g<cmd>}", strng) 

682 strng = par_re.sub(r"\\\\", strng) 

683 strng = escape_re.sub(r"\\\1", strng) 

684 strng = newline_re.sub(r"\\textbackslash{}n", strng) 

685 return strng 

686 

687 def parse_options( 

688 self, arg_str: str, opt_str: str, *long_opts: str, **kw: Any 

689 ) -> tuple[Any, Any]: 

690 """Parse options passed to an argument string. 

691 

692 The interface is similar to that of :func:`getopt.getopt`, but it 

693 returns a :class:`~IPython.utils.struct.Struct` with the options as keys 

694 and the stripped argument string still as a string. 

695 

696 arg_str is quoted as a true sys.argv vector by using shlex.split. 

697 This allows us to easily expand variables, glob files, quote 

698 arguments, etc. 

699 

700 Parameters 

701 ---------- 

702 arg_str : str 

703 The arguments to parse. 

704 opt_str : str 

705 The options specification. 

706 mode : str, default 'string' 

707 If given as 'list', the argument string is returned as a list (split 

708 on whitespace) instead of a string. 

709 list_all : bool, default False 

710 Put all option values in lists. Normally only options 

711 appearing more than once are put in a list. 

712 posix : bool, default True 

713 Whether to split the input line in POSIX mode or not, as per the 

714 conventions outlined in the :mod:`shlex` module from the standard 

715 library. 

716 """ 

717 

718 # inject default options at the beginning of the input line 

719 caller = sys._getframe(1).f_code.co_name 

720 arg_str = "%s %s" % (self.options_table.get(caller, ""), arg_str) 

721 

722 mode = kw.get("mode", "string") 

723 if mode not in ["string", "list"]: 

724 raise ValueError("incorrect mode given: %s" % mode) 

725 # Get options 

726 list_all = kw.get("list_all", 0) 

727 posix = kw.get("posix", os.name == "posix") 

728 strict = kw.get("strict", True) 

729 

730 preserve_non_opts = kw.get("preserve_non_opts", False) 

731 remainder_arg_str = arg_str 

732 

733 # Check if we have more than one argument to warrant extra processing: 

734 odict: dict[str, t.Any] = {} # Dictionary with options 

735 args = arg_str.split() 

736 if len(args) >= 1: 

737 # If the list of inputs only has 0 or 1 thing in it, there's no 

738 # need to look for options 

739 argv = arg_split(arg_str, posix, strict) 

740 # Do regular option processing 

741 try: 

742 opts, args = getopt(argv, opt_str, long_opts) 

743 except GetoptError as e: 

744 raise UsageError( 

745 '%s (allowed: "%s"%s)' 

746 % (e.msg, opt_str, " ".join(("",) + long_opts) if long_opts else "") 

747 ) from e 

748 for o, a in opts: 

749 if mode == "string" and preserve_non_opts: 

750 # remove option-parts from the original args-string and preserve remaining-part. 

751 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are 

752 # returned in the original order. 

753 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace( 

754 a, "", 1 

755 ) 

756 if o.startswith("--"): 

757 o = o[2:] 

758 else: 

759 o = o[1:] 

760 try: 

761 odict[o].append(a) 

762 except AttributeError: 

763 odict[o] = [odict[o], a] 

764 except KeyError: 

765 if list_all: 

766 odict[o] = [a] 

767 else: 

768 odict[o] = a 

769 

770 # Prepare opts,args for return 

771 opts = Struct(odict) # type: ignore[assignment, no-untyped-call] 

772 if mode == "string": 

773 if preserve_non_opts: 

774 args = remainder_arg_str.lstrip() # type: ignore[assignment] 

775 else: 

776 args = " ".join(args) # type: ignore[assignment] 

777 

778 return opts, args 

779 

780class MagicAlias: 

781 """An alias to another magic function. 

782 

783 An alias is determined by its magic name and magic kind. Lookup 

784 is done at call time, so if the underlying magic changes the alias 

785 will call the new function. 

786 

787 Use the :meth:`MagicsManager.register_alias` method or the 

788 `%alias_magic` magic function to create and register a new alias. 

789 """ 

790 

791 def __init__( 

792 self, 

793 shell: InteractiveShell, 

794 magic_name: str, 

795 magic_kind: _MagicKind, 

796 magic_params: str | None = None, 

797 ) -> None: 

798 self.shell = shell 

799 self.magic_name = magic_name 

800 self.magic_params = magic_params 

801 self.magic_kind = magic_kind 

802 

803 self.pretty_target = "%s%s" % (magic_escapes[self.magic_kind], self.magic_name) 

804 self.__doc__ = "Alias for `%s`." % self.pretty_target 

805 

806 self._in_call = False 

807 

808 def __call__(self, *args: Any, **kwargs: Any) -> Any: 

809 """Call the magic alias.""" 

810 fn = self.shell.find_magic(self.magic_name, self.magic_kind) # type: ignore[no-untyped-call] 

811 if fn is None: 

812 raise UsageError("Magic `%s` not found." % self.pretty_target) 

813 

814 # Protect against infinite recursion. 

815 if self._in_call: 

816 raise UsageError( 

817 "Infinite recursion detected; magic aliases cannot call themselves." 

818 ) 

819 self._in_call = True 

820 try: 

821 if self.magic_params: 

822 args_list = list(args) 

823 args_list[0] = self.magic_params + " " + args[0] 

824 args = tuple(args_list) 

825 return fn(*args, **kwargs) 

826 finally: 

827 self._in_call = False