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
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
1from __future__ import annotations
3"""Magic functions for InteractiveShell."""
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
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# -----------------------------------------------------------------------------
14import os
15import re
16import sys
17from getopt import getopt, GetoptError
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
29import typing as t
30from typing import Any, Callable, Literal, TypeVar, overload
32if t.TYPE_CHECKING:
33 from types import FrameType
35 from IPython.core.interactiveshell import InteractiveShell
37_F = TypeVar("_F", bound=Callable[..., Any])
38_MagicKind = Literal["line", "cell"]
39_MagicSpec = Literal["line", "cell", "line_cell"]
42# -----------------------------------------------------------------------------
43# Globals
44# -----------------------------------------------------------------------------
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
52magics: dict[str, dict[str, str]] = dict(line={}, cell={})
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)
58# -----------------------------------------------------------------------------
59# Utility classes and functions
60# -----------------------------------------------------------------------------
63class Bunch:
64 pass
67def compress_dhist(dh: list[str]) -> list[str]:
68 """Compress a directory history into a new one with at most 20 entries.
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:]
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)
83 return newhead + tail
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
92# -----------------------------------------------------------------------------
93# Class and method decorators for registering magics
94# -----------------------------------------------------------------------------
97_T = TypeVar("_T", bound=type["Magics"])
100def magics_class(cls: _T) -> _T:
101 """Class decorator for all subclasses of the main Magics class.
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.
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
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.
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
150def validate_type(magic_kind: str) -> None:
151 """Ensure that the given magic_kind is valid.
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 )
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.
167The decorator can be used with or without arguments, as follows.
169i) without arguments: it will create a {1} magic named as the {0} being
170decorated::
172 @deco
173 def foo(...)
175will create a {1} magic named `foo`.
177ii) with one string argument: which will be used as the actual name of the
178resulting magic::
180 @deco('bar')
181 def foo(...)
183will create a {1} magic named `bar`.
185To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
186"""
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.
194def _method_magic_marker(
195 magic_kind: _MagicSpec,
196) -> Callable[[_F | str], _F | Callable[[_F], _F]]:
197 """Decorator factory for methods in Magics subclasses."""
199 validate_type(magic_kind)
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
215 def mark(func: _F, *a: Any, **kw: Any) -> _F:
216 record_magic(magics, magic_kind, name, func.__name__)
217 return func
219 retval = mark
220 else:
221 raise TypeError("Decorator can only be called with string or function")
222 return retval
224 # Ensure the resulting decorator has a usable docstring
225 magic_deco.__doc__ = _docstring_template.format("method", magic_kind)
226 return magic_deco
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)
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 )
250 ip: InteractiveShell = get_ipython()
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
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
267 retval = mark
268 else:
269 raise TypeError("Decorator can only be called with string or function")
270 return retval
272 # Ensure the resulting decorator has a usable docstring
273 ds = _docstring_template.format("function", magic_kind)
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 )
286 magic_deco.__doc__ = ds
287 return magic_deco
290MAGIC_NO_VAR_EXPAND_ATTR = "_ipython_magic_no_var_expand"
291MAGIC_OUTPUT_CAN_BE_SILENCED = "_ipython_magic_output_can_be_silenced"
294def no_var_expand(magic_func: _F) -> _F:
295 """Mark a magic function as not needing variable expansion
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.
304 .. versionadded:: 7.3
305 """
306 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
307 return magic_func
310def output_can_be_silenced(magic_func: _F) -> _F:
311 """Mark a magic function so its output may be silenced.
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
321# Create the actual decorators for public use
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")
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")
334# -----------------------------------------------------------------------------
335# Core Magic classes
336# -----------------------------------------------------------------------------
339class MagicsManager(Configurable):
340 """Object that handles all magic-related functionality for IPython."""
342 # Non-configurable class attributes
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.
352 This can be used in IPython/IPykernel configuration to declare lazy magics
353 that will only be imported/registered on first use.
355 For example::
357 c.MagicsManager.lazy_magics = {
358 "my_magic": "slow.to.import",
359 "my_other_magic": "also.slow",
360 }
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`.
366 Magics names should be without percent(s) as magics can be both cell
367 and line magics.
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 )
377 # A registry of the original objects that we've been given holding magics.
378 registry = Dict()
380 shell = Instance(
381 "IPython.core.interactiveshell.InteractiveShellABC", allow_none=True
382 )
384 auto_magic = Bool(
385 True, help="Automatically call line magics without requiring explicit % prefix"
386 ).tag(config=True)
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"]
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 ]
398 user_magics = Instance("IPython.core.magics.UserMagics", allow_none=True)
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
416 def auto_status(self) -> str:
417 """Return descriptive string with automagic status."""
418 return self._auto_status[self.auto_magic]
420 def lsmagic(self) -> dict[str, dict[str, Any]]:
421 """Return a dict of currently available magic functions.
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
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.
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.
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
454 def register_lazy(self, name: str, fully_qualified_name: str) -> None:
455 """
456 Lazily register a magic via an extension.
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 """
470 self.lazy_magics[name] = fully_qualified_name
472 def register(self, *magic_objects: type[Magics] | Magics) -> None:
473 """Register one or more instances of Magics.
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.
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.
486 The provided arguments can be an arbitrary mix of classes and instances.
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)
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])
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.
518 This will create an IPython magic (line, cell or both) from a
519 standalone function. The functions should have the following
520 signatures:
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)`
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`.
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 """
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)
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.
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.
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 """
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 )
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)
586# Key base class that provides the central functionality for magics.
589class Magics(Configurable):
590 """Base class for implementing magic functions.
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("../")`
597 Classes providing magic functions need to subclass this class, and they
598 MUST:
600 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
601 individual methods as magic functions, AND
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.
607 See :mod:`magic_functions` for examples of actual implementation classes.
608 """
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
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)
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)
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))
663 def format_latex(self, strng: str) -> str:
664 """Format a string for latex inclusion."""
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)
675 # The "\n" symbol
676 newline_re = re.compile(r"\\n")
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
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.
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.
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.
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 """
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)
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)
730 preserve_non_opts = kw.get("preserve_non_opts", False)
731 remainder_arg_str = arg_str
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
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]
778 return opts, args
780class MagicAlias:
781 """An alias to another magic function.
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.
787 Use the :meth:`MagicsManager.register_alias` method or the
788 `%alias_magic` magic function to create and register a new alias.
789 """
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
803 self.pretty_target = "%s%s" % (magic_escapes[self.magic_kind], self.magic_name)
804 self.__doc__ = "Alias for `%s`." % self.pretty_target
806 self._in_call = False
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)
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