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

270 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 

30 

31if t.TYPE_CHECKING: 

32 from IPython.core.interactiveshell import InteractiveShell 

33 

34 

35# ----------------------------------------------------------------------------- 

36# Globals 

37# ----------------------------------------------------------------------------- 

38 

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

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

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

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

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

44 

45magics: t.Dict = dict(line={}, cell={}) 

46 

47magic_kinds = ("line", "cell") 

48magic_spec = ("line", "cell", "line_cell") 

49magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2) 

50 

51# ----------------------------------------------------------------------------- 

52# Utility classes and functions 

53# ----------------------------------------------------------------------------- 

54 

55 

56class Bunch: 

57 pass 

58 

59 

60def on_off(tag): 

61 """Return an ON/OFF string for a 1/0 input. Simple utility function.""" 

62 return ["OFF", "ON"][tag] 

63 

64 

65def compress_dhist(dh): 

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

67 

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

69 removal of duplicates. 

70 """ 

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

72 

73 newhead = [] 

74 done = set() 

75 for h in head: 

76 if h in done: 

77 continue 

78 newhead.append(h) 

79 done.add(h) 

80 

81 return newhead + tail 

82 

83 

84def needs_local_scope(func): 

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

86 func.needs_local_scope = True 

87 return func 

88 

89 

90# ----------------------------------------------------------------------------- 

91# Class and method decorators for registering magics 

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

93 

94 

95def magics_class(cls): 

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

97 

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

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

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

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

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

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

104 clears the global. 

105 

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

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

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

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

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

111 problems. 

112 """ 

113 cls.registered = True 

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

115 magics["line"] = {} 

116 magics["cell"] = {} 

117 return cls 

118 

119 

120def record_magic(dct, magic_kind, magic_name, func): 

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

122 

123 Parameters 

124 ---------- 

125 dct : dict 

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

127 magic_kind : str 

128 Kind of magic to be stored. 

129 magic_name : str 

130 Key to store the magic as. 

131 func : function 

132 Callable object to store. 

133 """ 

134 if magic_kind == "line_cell": 

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

136 else: 

137 dct[magic_kind][magic_name] = func 

138 

139 

140def validate_type(magic_kind): 

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

142 

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

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

145 """ 

146 if magic_kind not in magic_spec: 

147 raise ValueError( 

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

149 ) 

150 

151 

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

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

154# templates below. 

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

156 

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

158 

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

160decorated:: 

161 

162 @deco 

163 def foo(...) 

164 

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

166 

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

168resulting magic:: 

169 

170 @deco('bar') 

171 def foo(...) 

172 

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

174 

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

176""" 

177 

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

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

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

181# and make a single one with convoluted logic. 

182 

183 

184def _method_magic_marker(magic_kind): 

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

186 

187 validate_type(magic_kind) 

188 

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

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

191 def magic_deco(arg): 

192 if callable(arg): 

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

194 func = arg 

195 name = func.__name__ 

196 retval = arg 

197 record_magic(magics, magic_kind, name, name) 

198 elif isinstance(arg, str): 

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

200 name = arg 

201 

202 def mark(func, *a, **kw): 

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

204 return func 

205 

206 retval = mark 

207 else: 

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

209 return retval 

210 

211 # Ensure the resulting decorator has a usable docstring 

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

213 return magic_deco 

214 

215 

216def _function_magic_marker(magic_kind): 

217 """Decorator factory for standalone functions.""" 

218 validate_type(magic_kind) 

219 

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

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

222 def magic_deco(arg): 

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

224 caller = sys._getframe(1) 

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

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

227 if get_ipython is not None: 

228 break 

229 else: 

230 raise NameError( 

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

232 ) 

233 

234 ip = get_ipython() 

235 

236 if callable(arg): 

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

238 func = arg 

239 name = func.__name__ 

240 ip.register_magic_function(func, magic_kind, name) 

241 retval = arg 

242 elif isinstance(arg, str): 

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

244 name = arg 

245 

246 def mark(func, *a, **kw): 

247 ip.register_magic_function(func, magic_kind, name) 

248 return func 

249 

250 retval = mark 

251 else: 

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

253 return retval 

254 

255 # Ensure the resulting decorator has a usable docstring 

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

257 

258 ds += dedent( 

259 """ 

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

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

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

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

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

265 your configuration profile will be OK in this sense. 

266 """ 

267 ) 

268 

269 magic_deco.__doc__ = ds 

270 return magic_deco 

271 

272 

273MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand" 

274MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced" 

275 

276 

277def no_var_expand(magic_func): 

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

279 

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

281 as variables that should be interpolated from the interactive namespace 

282 before passing the line to the magic function. 

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

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

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

286 

287 .. versionadded:: 7.3 

288 """ 

289 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True) 

290 return magic_func 

291 

292 

293def output_can_be_silenced(magic_func): 

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

295 

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

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

298 follow it. 

299 """ 

300 setattr(magic_func, MAGIC_OUTPUT_CAN_BE_SILENCED, True) 

301 return magic_func 

302 

303 

304# Create the actual decorators for public use 

305 

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

307line_magic = _method_magic_marker("line") 

308cell_magic = _method_magic_marker("cell") 

309line_cell_magic = _method_magic_marker("line_cell") 

310 

311# These three decorate standalone functions and perform the decoration 

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

313register_line_magic = _function_magic_marker("line") 

314register_cell_magic = _function_magic_marker("cell") 

315register_line_cell_magic = _function_magic_marker("line_cell") 

316 

317# ----------------------------------------------------------------------------- 

318# Core Magic classes 

319# ----------------------------------------------------------------------------- 

320 

321 

322class MagicsManager(Configurable): 

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

324 

325 # Non-configurable class attributes 

326 

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

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

329 # magic function dispatch 

330 magics = Dict() 

331 lazy_magics = Dict( 

332 help=""" 

333 Mapping from magic names to modules to load. 

334 

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

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

337 

338 For example:: 

339 

340 c.MagicsManager.lazy_magics = { 

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

342 "my_other_magic": "also.slow", 

343 } 

344 

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

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

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

348 

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

350 and line magics. 

351 

352 Lazy loading happen relatively late in execution process, and 

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

354 might not support lazy loading. 

355 """ 

356 ).tag( 

357 config=True, 

358 ) 

359 

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

361 registry = Dict() 

362 

363 shell = Instance( 

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

365 ) 

366 

367 auto_magic = Bool( 

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

369 ).tag(config=True) 

370 

371 @observe("auto_magic") 

372 def _auto_magic_changed(self, change): 

373 assert self.shell is not None 

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

375 

376 _auto_status = [ 

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

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

379 ] 

380 

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

382 

383 def __init__(self, shell=None, config=None, user_magics=None, **traits): 

384 super(MagicsManager, self).__init__( 

385 shell=shell, config=config, user_magics=user_magics, **traits 

386 ) 

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

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

389 # registered magic containers can be found there. 

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

391 

392 def auto_status(self): 

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

394 return self._auto_status[self.auto_magic] 

395 

396 def lsmagic(self): 

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

398 

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

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

401 """ 

402 return self.magics 

403 

404 def lsmagic_docs(self, brief=False, missing=""): 

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

406 

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

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

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

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

411 

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

413 """ 

414 docs = {} 

415 for m_type in self.magics: 

416 m_docs = {} 

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

418 if m_func.__doc__: 

419 if brief: 

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

421 else: 

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

423 else: 

424 m_docs[m_name] = missing 

425 docs[m_type] = m_docs 

426 return docs 

427 

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

429 """ 

430 Lazily register a magic via an extension. 

431 

432 

433 Parameters 

434 ---------- 

435 name : str 

436 Name of the magic you wish to register. 

437 fully_qualified_name : 

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

439 as an extensions when the magic is first called. 

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

441 magic. 

442 """ 

443 

444 self.lazy_magics[name] = fully_qualified_name 

445 

446 def register(self, *magic_objects): 

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

448 

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

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

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

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

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

454 respectively. 

455 

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

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

458 instanitate them first and pass the instance. 

459 

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

461 

462 Parameters 

463 ---------- 

464 *magic_objects : one or more classes or instances 

465 """ 

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

467 # methods registered at the instance level 

468 for m in magic_objects: 

469 if not m.registered: 

470 raise ValueError( 

471 "Class of magics %r was constructed without " 

472 "the @register_magics class decorator" 

473 ) 

474 if isinstance(m, type): 

475 # If we're given an uninstantiated class 

476 m = m(shell=self.shell) 

477 

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

479 # table of callables 

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

481 for mtype in magic_kinds: 

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

483 

484 def register_function(self, func, magic_kind="line", magic_name=None): 

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

486 

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

488 standalone function. The functions should have the following 

489 signatures: 

490 

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

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

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

494 

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

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

497 

498 Parameters 

499 ---------- 

500 func : callable 

501 Function to be registered as a magic. 

502 magic_kind : str 

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

504 magic_name : optional str 

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

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

507 """ 

508 

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

510 # global table 

511 validate_type(magic_kind) 

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

513 setattr(self.user_magics, magic_name, func) 

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

515 

516 def register_alias( 

517 self, alias_name, magic_name, magic_kind="line", magic_params=None 

518 ): 

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

520 

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

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

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

524 will call the new function. 

525 

526 Parameters 

527 ---------- 

528 alias_name : str 

529 The name of the magic to be registered. 

530 magic_name : str 

531 The name of an existing magic. 

532 magic_kind : str 

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

534 """ 

535 

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

537 # which we do not handle. 

538 if magic_kind not in magic_kinds: 

539 raise ValueError( 

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

541 ) 

542 

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

544 setattr(self.user_magics, alias_name, alias) 

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

546 

547 

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

549 

550 

551class Magics(Configurable): 

552 """Base class for implementing magic functions. 

553 

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

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

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

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

558 

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

560 MUST: 

561 

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

563 individual methods as magic functions, AND 

564 

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

566 methods are properly registered at the instance level upon instance 

567 initialization. 

568 

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

570 """ 

571 

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

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

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

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

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

577 registered: bool = False 

578 # Instance of IPython shell 

579 shell: None | InteractiveShell = None 

580 

581 def __init__(self, shell=None, **kwargs): 

582 if not (self.__class__.registered): 

583 raise ValueError( 

584 "Magics subclass without registration - " 

585 "did you forget to apply @magics_class?" 

586 ) 

587 if shell is not None: 

588 if hasattr(shell, "configurables"): 

589 shell.configurables.append(self) 

590 if hasattr(shell, "config"): 

591 kwargs.setdefault("parent", shell) 

592 

593 self.shell = shell 

594 self.options_table = {} 

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

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

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

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

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

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

601 class_magics = self.magics 

602 self.magics = {} 

603 for mtype in magic_kinds: 

604 tab = self.magics[mtype] = {} 

605 cls_tab = class_magics[mtype] 

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

607 if isinstance(meth_name, str): 

608 # it's a method name, grab it 

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

610 else: 

611 # it's the real thing 

612 tab[magic_name] = meth_name 

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

614 # magics get screwed up. 

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

616 

617 def arg_err(self, func): 

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

619 print("Error in arguments:") 

620 print(oinspect.getdoc(func)) 

621 

622 def format_latex(self, strng): 

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

624 

625 # Characters that need to be escaped for latex: 

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

627 # Magic command names as headers: 

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

629 # Magic commands 

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

631 # Paragraph continue 

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

633 

634 # The "\n" symbol 

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

636 

637 # Now build the string for output: 

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

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

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

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

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

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

644 return strng 

645 

646 def parse_options(self, arg_str, opt_str, *long_opts, **kw): 

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

648 

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

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

651 and the stripped argument string still as a string. 

652 

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

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

655 arguments, etc. 

656 

657 Parameters 

658 ---------- 

659 arg_str : str 

660 The arguments to parse. 

661 opt_str : str 

662 The options specification. 

663 mode : str, default 'string' 

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

665 on whitespace) instead of a string. 

666 list_all : bool, default False 

667 Put all option values in lists. Normally only options 

668 appearing more than once are put in a list. 

669 posix : bool, default True 

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

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

672 library. 

673 """ 

674 

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

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

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

678 

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

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

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

682 # Get options 

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

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

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

686 

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

688 remainder_arg_str = arg_str 

689 

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

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

692 args = arg_str.split() 

693 if len(args) >= 1: 

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

695 # need to look for options 

696 argv = arg_split(arg_str, posix, strict) 

697 # Do regular option processing 

698 try: 

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

700 except GetoptError as e: 

701 raise UsageError( 

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

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

704 ) from e 

705 for o, a in opts: 

706 if mode == "string" and preserve_non_opts: 

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

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

709 # returned in the original order. 

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

711 a, "", 1 

712 ) 

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

714 o = o[2:] 

715 else: 

716 o = o[1:] 

717 try: 

718 odict[o].append(a) 

719 except AttributeError: 

720 odict[o] = [odict[o], a] 

721 except KeyError: 

722 if list_all: 

723 odict[o] = [a] 

724 else: 

725 odict[o] = a 

726 

727 # Prepare opts,args for return 

728 opts = Struct(odict) # type: ignore[assignment] 

729 if mode == "string": 

730 if preserve_non_opts: 

731 args = remainder_arg_str.lstrip() 

732 else: 

733 args = " ".join(args) 

734 

735 return opts, args 

736 

737 def default_option(self, fn, optstr): 

738 """Make an entry in the options_table for fn, with value optstr""" 

739 assert False, "is this even called?" 

740 if fn not in self.lsmagic(): 

741 error("%s is not a magic function" % fn) 

742 self.options_table[fn] = optstr 

743 

744 

745class MagicAlias: 

746 """An alias to another magic function. 

747 

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

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

750 will call the new function. 

751 

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

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

754 """ 

755 

756 def __init__(self, shell, magic_name, magic_kind, magic_params=None): 

757 self.shell = shell 

758 self.magic_name = magic_name 

759 self.magic_params = magic_params 

760 self.magic_kind = magic_kind 

761 

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

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

764 

765 self._in_call = False 

766 

767 def __call__(self, *args, **kwargs): 

768 """Call the magic alias.""" 

769 fn = self.shell.find_magic(self.magic_name, self.magic_kind) 

770 if fn is None: 

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

772 

773 # Protect against infinite recursion. 

774 if self._in_call: 

775 raise UsageError( 

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

777 ) 

778 self._in_call = True 

779 try: 

780 if self.magic_params: 

781 args_list = list(args) 

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

783 args = tuple(args_list) 

784 return fn(*args, **kwargs) 

785 finally: 

786 self._in_call = False