diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/alias.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/alias.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca736f36217f9b9ad7383bd62e361be5209b5407 Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/alias.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/crashhandler.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/crashhandler.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a875e4b276b681803b712eab000c09acf7e39757 Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/crashhandler.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba0b2529f0e008fedeefd258b5f3781879b5d888 Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display_trap.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display_trap.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b01393c32f1e693bcfcbe1de50dfa3439553c68c Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display_trap.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/extensions.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/extensions.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e929799ef60e9b22ced5b6acb65bf0bc27a963ff Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/extensions.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/getipython.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/getipython.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c72cc27fe22237b2d8a882837e05c0b4a4385ef4 Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/getipython.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/oinspect.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/oinspect.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ec52e3c8a71e6a5a1e202c85e6e49ab30e0b02a Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/oinspect.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/payload.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/payload.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d93c376e47ca81e69bdd2d48823ab2bd0255b8f Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/payload.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/ultratb.cpython-313.pyc b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/ultratb.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ab7a8cb074e8da840438f89e966ec7f4c4fa863 Binary files /dev/null and b/temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/ultratb.cpython-313.pyc differ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/__init__.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a6c5f474c15d29032a23a50d9c884e00235e56ac --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/__init__.py @@ -0,0 +1,42 @@ +"""Implementation of all the magic functions built into IPython. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012 The IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +from ..magic import Magics, magics_class +from .auto import AutoMagics +from .basic import BasicMagics, AsyncMagics +from .code import CodeMagics, MacroToEdit +from .config import ConfigMagics +from .display import DisplayMagics +from .execution import ExecutionMagics +from .extension import ExtensionMagics +from .history import HistoryMagics +from .logging import LoggingMagics +from .namespace import NamespaceMagics +from .osm import OSMagics +from .packaging import PackagingMagics +from .pylab import PylabMagics +from .script import ScriptMagics + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +@magics_class +class UserMagics(Magics): + """Placeholder for user-defined magics to be added at runtime. + + All magics are eventually merged into a single namespace at runtime, but we + use this class to isolate the magics defined dynamically by the user into + their own class. + """ diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/ast_mod.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/ast_mod.py new file mode 100644 index 0000000000000000000000000000000000000000..dc3c5bc76838008d970f50416a4565ebb7ad78b9 --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/ast_mod.py @@ -0,0 +1,330 @@ +""" +This module contains utility function and classes to inject simple ast +transformations based on code strings into IPython. While it is already possible +with ast-transformers it is not easy to directly manipulate ast. + + +IPython has pre-code and post-code hooks, but are ran from within the IPython +machinery so may be inappropriate, for example for performance measurement. + +This module give you tools to simplify this, and expose 2 classes: + +- `ReplaceCodeTransformer` which is a simple ast transformer based on code + template, + +and for advance case: + +- `Mangler` which is a simple ast transformer that mangle names in the ast. + + +Example, let's try to make a simple version of the ``timeit`` magic, that run a +code snippet 10 times and print the average time taken. + +Basically we want to run : + +.. code-block:: python + + from time import perf_counter + now = perf_counter() + for i in range(10): + __code__ # our code + print(f"Time taken: {(perf_counter() - now)/10}") + __ret__ # the result of the last statement + +Where ``__code__`` is the code snippet we want to run, and ``__ret__`` is the +result, so that if we for example run `dataframe.head()` IPython still display +the head of dataframe instead of nothing. + +Here is a complete example of a file `timit2.py` that define such a magic: + +.. code-block:: python + + from IPython.core.magic import ( + Magics, + magics_class, + line_cell_magic, + ) + from IPython.core.magics.ast_mod import ReplaceCodeTransformer + from textwrap import dedent + import ast + + template = template = dedent(''' + from time import perf_counter + now = perf_counter() + for i in range(10): + __code__ + print(f"Time taken: {(perf_counter() - now)/10}") + __ret__ + ''' + ) + + + @magics_class + class AstM(Magics): + @line_cell_magic + def t2(self, line, cell): + transformer = ReplaceCodeTransformer.from_string(template) + transformer.debug = True + transformer.mangler.debug = True + new_code = transformer.visit(ast.parse(cell)) + return exec(compile(new_code, "", "exec")) + + + def load_ipython_extension(ip): + ip.register_magics(AstM) + + + +.. code-block:: python + + In [1]: %load_ext timit2 + + In [2]: %%t2 + ...: import time + ...: time.sleep(0.05) + ...: + ...: + Time taken: 0.05435649999999441 + + +If you wish to ran all the code enter in IPython in an ast transformer, you can +do so as well: + +.. code-block:: python + + In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer + ...: + ...: template = ''' + ...: from time import perf_counter + ...: now = perf_counter() + ...: __code__ + ...: print(f"Code ran in {perf_counter()-now}") + ...: __ret__''' + ...: + ...: get_ipython().ast_transformers.append(ReplaceCodeTransformer.from_string(template)) + + In [2]: 1+1 + Code ran in 3.40410006174352e-05 + Out[2]: 2 + + + +Hygiene and Mangling +-------------------- + +The ast transformer above is not hygienic, it may not work if the user code use +the same variable names as the ones used in the template. For example. + +To help with this by default the `ReplaceCodeTransformer` will mangle all names +staring with 3 underscores. This is a simple heuristic that should work in most +case, but can be cumbersome in some case. We provide a `Mangler` class that can +be overridden to change the mangling heuristic, or simply use the `mangle_all` +utility function. It will _try_ to mangle all names (except `__ret__` and +`__code__`), but this include builtins (``print``, ``range``, ``type``) and +replace those by invalid identifiers py prepending ``mangle-``: +``mangle-print``, ``mangle-range``, ``mangle-type`` etc. This is not a problem +as currently Python AST support invalid identifiers, but it may not be the case +in the future. + +You can set `ReplaceCodeTransformer.debug=True` and +`ReplaceCodeTransformer.mangler.debug=True` to see the code after mangling and +transforming: + +.. code-block:: python + + + In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer, mangle_all + ...: + ...: template = ''' + ...: from builtins import type, print + ...: from time import perf_counter + ...: now = perf_counter() + ...: __code__ + ...: print(f"Code ran in {perf_counter()-now}") + ...: __ret__''' + ...: + ...: transformer = ReplaceCodeTransformer.from_string(template, mangling_predicate=mangle_all) + + + In [2]: transformer.debug = True + ...: transformer.mangler.debug = True + ...: get_ipython().ast_transformers.append(transformer) + + In [3]: 1+1 + Mangling Alias mangle-type + Mangling Alias mangle-print + Mangling Alias mangle-perf_counter + Mangling now + Mangling perf_counter + Not mangling __code__ + Mangling print + Mangling perf_counter + Mangling now + Not mangling __ret__ + ---- Transformed code ---- + from builtins import type as mangle-type, print as mangle-print + from time import perf_counter as mangle-perf_counter + mangle-now = mangle-perf_counter() + ret-tmp = 1 + 1 + mangle-print(f'Code ran in {mangle-perf_counter() - mangle-now}') + ret-tmp + ---- ---------------- ---- + Code ran in 0.00013654199938173406 + Out[3]: 2 + + +""" + +__skip_doctest__ = True + + +from ast import ( + NodeTransformer, + Store, + Load, + Name, + Expr, + Assign, + Module, + Import, + ImportFrom, +) +import ast +import copy + +from typing import Dict, Optional, Union + + +mangle_all = lambda name: False if name in ("__ret__", "__code__") else True + + +class Mangler(NodeTransformer): + """ + Mangle given names in and ast tree to make sure they do not conflict with + user code. + """ + + enabled: bool = True + debug: bool = False + + def log(self, *args, **kwargs): + if self.debug: + print(*args, **kwargs) + + def __init__(self, predicate=None): + if predicate is None: + predicate = lambda name: name.startswith("___") + self.predicate = predicate + + def visit_Name(self, node): + if self.predicate(node.id): + self.log("Mangling", node.id) + # Once in the ast we do not need + # names to be valid identifiers. + node.id = "mangle-" + node.id + else: + self.log("Not mangling", node.id) + return node + + def visit_FunctionDef(self, node): + if self.predicate(node.name): + self.log("Mangling", node.name) + node.name = "mangle-" + node.name + else: + self.log("Not mangling", node.name) + + for arg in node.args.args: + if self.predicate(arg.arg): + self.log("Mangling function arg", arg.arg) + arg.arg = "mangle-" + arg.arg + else: + self.log("Not mangling function arg", arg.arg) + return self.generic_visit(node) + + def visit_ImportFrom(self, node: ImportFrom): + return self._visit_Import_and_ImportFrom(node) + + def visit_Import(self, node: Import): + return self._visit_Import_and_ImportFrom(node) + + def _visit_Import_and_ImportFrom(self, node: Union[Import, ImportFrom]): + for alias in node.names: + asname = alias.name if alias.asname is None else alias.asname + if self.predicate(asname): + new_name: str = "mangle-" + asname + self.log("Mangling Alias", new_name) + alias.asname = new_name + else: + self.log("Not mangling Alias", alias.asname) + return node + + +class ReplaceCodeTransformer(NodeTransformer): + enabled: bool = True + debug: bool = False + mangler: Mangler + + def __init__( + self, template: Module, mapping: Optional[Dict] = None, mangling_predicate=None + ): + assert isinstance(mapping, (dict, type(None))) + assert isinstance(mangling_predicate, (type(None), type(lambda: None))) + assert isinstance(template, ast.Module) + self.template = template + self.mangler = Mangler(predicate=mangling_predicate) + if mapping is None: + mapping = {} + self.mapping = mapping + + @classmethod + def from_string( + cls, template: str, mapping: Optional[Dict] = None, mangling_predicate=None + ): + return cls( + ast.parse(template), mapping=mapping, mangling_predicate=mangling_predicate + ) + + def visit_Module(self, code): + if not self.enabled: + return code + # if not isinstance(code, ast.Module): + # recursively called... + # return generic_visit(self, code) + last = code.body[-1] + if isinstance(last, Expr): + code.body.pop() + code.body.append(Assign([Name("ret-tmp", ctx=Store())], value=last.value)) + ast.fix_missing_locations(code) + ret = Expr(value=Name("ret-tmp", ctx=Load())) + ret = ast.fix_missing_locations(ret) + self.mapping["__ret__"] = ret + else: + self.mapping["__ret__"] = ast.parse("None").body[0] + self.mapping["__code__"] = code.body + tpl = ast.fix_missing_locations(self.template) + + tx = copy.deepcopy(tpl) + tx = self.mangler.visit(tx) + node = self.generic_visit(tx) + node_2 = ast.fix_missing_locations(node) + if self.debug: + print("---- Transformed code ----") + print(ast.unparse(node_2)) + print("---- ---------------- ----") + return node_2 + + # this does not work as the name might be in a list and one might want to extend the list. + # def visit_Name(self, name): + # if name.id in self.mapping and name.id == "__ret__": + # print(name, "in mapping") + # if isinstance(name.ctx, ast.Store): + # return Name("tmp", ctx=Store()) + # else: + # return copy.deepcopy(self.mapping[name.id]) + # return name + + def visit_Expr(self, expr): + if isinstance(expr.value, Name) and expr.value.id in self.mapping: + if self.mapping[expr.value.id] is not None: + return copy.deepcopy(self.mapping[expr.value.id]) + return self.generic_visit(expr) diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/auto.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/auto.py new file mode 100644 index 0000000000000000000000000000000000000000..329e7acdbe518725443352523112f4805322e8fe --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/auto.py @@ -0,0 +1,144 @@ +"""Implementation of magic functions that control various automatic behaviors. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012 The IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +# Our own packages +from IPython.core.magic import Bunch, Magics, magics_class, line_magic +from IPython.testing.skipdoctest import skip_doctest +from logging import error + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +@magics_class +class AutoMagics(Magics): + """Magics that control various autoX behaviors.""" + + def __init__(self, shell): + super(AutoMagics, self).__init__(shell) + # namespace for holding state we may need + self._magic_state = Bunch() + + @line_magic + def automagic(self, parameter_s=''): + """Make magic functions callable without having to type the initial %. + + Without arguments toggles on/off (when off, you must call it as + %automagic, of course). With arguments it sets the value, and you can + use any of (case insensitive): + + - on, 1, True: to activate + + - off, 0, False: to deactivate. + + Note that magic functions have lowest priority, so if there's a + variable whose name collides with that of a magic fn, automagic won't + work for that function (you get the variable instead). However, if you + delete the variable (del var), the previously shadowed magic function + becomes visible to automagic again.""" + + arg = parameter_s.lower() + mman = self.shell.magics_manager + if arg in ('on', '1', 'true'): + val = True + elif arg in ('off', '0', 'false'): + val = False + else: + val = not mman.auto_magic + mman.auto_magic = val + print('\n' + self.shell.magics_manager.auto_status()) + + @skip_doctest + @line_magic + def autocall(self, parameter_s=''): + """Make functions callable without having to type parentheses. + + Usage: + + %autocall [mode] + + The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the + value is toggled on and off (remembering the previous state). + + In more detail, these values mean: + + 0 -> fully disabled + + 1 -> active, but do not apply if there are no arguments on the line. + + In this mode, you get:: + + In [1]: callable + Out[1]: + + In [2]: callable 'hello' + ------> callable('hello') + Out[2]: False + + 2 -> Active always. Even if no arguments are present, the callable + object is called:: + + In [2]: float + ------> float() + Out[2]: 0.0 + + Note that even with autocall off, you can still use '/' at the start of + a line to treat the first argument on the command line as a function + and add parentheses to it:: + + In [8]: /str 43 + ------> str(43) + Out[8]: '43' + + # all-random (note for auto-testing) + """ + + valid_modes = { + 0: "Off", + 1: "Smart", + 2: "Full", + } + + def errorMessage() -> str: + error = "Valid modes: " + for k, v in valid_modes.items(): + error += str(k) + "->" + v + ", " + error = error[:-2] # remove tailing `, ` after last element + return error + + if parameter_s: + if parameter_s not in map(str, valid_modes.keys()): + error(errorMessage()) + return + arg = int(parameter_s) + else: + arg = 'toggle' + + if arg not in (*list(valid_modes.keys()), "toggle"): + error(errorMessage()) + return + + if arg in (valid_modes.keys()): + self.shell.autocall = arg + else: # toggle + if self.shell.autocall: + self._magic_state.autocall_save = self.shell.autocall + self.shell.autocall = 0 + else: + try: + self.shell.autocall = self._magic_state.autocall_save + except AttributeError: + self.shell.autocall = self._magic_state.autocall_save = 1 + + print("Automatic calling is:", list(valid_modes.values())[self.shell.autocall]) diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/basic.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..ec1ab53233718e5b9d50dd85986e7bf63e3b37c1 --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/basic.py @@ -0,0 +1,674 @@ +"""Implementation of basic magic functions.""" + + +from logging import error +import io +import os +from pprint import pformat +import sys +from warnings import warn + +from traitlets.utils.importstring import import_item +from IPython.core import magic_arguments, page +from IPython.core.error import UsageError +from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes +from IPython.utils.text import format_screen, dedent, indent +from IPython.testing.skipdoctest import skip_doctest +from IPython.utils.ipstruct import Struct + + +class MagicsDisplay: + def __init__(self, magics_manager, ignore=None): + self.ignore = ignore if ignore else [] + self.magics_manager = magics_manager + + def _lsmagic(self): + """The main implementation of the %lsmagic""" + mesc = magic_escapes['line'] + cesc = magic_escapes['cell'] + mman = self.magics_manager + magics = mman.lsmagic() + out = ['Available line magics:', + mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])), + '', + 'Available cell magics:', + cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])), + '', + mman.auto_status()] + return '\n'.join(out) + + def _repr_pretty_(self, p, cycle): + p.text(self._lsmagic()) + + def __repr__(self): + return self.__str__() + + def __str__(self): + return self._lsmagic() + + def _jsonable(self): + """turn magics dict into jsonable dict of the same structure + + replaces object instances with their class names as strings + """ + magic_dict = {} + mman = self.magics_manager + magics = mman.lsmagic() + for key, subdict in magics.items(): + d = {} + magic_dict[key] = d + for name, obj in subdict.items(): + try: + classname = obj.__self__.__class__.__name__ + except AttributeError: + classname = 'Other' + + d[name] = classname + return magic_dict + + def _repr_json_(self): + return self._jsonable() + + +@magics_class +class BasicMagics(Magics): + """Magics that provide central IPython functionality. + + These are various magics that don't fit into specific categories but that + are all part of the base 'IPython experience'.""" + + @skip_doctest + @magic_arguments.magic_arguments() + @magic_arguments.argument( + '-l', '--line', action='store_true', + help="""Create a line magic alias.""" + ) + @magic_arguments.argument( + '-c', '--cell', action='store_true', + help="""Create a cell magic alias.""" + ) + @magic_arguments.argument( + 'name', + help="""Name of the magic to be created.""" + ) + @magic_arguments.argument( + 'target', + help="""Name of the existing line or cell magic.""" + ) + @magic_arguments.argument( + '-p', '--params', default=None, + help="""Parameters passed to the magic function.""" + ) + @line_magic + def alias_magic(self, line=''): + """Create an alias for an existing line or cell magic. + + Examples + -------- + :: + + In [1]: %alias_magic t timeit + Created `%t` as an alias for `%timeit`. + Created `%%t` as an alias for `%%timeit`. + + In [2]: %t -n1 pass + 107 ns ± 43.6 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) + + In [3]: %%t -n1 + ...: pass + ...: + 107 ns ± 58.3 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) + + In [4]: %alias_magic --cell whereami pwd + UsageError: Cell magic function `%%pwd` not found. + In [5]: %alias_magic --line whereami pwd + Created `%whereami` as an alias for `%pwd`. + + In [6]: %whereami + Out[6]: '/home/testuser' + + In [7]: %alias_magic h history -p "-l 30" --line + Created `%h` as an alias for `%history -l 30`. + """ + + args = magic_arguments.parse_argstring(self.alias_magic, line) + shell = self.shell + mman = self.shell.magics_manager + escs = ''.join(magic_escapes.values()) + + target = args.target.lstrip(escs) + name = args.name.lstrip(escs) + + params = args.params + if (params and + ((params.startswith('"') and params.endswith('"')) + or (params.startswith("'") and params.endswith("'")))): + params = params[1:-1] + + # Find the requested magics. + m_line = shell.find_magic(target, 'line') + m_cell = shell.find_magic(target, 'cell') + if args.line and m_line is None: + raise UsageError('Line magic function `%s%s` not found.' % + (magic_escapes['line'], target)) + if args.cell and m_cell is None: + raise UsageError('Cell magic function `%s%s` not found.' % + (magic_escapes['cell'], target)) + + # If --line and --cell are not specified, default to the ones + # that are available. + if not args.line and not args.cell: + if not m_line and not m_cell: + raise UsageError( + 'No line or cell magic with name `%s` found.' % target + ) + args.line = bool(m_line) + args.cell = bool(m_cell) + + params_str = "" if params is None else " " + params + + if args.line: + mman.register_alias(name, target, 'line', params) + print('Created `%s%s` as an alias for `%s%s%s`.' % ( + magic_escapes['line'], name, + magic_escapes['line'], target, params_str)) + + if args.cell: + mman.register_alias(name, target, 'cell', params) + print('Created `%s%s` as an alias for `%s%s%s`.' % ( + magic_escapes['cell'], name, + magic_escapes['cell'], target, params_str)) + + @line_magic + def lsmagic(self, parameter_s=''): + """List currently available magic functions.""" + return MagicsDisplay(self.shell.magics_manager, ignore=[]) + + def _magic_docs(self, brief=False, rest=False): + """Return docstrings from magic functions.""" + mman = self.shell.magics_manager + docs = mman.lsmagic_docs(brief, missing='No documentation') + + if rest: + format_string = '**%s%s**::\n\n%s\n\n' + else: + format_string = '%s%s:\n%s\n' + + return ''.join( + [format_string % (magic_escapes['line'], fname, + indent(dedent(fndoc))) + for fname, fndoc in sorted(docs['line'].items())] + + + [format_string % (magic_escapes['cell'], fname, + indent(dedent(fndoc))) + for fname, fndoc in sorted(docs['cell'].items())] + ) + + @line_magic + def magic(self, parameter_s=''): + """Print information about the magic function system. + + Supported formats: -latex, -brief, -rest + """ + + mode = '' + try: + mode = parameter_s.split()[0][1:] + except IndexError: + pass + + brief = (mode == 'brief') + rest = (mode == 'rest') + magic_docs = self._magic_docs(brief, rest) + + if mode == 'latex': + print(self.format_latex(magic_docs)) + return + else: + magic_docs = format_screen(magic_docs) + + out = [""" +IPython's 'magic' functions +=========================== + +The magic function system provides a series of functions which allow you to +control the behavior of IPython itself, plus a lot of system-type +features. There are two kinds of magics, line-oriented and cell-oriented. + +Line magics are prefixed with the % character and work much like OS +command-line calls: they get as an argument the rest of the line, where +arguments are passed without parentheses or quotes. For example, this will +time the given statement:: + + %timeit range(1000) + +Cell magics are prefixed with a double %%, and they are functions that get as +an argument not only the rest of the line, but also the lines below it in a +separate argument. These magics are called with two arguments: the rest of the +call line and the body of the cell, consisting of the lines below the first. +For example:: + + %%timeit x = numpy.random.randn((100, 100)) + numpy.linalg.svd(x) + +will time the execution of the numpy svd routine, running the assignment of x +as part of the setup phase, which is not timed. + +In a line-oriented client (the terminal or Qt console IPython), starting a new +input with %% will automatically enter cell mode, and IPython will continue +reading input until a blank line is given. In the notebook, simply type the +whole cell as one entity, but keep in mind that the %% escape can only be at +the very start of the cell. + +NOTE: If you have 'automagic' enabled (via the command line option or with the +%automagic function), you don't need to type in the % explicitly for line +magics; cell magics always require an explicit '%%' escape. By default, +IPython ships with automagic on, so you should only rarely need the % escape. + +Example: typing '%cd mydir' (without the quotes) changes your working directory +to 'mydir', if it exists. + +For a list of the available magic functions, use %lsmagic. For a description +of any of them, type %magic_name?, e.g. '%cd?'. + +Currently the magic system has the following functions:""", + magic_docs, + "Summary of magic functions (from %slsmagic):" % magic_escapes['line'], + str(self.lsmagic()), + ] + page.page('\n'.join(out)) + + + @line_magic + def page(self, parameter_s=''): + """Pretty print the object and display it through a pager. + + %page [options] OBJECT + + If no object is given, use _ (last output). + + Options: + + -r: page str(object), don't pretty-print it.""" + + # After a function contributed by Olivier Aubert, slightly modified. + + # Process options/args + opts, args = self.parse_options(parameter_s, 'r') + raw = 'r' in opts + + oname = args and args or '_' + info = self.shell._ofind(oname) + if info.found: + if raw: + txt = str(info.obj) + else: + txt = pformat(info.obj) + page.page(txt) + else: + print('Object `%s` not found' % oname) + + @line_magic + def pprint(self, parameter_s=''): + """Toggle pretty printing on/off.""" + ptformatter = self.shell.display_formatter.formatters['text/plain'] + ptformatter.pprint = bool(1 - ptformatter.pprint) + print('Pretty printing has been turned', + ['OFF','ON'][ptformatter.pprint]) + + @line_magic + def colors(self, parameter_s=''): + """Switch color scheme/theme globally for IPython + + Examples + -------- + To get a plain black and white terminal:: + + %colors nocolor + """ + + + new_theme = parameter_s.strip() + if not new_theme: + from IPython.utils.PyColorize import theme_table + + raise UsageError( + "%colors: you must specify a color theme. See '%colors?'." + f" Available themes: {list(theme_table.keys())}" + ) + + self.shell.colors = new_theme + + @line_magic + def xmode(self, parameter_s=''): + """Switch modes for the exception handlers. + + Valid modes: Plain, Context, Verbose, and Minimal. + + If called without arguments, acts as a toggle. + + When in verbose mode the value `--show` (and `--hide`) + will respectively show (or hide) frames with ``__tracebackhide__ = + True`` value set. + """ + + def xmode_switch_err(name): + warn('Error changing %s exception modes.\n%s' % + (name,sys.exc_info()[1])) + + shell = self.shell + if parameter_s.strip() == "--show": + shell.InteractiveTB.skip_hidden = False + return + if parameter_s.strip() == "--hide": + shell.InteractiveTB.skip_hidden = True + return + + new_mode = parameter_s.strip().capitalize() + try: + shell.InteractiveTB.set_mode(mode=new_mode) + print('Exception reporting mode:',shell.InteractiveTB.mode) + except: + raise + xmode_switch_err('user') + + @line_magic + def quickref(self, arg): + """ Show a quick reference sheet """ + from IPython.core.usage import quick_reference + qr = quick_reference + self._magic_docs(brief=True) + page.page(qr) + + @line_magic + def doctest_mode(self, parameter_s=''): + """Toggle doctest mode on and off. + + This mode is intended to make IPython behave as much as possible like a + plain Python shell, from the perspective of how its prompts, exceptions + and output look. This makes it easy to copy and paste parts of a + session into doctests. It does so by: + + - Changing the prompts to the classic ``>>>`` ones. + - Changing the exception reporting mode to 'Plain'. + - Disabling pretty-printing of output. + + Note that IPython also supports the pasting of code snippets that have + leading '>>>' and '...' prompts in them. This means that you can paste + doctests from files or docstrings (even if they have leading + whitespace), and the code will execute correctly. You can then use + '%history -t' to see the translated history; this will give you the + input after removal of all the leading prompts and whitespace, which + can be pasted back into an editor. + + With these features, you can switch into this mode easily whenever you + need to do testing and changes to doctests, without having to leave + your existing IPython session. + """ + + # Shorthands + shell = self.shell + meta = shell.meta + disp_formatter = self.shell.display_formatter + ptformatter = disp_formatter.formatters['text/plain'] + # dstore is a data store kept in the instance metadata bag to track any + # changes we make, so we can undo them later. + dstore = meta.setdefault('doctest_mode',Struct()) + save_dstore = dstore.setdefault + + # save a few values we'll need to recover later + mode = save_dstore('mode',False) + save_dstore('rc_pprint',ptformatter.pprint) + save_dstore('xmode',shell.InteractiveTB.mode) + save_dstore('rc_separate_out',shell.separate_out) + save_dstore('rc_separate_out2',shell.separate_out2) + save_dstore('rc_separate_in',shell.separate_in) + save_dstore('rc_active_types',disp_formatter.active_types) + + if not mode: + # turn on + + # Prompt separators like plain python + shell.separate_in = '' + shell.separate_out = '' + shell.separate_out2 = '' + + + ptformatter.pprint = False + disp_formatter.active_types = ['text/plain'] + + shell.run_line_magic("xmode", "Plain") + else: + # turn off + shell.separate_in = dstore.rc_separate_in + + shell.separate_out = dstore.rc_separate_out + shell.separate_out2 = dstore.rc_separate_out2 + + ptformatter.pprint = dstore.rc_pprint + disp_formatter.active_types = dstore.rc_active_types + + shell.run_line_magic("xmode", dstore.xmode) + + # mode here is the state before we switch; switch_doctest_mode takes + # the mode we're switching to. + shell.switch_doctest_mode(not mode) + + # Store new mode and inform + dstore.mode = bool(not mode) + mode_label = ['OFF','ON'][dstore.mode] + print('Doctest mode is:', mode_label) + + @line_magic + def gui(self, parameter_s=''): + """Enable or disable IPython GUI event loop integration. + + %gui [GUINAME] + + This magic replaces IPython's threaded shells that were activated + using the (pylab/wthread/etc.) command line flags. GUI toolkits + can now be enabled at runtime and keyboard + interrupts should work without any problems. The following toolkits + are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX):: + + %gui wx # enable wxPython event loop integration + %gui qt # enable PyQt/PySide event loop integration + # with the latest version available. + %gui qt6 # enable PyQt6/PySide6 event loop integration + %gui qt5 # enable PyQt5/PySide2 event loop integration + %gui gtk # enable PyGTK event loop integration + %gui gtk3 # enable Gtk3 event loop integration + %gui gtk4 # enable Gtk4 event loop integration + %gui tk # enable Tk event loop integration + %gui osx # enable Cocoa event loop integration + # (requires %matplotlib 1.1) + %gui # disable all event loop integration + + WARNING: after any of these has been called you can simply create + an application object, but DO NOT start the event loop yourself, as + we have already handled that. + """ + opts, arg = self.parse_options(parameter_s, '') + if arg=='': arg = None + try: + return self.shell.enable_gui(arg) + except Exception as e: + # print simple error message, rather than traceback if we can't + # hook up the GUI + error(str(e)) + + @skip_doctest + @line_magic + def precision(self, s=''): + """Set floating point precision for pretty printing. + + Can set either integer precision or a format string. + + If numpy has been imported and precision is an int, + numpy display precision will also be set, via ``numpy.set_printoptions``. + + If no argument is given, defaults will be restored. + + Examples + -------- + :: + + In [1]: from math import pi + + In [2]: %precision 3 + Out[2]: '%.3f' + + In [3]: pi + Out[3]: 3.142 + + In [4]: %precision %i + Out[4]: '%i' + + In [5]: pi + Out[5]: 3 + + In [6]: %precision %e + Out[6]: '%e' + + In [7]: pi**10 + Out[7]: 9.364805e+04 + + In [8]: %precision + Out[8]: '%r' + + In [9]: pi**10 + Out[9]: 93648.047476082982 + """ + ptformatter = self.shell.display_formatter.formatters['text/plain'] + ptformatter.float_precision = s + return ptformatter.float_format + + @magic_arguments.magic_arguments() + @magic_arguments.argument( + 'filename', type=str, + help='Notebook name or filename' + ) + @line_magic + def notebook(self, s): + """Export and convert IPython notebooks. + + This function can export the current IPython history to a notebook file. + For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb". + """ + args = magic_arguments.parse_argstring(self.notebook, s) + outfname = os.path.expanduser(args.filename) + + from nbformat import write, v4 + + cells = [] + hist = list(self.shell.history_manager.get_range()) + outputs = self.shell.history_manager.outputs + exceptions = self.shell.history_manager.exceptions + + if(len(hist)<=1): + raise ValueError('History is empty, cannot export') + for session, execution_count, source in hist[:-1]: + cell = v4.new_code_cell(execution_count=execution_count, source=source) + for output in outputs[execution_count]: + for mime_type, data in output.bundle.items(): + if output.output_type == "out_stream": + cell.outputs.append(v4.new_output("stream", text=[data])) + elif output.output_type == "err_stream": + err_output = v4.new_output("stream", text=[data]) + err_output.name = "stderr" + cell.outputs.append(err_output) + elif output.output_type == "execute_result": + cell.outputs.append( + v4.new_output( + "execute_result", + data={mime_type: data}, + execution_count=execution_count, + ) + ) + elif output.output_type == "display_data": + cell.outputs.append( + v4.new_output( + "display_data", + data={mime_type: data}, + ) + ) + else: + raise ValueError(f"Unknown output type: {output.output_type}") + + # Check if this execution_count is in exceptions (current session) + if execution_count in exceptions: + cell.outputs.append( + v4.new_output("error", **exceptions[execution_count]) + ) + cells.append(cell) + + nb = v4.new_notebook(cells=cells) + with io.open(outfname, "w", encoding="utf-8") as f: + write(nb, f, version=4) + +@magics_class +class AsyncMagics(BasicMagics): + + @line_magic + def autoawait(self, parameter_s): + """ + Allow to change the status of the autoawait option. + + This allow you to set a specific asynchronous code runner. + + If no value is passed, print the currently used asynchronous integration + and whether it is activated. + + It can take a number of value evaluated in the following order: + + - False/false/off deactivate autoawait integration + - True/true/on activate autoawait integration using configured default + loop + - asyncio/curio/trio activate autoawait integration and use integration + with said library. + + - `sync` turn on the pseudo-sync integration (mostly used for + `IPython.embed()` which does not run IPython with a real eventloop and + deactivate running asynchronous code. Turning on Asynchronous code with + the pseudo sync loop is undefined behavior and may lead IPython to crash. + + If the passed parameter does not match any of the above and is a python + identifier, get said object from user namespace and set it as the + runner, and activate autoawait. + + If the object is a fully qualified object name, attempt to import it and + set it as the runner, and activate autoawait. + + The exact behavior of autoawait is experimental and subject to change + across version of IPython and Python. + """ + + param = parameter_s.strip() + d = {True: "on", False: "off"} + + if not param: + print("IPython autoawait is `{}`, and set to use `{}`".format( + d[self.shell.autoawait], + self.shell.loop_runner + )) + return None + + if param.lower() in ('false', 'off'): + self.shell.autoawait = False + return None + if param.lower() in ('true', 'on'): + self.shell.autoawait = True + return None + + if param in self.shell.loop_runner_map: + self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param] + return None + + if param in self.shell.user_ns : + self.shell.loop_runner = self.shell.user_ns[param] + self.shell.autoawait = True + return None + + runner = import_item(param) + + self.shell.loop_runner = runner + self.shell.autoawait = True diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/code.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/code.py new file mode 100644 index 0000000000000000000000000000000000000000..191e55ab6e55562e03cb7de068c16c43ea445a29 --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/code.py @@ -0,0 +1,757 @@ +"""Implementation of code management magic functions. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012 The IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +# Stdlib +import inspect +import io +import os +import re +import sys +import ast +from itertools import chain +from urllib.request import Request, urlopen +from urllib.parse import urlencode +from pathlib import Path + +# Our own packages +from IPython.core.error import TryNext, StdinNotImplementedError, UsageError +from IPython.core.macro import Macro +from IPython.core.magic import Magics, magics_class, line_magic +from IPython.core.oinspect import find_file, find_source_lines +from IPython.core.release import version +from IPython.testing.skipdoctest import skip_doctest +from IPython.utils.contexts import preserve_keys +from IPython.utils.path import get_py_filename +from warnings import warn +from logging import error +from IPython.utils.text import get_text_list + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +# Used for exception handling in magic_edit +class MacroToEdit(ValueError): pass + +ipython_input_pat = re.compile(r"$") + +# To match, e.g. 8-10 1:5 :10 3- +range_re = re.compile(r""" +(?P\d+)? +((?P[\-:]) + (?P\d+)?)? +$""", re.VERBOSE) + + +def extract_code_ranges(ranges_str): + """Turn a string of range for %%load into 2-tuples of (start, stop) + ready to use as a slice of the content split by lines. + + Examples + -------- + list(extract_input_ranges("5-10 2")) + [(4, 10), (1, 2)] + """ + for range_str in ranges_str.split(): + rmatch = range_re.match(range_str) + if not rmatch: + continue + sep = rmatch.group("sep") + start = rmatch.group("start") + end = rmatch.group("end") + + if sep == '-': + start = int(start) - 1 if start else None + end = int(end) if end else None + elif sep == ':': + start = int(start) - 1 if start else None + end = int(end) - 1 if end else None + else: + end = int(start) + start = int(start) - 1 + yield (start, end) + + +def extract_symbols(code, symbols): + """ + Return a tuple (blocks, not_found) + where ``blocks`` is a list of code fragments + for each symbol parsed from code, and ``not_found`` are + symbols not found in the code. + + For example:: + + In [1]: code = '''a = 10 + ...: def b(): return 42 + ...: class A: pass''' + + In [2]: extract_symbols(code, 'A,b,z') + Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z']) + """ + symbols = symbols.split(',') + + # this will raise SyntaxError if code isn't valid Python + py_code = ast.parse(code) + + marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body] + code = code.split('\n') + + symbols_lines = {} + + # we already know the start_lineno of each symbol (marks). + # To find each end_lineno, we traverse in reverse order until each + # non-blank line + end = len(code) + for name, start in reversed(marks): + while not code[end - 1].strip(): + end -= 1 + if name: + symbols_lines[name] = (start - 1, end) + end = start - 1 + + # Now symbols_lines is a map + # {'symbol_name': (start_lineno, end_lineno), ...} + + # fill a list with chunks of codes for each requested symbol + blocks = [] + not_found = [] + for symbol in symbols: + if symbol in symbols_lines: + start, end = symbols_lines[symbol] + blocks.append('\n'.join(code[start:end]) + '\n') + else: + not_found.append(symbol) + + return blocks, not_found + +def strip_initial_indent(lines): + """For %load, strip indent from lines until finding an unindented line. + + https://github.com/ipython/ipython/issues/9775 + """ + indent_re = re.compile(r'\s+') + + it = iter(lines) + first_line = next(it) + indent_match = indent_re.match(first_line) + + if indent_match: + # First line was indented + indent = indent_match.group() + yield first_line[len(indent):] + + for line in it: + if line.startswith(indent): + yield line[len(indent) :] + elif line in ("\n", "\r\n") or len(line) == 0: + yield line + else: + # Less indented than the first line - stop dedenting + yield line + break + else: + yield first_line + + # Pass the remaining lines through without dedenting + for line in it: + yield line + + +class InteractivelyDefined(Exception): + """Exception for interactively defined variable in magic_edit""" + def __init__(self, index): + self.index = index + + +@magics_class +class CodeMagics(Magics): + """Magics related to code management (loading, saving, editing, ...).""" + + def __init__(self, *args, **kwargs): + self._knowntemps = set() + super(CodeMagics, self).__init__(*args, **kwargs) + + @line_magic + def save(self, parameter_s=''): + """Save a set of lines or a macro to a given filename. + + Usage:\\ + %save [options] filename [history] + + Options: + + -r: use 'raw' input. By default, the 'processed' history is used, + so that magics are loaded in their transformed version to valid + Python. If this option is given, the raw input as typed at the + command line is used instead. + + -f: force overwrite. If file exists, %save will prompt for overwrite + unless -f is given. + + -a: append to the file instead of overwriting it. + + The history argument uses the same syntax as %history for input ranges, + then saves the lines to the filename you specify. + + If no ranges are specified, saves history of the current session up to + this point. + + It adds a '.py' extension to the file if you don't do so yourself, and + it asks for confirmation before overwriting existing files. + + If `-r` option is used, the default extension is `.ipy`. + """ + + opts,args = self.parse_options(parameter_s,'fra',mode='list') + if not args: + raise UsageError('Missing filename.') + raw = 'r' in opts + force = 'f' in opts + append = 'a' in opts + mode = 'a' if append else 'w' + ext = '.ipy' if raw else '.py' + fname, codefrom = args[0], " ".join(args[1:]) + if not fname.endswith(('.py','.ipy')): + fname += ext + fname = os.path.expanduser(fname) + file_exists = os.path.isfile(fname) + if file_exists and not force and not append: + try: + overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n') + except StdinNotImplementedError: + print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)) + return + if not overwrite : + print('Operation cancelled.') + return + try: + cmds = self.shell.find_user_code(codefrom,raw) + except (TypeError, ValueError) as e: + print(e.args[0]) + return + with io.open(fname, mode, encoding="utf-8") as f: + if not file_exists or not append: + f.write("# coding: utf-8\n") + f.write(cmds) + # make sure we end on a newline + if not cmds.endswith('\n'): + f.write('\n') + print('The following commands were written to file `%s`:' % fname) + print(cmds) + + @line_magic + def pastebin(self, parameter_s=''): + """Upload code to dpaste.com, returning the URL. + + Usage:\\ + %pastebin [-d "Custom description"][-e 24] 1-7 + + The argument can be an input history range, a filename, or the name of a + string or macro. + + If no arguments are given, uploads the history of this session up to + this point. + + Options: + + -d: Pass a custom description. The default will say + "Pasted from IPython". + -e: Pass number of days for the link to be expired. + The default will be 7 days. + """ + opts, args = self.parse_options(parameter_s, "d:e:") + + try: + code = self.shell.find_user_code(args) + except (ValueError, TypeError) as e: + print(e.args[0]) + return + + expiry_days = 7 + try: + expiry_days = int(opts.get("e", 7)) + except ValueError as e: + print(e.args[0].capitalize()) + return + if expiry_days < 1 or expiry_days > 365: + print("Expiry days should be in range of 1 to 365") + return + + post_data = urlencode( + { + "title": opts.get("d", "Pasted from IPython"), + "syntax": "python", + "content": code, + "expiry_days": expiry_days, + } + ).encode("utf-8") + + request = Request( + "https://dpaste.com/api/v2/", + headers={"User-Agent": "IPython v{}".format(version)}, + ) + response = urlopen(request, post_data) + return response.headers.get('Location') + + @line_magic + def loadpy(self, arg_s): + """Alias of `%load` + + `%loadpy` has gained some flexibility and dropped the requirement of a `.py` + extension. So it has been renamed simply into %load. You can look at + `%load`'s docstring for more info. + """ + self.load(arg_s) + + @line_magic + def load(self, arg_s): + """Load code into the current frontend. + + Usage:\\ + %load [options] source + + where source can be a filename, URL, input history range, macro, or + element in the user namespace + + If no arguments are given, loads the history of this session up to this + point. + + Options: + + -r : Specify lines or ranges of lines to load from the source. + Ranges could be specified as x-y (x..y) or in python-style x:y + (x..(y-1)). Both limits x and y can be left blank (meaning the + beginning and end of the file, respectively). + + -s : Specify function or classes to load from python source. + + -y : Don't ask confirmation for loading source above 200 000 characters. + + -n : Include the user's namespace when searching for source code. + + This magic command can either take a local filename, a URL, an history + range (see %history) or a macro as argument, it will prompt for + confirmation before loading source with more than 200 000 characters, unless + -y flag is passed or if the frontend does not support raw_input:: + + %load + %load myscript.py + %load 7-27 + %load myMacro + %load http://www.example.com/myscript.py + %load -r 5-10 myscript.py + %load -r 10-20,30,40: foo.py + %load -s MyClass,wonder_function myscript.py + %load -n MyClass + %load -n my_module.wonder_function + """ + opts,args = self.parse_options(arg_s,'yns:r:') + search_ns = 'n' in opts + contents = self.shell.find_user_code(args, search_ns=search_ns) + + if 's' in opts: + try: + blocks, not_found = extract_symbols(contents, opts['s']) + except SyntaxError: + # non python code + error("Unable to parse the input as valid Python code") + return + + if len(not_found) == 1: + warn('The symbol `%s` was not found' % not_found[0]) + elif len(not_found) > 1: + warn('The symbols %s were not found' % get_text_list(not_found, + wrap_item_with='`') + ) + + contents = '\n'.join(blocks) + + if 'r' in opts: + ranges = opts['r'].replace(',', ' ') + lines = contents.split('\n') + slices = extract_code_ranges(ranges) + contents = [lines[slice(*slc)] for slc in slices] + contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents))) + + l = len(contents) + + # 200 000 is ~ 2500 full 80 character lines + # so in average, more than 5000 lines + if l > 200000 and 'y' not in opts: + try: + ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\ + " (%d characters). Continue (y/[N]) ?" % l), default='n' ) + except StdinNotImplementedError: + #assume yes if raw input not implemented + ans = True + + if ans is False : + print('Operation cancelled.') + return + + contents = "# %load {}\n".format(arg_s) + contents + + self.shell.set_next_input(contents, replace=True) + + @staticmethod + def _find_edit_target(shell, args, opts, last_call): + """Utility method used by magic_edit to find what to edit.""" + + def make_filename(arg): + "Make a filename from the given args" + try: + filename = get_py_filename(arg) + except IOError: + # If it ends with .py but doesn't already exist, assume we want + # a new file. + if arg.endswith('.py'): + filename = arg + else: + filename = None + return filename + + # Set a few locals from the options for convenience: + opts_prev = 'p' in opts + opts_raw = 'r' in opts + + # custom exceptions + class DataIsObject(Exception): pass + + # Default line number value + lineno = opts.get('n',None) + + if opts_prev: + args = '_%s' % last_call[0] + if args not in shell.user_ns: + args = last_call[1] + + # by default this is done with temp files, except when the given + # arg is a filename + use_temp = True + + data = '' + + # First, see if the arguments should be a filename. + filename = make_filename(args) + if filename: + use_temp = False + elif args: + # Mode where user specifies ranges of lines, like in %macro. + data = shell.extract_input_lines(args, opts_raw) + if not data: + try: + # Load the parameter given as a variable. If not a string, + # process it as an object instead (below) + + # print('*** args',args,'type',type(args)) # dbg + data = eval(args, shell.user_ns) + if not isinstance(data, str): + raise DataIsObject + + except (NameError,SyntaxError): + # given argument is not a variable, try as a filename + filename = make_filename(args) + if filename is None: + warn("Argument given (%s) can't be found as a variable " + "or as a filename." % args) + return (None, None, None) + use_temp = False + + except DataIsObject as e: + # macros have a special edit function + if isinstance(data, Macro): + raise MacroToEdit(data) from e + + # For objects, try to edit the file where they are defined + filename = find_file(data) + if filename: + if 'fakemodule' in filename.lower() and \ + inspect.isclass(data): + # class created by %edit? Try to find source + # by looking for method definitions instead, the + # __module__ in those classes is FakeModule. + attrs = [getattr(data, aname) for aname in dir(data)] + for attr in attrs: + if not inspect.ismethod(attr): + continue + filename = find_file(attr) + if filename and \ + 'fakemodule' not in filename.lower(): + # change the attribute to be the edit + # target instead + data = attr + break + + m = ipython_input_pat.match(os.path.basename(filename)) + if m: + raise InteractivelyDefined(int(m.groups()[0])) from e + + datafile = 1 + if filename is None: + filename = make_filename(args) + datafile = 1 + if filename is not None: + # only warn about this if we get a real name + warn('Could not find file where `%s` is defined.\n' + 'Opening a file named `%s`' % (args, filename)) + # Now, make sure we can actually read the source (if it was + # in a temp file it's gone by now). + if datafile: + if lineno is None: + lineno = find_source_lines(data) + if lineno is None: + filename = make_filename(args) + if filename is None: + warn('The file where `%s` was defined ' + 'cannot be read or found.' % data) + return (None, None, None) + use_temp = False + + if use_temp: + filename = shell.mktempfile(data) + print('IPython will make a temporary file named:',filename) + + # use last_call to remember the state of the previous call, but don't + # let it be clobbered by successive '-p' calls. + try: + last_call[0] = shell.displayhook.prompt_count + if not opts_prev: + last_call[1] = args + except: + pass + + + return filename, lineno, use_temp + + def _edit_macro(self,mname,macro): + """open an editor with the macro data in a file""" + filename = self.shell.mktempfile(macro.value) + self.shell.hooks.editor(filename) + + # and make a new macro object, to replace the old one + mvalue = Path(filename).read_text(encoding="utf-8") + self.shell.user_ns[mname] = Macro(mvalue) + + @skip_doctest + @line_magic + def edit(self, parameter_s='',last_call=['','']): + """Bring up an editor and execute the resulting code. + + Usage: + %edit [options] [args] + + %edit runs IPython's editor hook. The default version of this hook is + set to call the editor specified by your $EDITOR environment variable. + If this isn't found, it will default to vi under Linux/Unix and to + notepad under Windows. See the end of this docstring for how to change + the editor hook. + + You can also set the value of this editor via the + ``TerminalInteractiveShell.editor`` option in your configuration file. + This is useful if you wish to use a different editor from your typical + default with IPython (and for Windows users who typically don't set + environment variables). + + This command allows you to conveniently edit multi-line code right in + your IPython session. + + If called without arguments, %edit opens up an empty editor with a + temporary file and will execute the contents of this file when you + close it (don't forget to save it!). + + + Options: + + -n : open the editor at a specified line number. By default, + the IPython editor hook uses the unix syntax 'editor +N filename', but + you can configure this by providing your own modified hook if your + favorite editor supports line-number specifications with a different + syntax. + + -p: this will call the editor with the same data as the previous time + it was used, regardless of how long ago (in your current session) it + was. + + -r: use 'raw' input. This option only applies to input taken from the + user's history. By default, the 'processed' history is used, so that + magics are loaded in their transformed version to valid Python. If + this option is given, the raw input as typed as the command line is + used instead. When you exit the editor, it will be executed by + IPython's own processor. + + -x: do not execute the edited code immediately upon exit. This is + mainly useful if you are editing programs which need to be called with + command line arguments, which you can then do using %run. + + + Arguments: + + If arguments are given, the following possibilities exist: + + - If the argument is a filename, IPython will load that into the + editor. It will execute its contents with execfile() when you exit, + loading any code in the file into your interactive namespace. + + - The arguments are ranges of input history, e.g. "7 ~1/4-6". + The syntax is the same as in the %history magic. + + - If the argument is a string variable, its contents are loaded + into the editor. You can thus edit any string which contains + python code (including the result of previous edits). + + - If the argument is the name of an object (other than a string), + IPython will try to locate the file where it was defined and open the + editor at the point where it is defined. You can use `%edit function` + to load an editor exactly at the point where 'function' is defined, + edit it and have the file be executed automatically. + + - If the object is a macro (see %macro for details), this opens up your + specified editor with a temporary file containing the macro's data. + Upon exit, the macro is reloaded with the contents of the file. + + Note: opening at an exact line is only supported under Unix, and some + editors (like kedit and gedit up to Gnome 2.8) do not understand the + '+NUMBER' parameter necessary for this feature. Good editors like + (X)Emacs, vi, jed, pico and joe all do. + + After executing your code, %edit will return as output the code you + typed in the editor (except when it was an existing file). This way + you can reload the code in further invocations of %edit as a variable, + via _ or Out[], where is the prompt number of + the output. + + Note that %edit is also available through the alias %ed. + + This is an example of creating a simple function inside the editor and + then modifying it. First, start up the editor:: + + In [1]: edit + Editing... done. Executing edited code... + Out[1]: 'def foo():\\n print("foo() was defined in an editing + session")\\n' + + We can then call the function foo():: + + In [2]: foo() + foo() was defined in an editing session + + Now we edit foo. IPython automatically loads the editor with the + (temporary) file where foo() was previously defined:: + + In [3]: edit foo + Editing... done. Executing edited code... + + And if we call foo() again we get the modified version:: + + In [4]: foo() + foo() has now been changed! + + Here is an example of how to edit a code snippet successive + times. First we call the editor:: + + In [5]: edit + Editing... done. Executing edited code... + hello + Out[5]: "print('hello')\\n" + + Now we call it again with the previous output (stored in _):: + + In [6]: edit _ + Editing... done. Executing edited code... + hello world + Out[6]: "print('hello world')\\n" + + Now we call it with the output #8 (stored in _8, also as Out[8]):: + + In [7]: edit _8 + Editing... done. Executing edited code... + hello again + Out[7]: "print('hello again')\\n" + + + Changing the default editor hook: + + If you wish to write your own editor hook, you can put it in a + configuration file which you load at startup time. The default hook + is defined in the IPython.core.hooks module, and you can use that as a + starting example for further modifications. That file also has + general instructions on how to set a new hook for use once you've + defined it.""" + opts,args = self.parse_options(parameter_s,'prxn:') + + try: + filename, lineno, is_temp = self._find_edit_target(self.shell, + args, opts, last_call) + except MacroToEdit as e: + self._edit_macro(args, e.args[0]) + return + except InteractivelyDefined as e: + print("Editing In[%i]" % e.index) + args = str(e.index) + filename, lineno, is_temp = self._find_edit_target(self.shell, + args, opts, last_call) + if filename is None: + # nothing was found, warnings have already been issued, + # just give up. + return + + if is_temp: + self._knowntemps.add(filename) + elif (filename in self._knowntemps): + is_temp = True + + + # do actual editing here + print('Editing...', end=' ') + sys.stdout.flush() + filepath = Path(filename) + try: + # Quote filenames that may have spaces in them when opening + # the editor + quoted = filename = str(filepath.absolute()) + if " " in quoted: + quoted = "'%s'" % quoted + self.shell.hooks.editor(quoted, lineno) + except TryNext: + warn('Could not open editor') + return + + # XXX TODO: should this be generalized for all string vars? + # For now, this is special-cased to blocks created by cpaste + if args.strip() == "pasted_block": + self.shell.user_ns["pasted_block"] = filepath.read_text(encoding="utf-8") + + if 'x' in opts: # -x prevents actual execution + print() + else: + print('done. Executing edited code...') + with preserve_keys(self.shell.user_ns, '__file__'): + if not is_temp: + self.shell.user_ns["__file__"] = filename + if "r" in opts: # Untranslated IPython code + source = filepath.read_text(encoding="utf-8") + self.shell.run_cell(source, store_history=False) + else: + self.shell.safe_execfile(filename, self.shell.user_ns, + self.shell.user_ns) + + if is_temp: + try: + return filepath.read_text(encoding="utf-8") + except IOError as msg: + if Path(msg.filename) == filepath: + warn('File not found. Did you forget to save?') + return + else: + self.shell.showtraceback() diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/config.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/config.py new file mode 100644 index 0000000000000000000000000000000000000000..9e1cb38c254f412cae88890bdd2da92da5232908 --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/config.py @@ -0,0 +1,140 @@ +"""Implementation of configuration-related magic functions. +""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012 The IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +# Stdlib +import re + +# Our own packages +from IPython.core.error import UsageError +from IPython.core.magic import Magics, magics_class, line_magic +from logging import error + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + +reg = re.compile(r'^\w+\.\w+$') +@magics_class +class ConfigMagics(Magics): + + def __init__(self, shell): + super(ConfigMagics, self).__init__(shell) + self.configurables = [] + + @line_magic + def config(self, s): + """configure IPython + + %config Class[.trait=value] + + This magic exposes most of the IPython config system. Any + Configurable class should be able to be configured with the simple + line:: + + %config Class.trait=value + + Where `value` will be resolved in the user's namespace, if it is an + expression or variable name. + + Examples + -------- + + To see what classes are available for config, pass no arguments:: + + In [1]: %config + Available objects for config: + AliasManager + DisplayFormatter + HistoryManager + IPCompleter + LoggingMagics + MagicsManager + OSMagics + PrefilterManager + ScriptMagics + TerminalInteractiveShell + + To view what is configurable on a given class, just pass the class + name:: + + In [2]: %config LoggingMagics + LoggingMagics(Magics) options + --------------------------- + LoggingMagics.quiet= + Suppress output of log state when logging is enabled + Current: False + + but the real use is in setting values:: + + In [3]: %config LoggingMagics.quiet = True + + and these values are read from the user_ns if they are variables:: + + In [4]: feeling_quiet=False + + In [5]: %config LoggingMagics.quiet = feeling_quiet + + """ + from traitlets.config.loader import Config + # some IPython objects are Configurable, but do not yet have + # any configurable traits. Exclude them from the effects of + # this magic, as their presence is just noise: + configurables = sorted(set([ c for c in self.shell.configurables + if c.__class__.class_traits(config=True) + ]), key=lambda x: x.__class__.__name__) + classnames = [ c.__class__.__name__ for c in configurables ] + + line = s.strip() + if not line: + # print available configurable names + print("Available objects for config:") + for name in classnames: + print(" ", name) + return + elif line in classnames: + # `%config TerminalInteractiveShell` will print trait info for + # TerminalInteractiveShell + c = configurables[classnames.index(line)] + cls = c.__class__ + help = cls.class_get_help(c) + # strip leading '--' from cl-args: + help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) + print(help) + return + elif reg.match(line): + cls, attr = line.split('.') + return getattr(configurables[classnames.index(cls)],attr) + elif '=' not in line: + msg = "Invalid config statement: %r, "\ + "should be `Class.trait = value`." + + ll = line.lower() + for classname in classnames: + if ll == classname.lower(): + msg = msg + '\nDid you mean %s (note the case)?' % classname + break + + raise UsageError( msg % line) + + # otherwise, assume we are setting configurables. + # leave quotes on args when splitting, because we want + # unquoted args to eval in user_ns + cfg = Config() + exec("cfg."+line, self.shell.user_ns, locals()) + + for configurable in configurables: + try: + configurable.update_config(cfg) + except Exception as e: + error(e) diff --git a/temp_venv/lib/python3.13/site-packages/IPython/core/magics/display.py b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/display.py new file mode 100644 index 0000000000000000000000000000000000000000..6c0eff6884f7666548f2c701c3a901b59f4c5abc --- /dev/null +++ b/temp_venv/lib/python3.13/site-packages/IPython/core/magics/display.py @@ -0,0 +1,93 @@ +"""Simple magics for display formats""" +#----------------------------------------------------------------------------- +# Copyright (c) 2012 The IPython Development Team. +# +# Distributed under the terms of the Modified BSD License. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# Imports +#----------------------------------------------------------------------------- + +# Our own packages +from IPython.display import display, Javascript, Latex, SVG, HTML, Markdown +from IPython.core.magic import ( + Magics, magics_class, cell_magic +) +from IPython.core import magic_arguments + +#----------------------------------------------------------------------------- +# Magic implementation classes +#----------------------------------------------------------------------------- + + +@magics_class +class DisplayMagics(Magics): + """Magics for displaying various output types with literals + + Defines javascript/latex/svg/html cell magics for writing + blocks in those languages, to be rendered in the frontend. + """ + + @cell_magic + def js(self, line, cell): + """Run the cell block of Javascript code + + Alias of `%%javascript` + + Starting with IPython 8.0 %%javascript is pending deprecation to be replaced + by a more flexible system + + Please See https://github.com/ipython/ipython/issues/13376 + """ + self.javascript(line, cell) + + @cell_magic + def javascript(self, line, cell): + """Run the cell block of Javascript code + + Starting with IPython 8.0 %%javascript is pending deprecation to be replaced + by a more flexible system + + Please See https://github.com/ipython/ipython/issues/13376 + """ + display(Javascript(cell)) + + + @cell_magic + def latex(self, line, cell): + """Render the cell as a block of LaTeX + + The subset of LaTeX which is supported depends on the implementation in + the client. In the Jupyter Notebook, this magic only renders the subset + of LaTeX defined by MathJax + [here](https://docs.mathjax.org/en/v2.5-latest/tex.html).""" + display(Latex(cell)) + + @cell_magic + def svg(self, line, cell): + """Render the cell as an SVG literal""" + display(SVG(cell)) + + @magic_arguments.magic_arguments() + @magic_arguments.argument( + '--isolated', action='store_true', default=False, + help="""Annotate the cell as 'isolated'. +Isolated cells are rendered inside their own