mehhl commited on
Commit
2bf669e
·
verified ·
1 Parent(s): ef5ff9c

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/alias.cpython-313.pyc +0 -0
  2. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/crashhandler.cpython-313.pyc +0 -0
  3. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display.cpython-313.pyc +0 -0
  4. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display_trap.cpython-313.pyc +0 -0
  5. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/extensions.cpython-313.pyc +0 -0
  6. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/getipython.cpython-313.pyc +0 -0
  7. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/oinspect.cpython-313.pyc +0 -0
  8. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/payload.cpython-313.pyc +0 -0
  9. temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/ultratb.cpython-313.pyc +0 -0
  10. temp_venv/lib/python3.13/site-packages/IPython/core/magics/__init__.py +42 -0
  11. temp_venv/lib/python3.13/site-packages/IPython/core/magics/ast_mod.py +330 -0
  12. temp_venv/lib/python3.13/site-packages/IPython/core/magics/auto.py +144 -0
  13. temp_venv/lib/python3.13/site-packages/IPython/core/magics/basic.py +674 -0
  14. temp_venv/lib/python3.13/site-packages/IPython/core/magics/code.py +757 -0
  15. temp_venv/lib/python3.13/site-packages/IPython/core/magics/config.py +140 -0
  16. temp_venv/lib/python3.13/site-packages/IPython/core/magics/display.py +93 -0
  17. temp_venv/lib/python3.13/site-packages/IPython/core/magics/execution.py +1677 -0
  18. temp_venv/lib/python3.13/site-packages/IPython/core/magics/extension.py +63 -0
  19. temp_venv/lib/python3.13/site-packages/IPython/core/magics/history.py +338 -0
  20. temp_venv/lib/python3.13/site-packages/IPython/core/magics/logging.py +195 -0
  21. temp_venv/lib/python3.13/site-packages/IPython/core/magics/namespace.py +711 -0
  22. temp_venv/lib/python3.13/site-packages/IPython/core/magics/osm.py +855 -0
  23. temp_venv/lib/python3.13/site-packages/IPython/core/magics/packaging.py +181 -0
  24. temp_venv/lib/python3.13/site-packages/IPython/core/magics/pylab.py +173 -0
  25. temp_venv/lib/python3.13/site-packages/IPython/core/magics/script.py +393 -0
  26. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/__init__.cpython-313.pyc +0 -0
  27. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/debugger.cpython-313.pyc +0 -0
  28. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/embed.cpython-313.pyc +0 -0
  29. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/interactiveshell.cpython-313.pyc +0 -0
  30. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/ipapp.cpython-313.pyc +0 -0
  31. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/magics.cpython-313.pyc +0 -0
  32. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/prompts.cpython-313.pyc +0 -0
  33. temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/ptutils.cpython-313.pyc +0 -0
  34. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/__init__.py +139 -0
  35. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/__pycache__/__init__.cpython-313.pyc +0 -0
  36. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/asyncio.py +40 -0
  37. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/glut.py +140 -0
  38. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk.py +60 -0
  39. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk3.py +13 -0
  40. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk4.py +27 -0
  41. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/osx.py +147 -0
  42. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/pyglet.py +67 -0
  43. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/qt.py +90 -0
  44. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/tk.py +93 -0
  45. temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/wx.py +219 -0
  46. temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__init__.py +636 -0
  47. temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/__init__.cpython-313.pyc +0 -0
  48. temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/auto_match.cpython-313.pyc +0 -0
  49. temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/auto_suggest.cpython-313.pyc +0 -0
  50. temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/filters.cpython-313.pyc +0 -0
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/alias.cpython-313.pyc ADDED
Binary file (10.8 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/crashhandler.cpython-313.pyc ADDED
Binary file (9.11 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display.cpython-313.pyc ADDED
Binary file (47.8 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/display_trap.cpython-313.pyc ADDED
Binary file (2.61 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/extensions.cpython-313.pyc ADDED
Binary file (6.29 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/getipython.cpython-313.pyc ADDED
Binary file (704 Bytes). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/oinspect.cpython-313.pyc ADDED
Binary file (42 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/payload.cpython-313.pyc ADDED
Binary file (1.91 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/__pycache__/ultratb.cpython-313.pyc ADDED
Binary file (47.2 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/core/magics/__init__.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of all the magic functions built into IPython.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ from ..magic import Magics, magics_class
16
+ from .auto import AutoMagics
17
+ from .basic import BasicMagics, AsyncMagics
18
+ from .code import CodeMagics, MacroToEdit
19
+ from .config import ConfigMagics
20
+ from .display import DisplayMagics
21
+ from .execution import ExecutionMagics
22
+ from .extension import ExtensionMagics
23
+ from .history import HistoryMagics
24
+ from .logging import LoggingMagics
25
+ from .namespace import NamespaceMagics
26
+ from .osm import OSMagics
27
+ from .packaging import PackagingMagics
28
+ from .pylab import PylabMagics
29
+ from .script import ScriptMagics
30
+
31
+ #-----------------------------------------------------------------------------
32
+ # Magic implementation classes
33
+ #-----------------------------------------------------------------------------
34
+
35
+ @magics_class
36
+ class UserMagics(Magics):
37
+ """Placeholder for user-defined magics to be added at runtime.
38
+
39
+ All magics are eventually merged into a single namespace at runtime, but we
40
+ use this class to isolate the magics defined dynamically by the user into
41
+ their own class.
42
+ """
temp_venv/lib/python3.13/site-packages/IPython/core/magics/ast_mod.py ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module contains utility function and classes to inject simple ast
3
+ transformations based on code strings into IPython. While it is already possible
4
+ with ast-transformers it is not easy to directly manipulate ast.
5
+
6
+
7
+ IPython has pre-code and post-code hooks, but are ran from within the IPython
8
+ machinery so may be inappropriate, for example for performance measurement.
9
+
10
+ This module give you tools to simplify this, and expose 2 classes:
11
+
12
+ - `ReplaceCodeTransformer` which is a simple ast transformer based on code
13
+ template,
14
+
15
+ and for advance case:
16
+
17
+ - `Mangler` which is a simple ast transformer that mangle names in the ast.
18
+
19
+
20
+ Example, let's try to make a simple version of the ``timeit`` magic, that run a
21
+ code snippet 10 times and print the average time taken.
22
+
23
+ Basically we want to run :
24
+
25
+ .. code-block:: python
26
+
27
+ from time import perf_counter
28
+ now = perf_counter()
29
+ for i in range(10):
30
+ __code__ # our code
31
+ print(f"Time taken: {(perf_counter() - now)/10}")
32
+ __ret__ # the result of the last statement
33
+
34
+ Where ``__code__`` is the code snippet we want to run, and ``__ret__`` is the
35
+ result, so that if we for example run `dataframe.head()` IPython still display
36
+ the head of dataframe instead of nothing.
37
+
38
+ Here is a complete example of a file `timit2.py` that define such a magic:
39
+
40
+ .. code-block:: python
41
+
42
+ from IPython.core.magic import (
43
+ Magics,
44
+ magics_class,
45
+ line_cell_magic,
46
+ )
47
+ from IPython.core.magics.ast_mod import ReplaceCodeTransformer
48
+ from textwrap import dedent
49
+ import ast
50
+
51
+ template = template = dedent('''
52
+ from time import perf_counter
53
+ now = perf_counter()
54
+ for i in range(10):
55
+ __code__
56
+ print(f"Time taken: {(perf_counter() - now)/10}")
57
+ __ret__
58
+ '''
59
+ )
60
+
61
+
62
+ @magics_class
63
+ class AstM(Magics):
64
+ @line_cell_magic
65
+ def t2(self, line, cell):
66
+ transformer = ReplaceCodeTransformer.from_string(template)
67
+ transformer.debug = True
68
+ transformer.mangler.debug = True
69
+ new_code = transformer.visit(ast.parse(cell))
70
+ return exec(compile(new_code, "<ast>", "exec"))
71
+
72
+
73
+ def load_ipython_extension(ip):
74
+ ip.register_magics(AstM)
75
+
76
+
77
+
78
+ .. code-block:: python
79
+
80
+ In [1]: %load_ext timit2
81
+
82
+ In [2]: %%t2
83
+ ...: import time
84
+ ...: time.sleep(0.05)
85
+ ...:
86
+ ...:
87
+ Time taken: 0.05435649999999441
88
+
89
+
90
+ If you wish to ran all the code enter in IPython in an ast transformer, you can
91
+ do so as well:
92
+
93
+ .. code-block:: python
94
+
95
+ In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer
96
+ ...:
97
+ ...: template = '''
98
+ ...: from time import perf_counter
99
+ ...: now = perf_counter()
100
+ ...: __code__
101
+ ...: print(f"Code ran in {perf_counter()-now}")
102
+ ...: __ret__'''
103
+ ...:
104
+ ...: get_ipython().ast_transformers.append(ReplaceCodeTransformer.from_string(template))
105
+
106
+ In [2]: 1+1
107
+ Code ran in 3.40410006174352e-05
108
+ Out[2]: 2
109
+
110
+
111
+
112
+ Hygiene and Mangling
113
+ --------------------
114
+
115
+ The ast transformer above is not hygienic, it may not work if the user code use
116
+ the same variable names as the ones used in the template. For example.
117
+
118
+ To help with this by default the `ReplaceCodeTransformer` will mangle all names
119
+ staring with 3 underscores. This is a simple heuristic that should work in most
120
+ case, but can be cumbersome in some case. We provide a `Mangler` class that can
121
+ be overridden to change the mangling heuristic, or simply use the `mangle_all`
122
+ utility function. It will _try_ to mangle all names (except `__ret__` and
123
+ `__code__`), but this include builtins (``print``, ``range``, ``type``) and
124
+ replace those by invalid identifiers py prepending ``mangle-``:
125
+ ``mangle-print``, ``mangle-range``, ``mangle-type`` etc. This is not a problem
126
+ as currently Python AST support invalid identifiers, but it may not be the case
127
+ in the future.
128
+
129
+ You can set `ReplaceCodeTransformer.debug=True` and
130
+ `ReplaceCodeTransformer.mangler.debug=True` to see the code after mangling and
131
+ transforming:
132
+
133
+ .. code-block:: python
134
+
135
+
136
+ In [1]: from IPython.core.magics.ast_mod import ReplaceCodeTransformer, mangle_all
137
+ ...:
138
+ ...: template = '''
139
+ ...: from builtins import type, print
140
+ ...: from time import perf_counter
141
+ ...: now = perf_counter()
142
+ ...: __code__
143
+ ...: print(f"Code ran in {perf_counter()-now}")
144
+ ...: __ret__'''
145
+ ...:
146
+ ...: transformer = ReplaceCodeTransformer.from_string(template, mangling_predicate=mangle_all)
147
+
148
+
149
+ In [2]: transformer.debug = True
150
+ ...: transformer.mangler.debug = True
151
+ ...: get_ipython().ast_transformers.append(transformer)
152
+
153
+ In [3]: 1+1
154
+ Mangling Alias mangle-type
155
+ Mangling Alias mangle-print
156
+ Mangling Alias mangle-perf_counter
157
+ Mangling now
158
+ Mangling perf_counter
159
+ Not mangling __code__
160
+ Mangling print
161
+ Mangling perf_counter
162
+ Mangling now
163
+ Not mangling __ret__
164
+ ---- Transformed code ----
165
+ from builtins import type as mangle-type, print as mangle-print
166
+ from time import perf_counter as mangle-perf_counter
167
+ mangle-now = mangle-perf_counter()
168
+ ret-tmp = 1 + 1
169
+ mangle-print(f'Code ran in {mangle-perf_counter() - mangle-now}')
170
+ ret-tmp
171
+ ---- ---------------- ----
172
+ Code ran in 0.00013654199938173406
173
+ Out[3]: 2
174
+
175
+
176
+ """
177
+
178
+ __skip_doctest__ = True
179
+
180
+
181
+ from ast import (
182
+ NodeTransformer,
183
+ Store,
184
+ Load,
185
+ Name,
186
+ Expr,
187
+ Assign,
188
+ Module,
189
+ Import,
190
+ ImportFrom,
191
+ )
192
+ import ast
193
+ import copy
194
+
195
+ from typing import Dict, Optional, Union
196
+
197
+
198
+ mangle_all = lambda name: False if name in ("__ret__", "__code__") else True
199
+
200
+
201
+ class Mangler(NodeTransformer):
202
+ """
203
+ Mangle given names in and ast tree to make sure they do not conflict with
204
+ user code.
205
+ """
206
+
207
+ enabled: bool = True
208
+ debug: bool = False
209
+
210
+ def log(self, *args, **kwargs):
211
+ if self.debug:
212
+ print(*args, **kwargs)
213
+
214
+ def __init__(self, predicate=None):
215
+ if predicate is None:
216
+ predicate = lambda name: name.startswith("___")
217
+ self.predicate = predicate
218
+
219
+ def visit_Name(self, node):
220
+ if self.predicate(node.id):
221
+ self.log("Mangling", node.id)
222
+ # Once in the ast we do not need
223
+ # names to be valid identifiers.
224
+ node.id = "mangle-" + node.id
225
+ else:
226
+ self.log("Not mangling", node.id)
227
+ return node
228
+
229
+ def visit_FunctionDef(self, node):
230
+ if self.predicate(node.name):
231
+ self.log("Mangling", node.name)
232
+ node.name = "mangle-" + node.name
233
+ else:
234
+ self.log("Not mangling", node.name)
235
+
236
+ for arg in node.args.args:
237
+ if self.predicate(arg.arg):
238
+ self.log("Mangling function arg", arg.arg)
239
+ arg.arg = "mangle-" + arg.arg
240
+ else:
241
+ self.log("Not mangling function arg", arg.arg)
242
+ return self.generic_visit(node)
243
+
244
+ def visit_ImportFrom(self, node: ImportFrom):
245
+ return self._visit_Import_and_ImportFrom(node)
246
+
247
+ def visit_Import(self, node: Import):
248
+ return self._visit_Import_and_ImportFrom(node)
249
+
250
+ def _visit_Import_and_ImportFrom(self, node: Union[Import, ImportFrom]):
251
+ for alias in node.names:
252
+ asname = alias.name if alias.asname is None else alias.asname
253
+ if self.predicate(asname):
254
+ new_name: str = "mangle-" + asname
255
+ self.log("Mangling Alias", new_name)
256
+ alias.asname = new_name
257
+ else:
258
+ self.log("Not mangling Alias", alias.asname)
259
+ return node
260
+
261
+
262
+ class ReplaceCodeTransformer(NodeTransformer):
263
+ enabled: bool = True
264
+ debug: bool = False
265
+ mangler: Mangler
266
+
267
+ def __init__(
268
+ self, template: Module, mapping: Optional[Dict] = None, mangling_predicate=None
269
+ ):
270
+ assert isinstance(mapping, (dict, type(None)))
271
+ assert isinstance(mangling_predicate, (type(None), type(lambda: None)))
272
+ assert isinstance(template, ast.Module)
273
+ self.template = template
274
+ self.mangler = Mangler(predicate=mangling_predicate)
275
+ if mapping is None:
276
+ mapping = {}
277
+ self.mapping = mapping
278
+
279
+ @classmethod
280
+ def from_string(
281
+ cls, template: str, mapping: Optional[Dict] = None, mangling_predicate=None
282
+ ):
283
+ return cls(
284
+ ast.parse(template), mapping=mapping, mangling_predicate=mangling_predicate
285
+ )
286
+
287
+ def visit_Module(self, code):
288
+ if not self.enabled:
289
+ return code
290
+ # if not isinstance(code, ast.Module):
291
+ # recursively called...
292
+ # return generic_visit(self, code)
293
+ last = code.body[-1]
294
+ if isinstance(last, Expr):
295
+ code.body.pop()
296
+ code.body.append(Assign([Name("ret-tmp", ctx=Store())], value=last.value))
297
+ ast.fix_missing_locations(code)
298
+ ret = Expr(value=Name("ret-tmp", ctx=Load()))
299
+ ret = ast.fix_missing_locations(ret)
300
+ self.mapping["__ret__"] = ret
301
+ else:
302
+ self.mapping["__ret__"] = ast.parse("None").body[0]
303
+ self.mapping["__code__"] = code.body
304
+ tpl = ast.fix_missing_locations(self.template)
305
+
306
+ tx = copy.deepcopy(tpl)
307
+ tx = self.mangler.visit(tx)
308
+ node = self.generic_visit(tx)
309
+ node_2 = ast.fix_missing_locations(node)
310
+ if self.debug:
311
+ print("---- Transformed code ----")
312
+ print(ast.unparse(node_2))
313
+ print("---- ---------------- ----")
314
+ return node_2
315
+
316
+ # this does not work as the name might be in a list and one might want to extend the list.
317
+ # def visit_Name(self, name):
318
+ # if name.id in self.mapping and name.id == "__ret__":
319
+ # print(name, "in mapping")
320
+ # if isinstance(name.ctx, ast.Store):
321
+ # return Name("tmp", ctx=Store())
322
+ # else:
323
+ # return copy.deepcopy(self.mapping[name.id])
324
+ # return name
325
+
326
+ def visit_Expr(self, expr):
327
+ if isinstance(expr.value, Name) and expr.value.id in self.mapping:
328
+ if self.mapping[expr.value.id] is not None:
329
+ return copy.deepcopy(self.mapping[expr.value.id])
330
+ return self.generic_visit(expr)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/auto.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions that control various automatic behaviors.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Our own packages
16
+ from IPython.core.magic import Bunch, Magics, magics_class, line_magic
17
+ from IPython.testing.skipdoctest import skip_doctest
18
+ from logging import error
19
+
20
+ #-----------------------------------------------------------------------------
21
+ # Magic implementation classes
22
+ #-----------------------------------------------------------------------------
23
+
24
+ @magics_class
25
+ class AutoMagics(Magics):
26
+ """Magics that control various autoX behaviors."""
27
+
28
+ def __init__(self, shell):
29
+ super(AutoMagics, self).__init__(shell)
30
+ # namespace for holding state we may need
31
+ self._magic_state = Bunch()
32
+
33
+ @line_magic
34
+ def automagic(self, parameter_s=''):
35
+ """Make magic functions callable without having to type the initial %.
36
+
37
+ Without arguments toggles on/off (when off, you must call it as
38
+ %automagic, of course). With arguments it sets the value, and you can
39
+ use any of (case insensitive):
40
+
41
+ - on, 1, True: to activate
42
+
43
+ - off, 0, False: to deactivate.
44
+
45
+ Note that magic functions have lowest priority, so if there's a
46
+ variable whose name collides with that of a magic fn, automagic won't
47
+ work for that function (you get the variable instead). However, if you
48
+ delete the variable (del var), the previously shadowed magic function
49
+ becomes visible to automagic again."""
50
+
51
+ arg = parameter_s.lower()
52
+ mman = self.shell.magics_manager
53
+ if arg in ('on', '1', 'true'):
54
+ val = True
55
+ elif arg in ('off', '0', 'false'):
56
+ val = False
57
+ else:
58
+ val = not mman.auto_magic
59
+ mman.auto_magic = val
60
+ print('\n' + self.shell.magics_manager.auto_status())
61
+
62
+ @skip_doctest
63
+ @line_magic
64
+ def autocall(self, parameter_s=''):
65
+ """Make functions callable without having to type parentheses.
66
+
67
+ Usage:
68
+
69
+ %autocall [mode]
70
+
71
+ The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
72
+ value is toggled on and off (remembering the previous state).
73
+
74
+ In more detail, these values mean:
75
+
76
+ 0 -> fully disabled
77
+
78
+ 1 -> active, but do not apply if there are no arguments on the line.
79
+
80
+ In this mode, you get::
81
+
82
+ In [1]: callable
83
+ Out[1]: <built-in function callable>
84
+
85
+ In [2]: callable 'hello'
86
+ ------> callable('hello')
87
+ Out[2]: False
88
+
89
+ 2 -> Active always. Even if no arguments are present, the callable
90
+ object is called::
91
+
92
+ In [2]: float
93
+ ------> float()
94
+ Out[2]: 0.0
95
+
96
+ Note that even with autocall off, you can still use '/' at the start of
97
+ a line to treat the first argument on the command line as a function
98
+ and add parentheses to it::
99
+
100
+ In [8]: /str 43
101
+ ------> str(43)
102
+ Out[8]: '43'
103
+
104
+ # all-random (note for auto-testing)
105
+ """
106
+
107
+ valid_modes = {
108
+ 0: "Off",
109
+ 1: "Smart",
110
+ 2: "Full",
111
+ }
112
+
113
+ def errorMessage() -> str:
114
+ error = "Valid modes: "
115
+ for k, v in valid_modes.items():
116
+ error += str(k) + "->" + v + ", "
117
+ error = error[:-2] # remove tailing `, ` after last element
118
+ return error
119
+
120
+ if parameter_s:
121
+ if parameter_s not in map(str, valid_modes.keys()):
122
+ error(errorMessage())
123
+ return
124
+ arg = int(parameter_s)
125
+ else:
126
+ arg = 'toggle'
127
+
128
+ if arg not in (*list(valid_modes.keys()), "toggle"):
129
+ error(errorMessage())
130
+ return
131
+
132
+ if arg in (valid_modes.keys()):
133
+ self.shell.autocall = arg
134
+ else: # toggle
135
+ if self.shell.autocall:
136
+ self._magic_state.autocall_save = self.shell.autocall
137
+ self.shell.autocall = 0
138
+ else:
139
+ try:
140
+ self.shell.autocall = self._magic_state.autocall_save
141
+ except AttributeError:
142
+ self.shell.autocall = self._magic_state.autocall_save = 1
143
+
144
+ print("Automatic calling is:", list(valid_modes.values())[self.shell.autocall])
temp_venv/lib/python3.13/site-packages/IPython/core/magics/basic.py ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of basic magic functions."""
2
+
3
+
4
+ from logging import error
5
+ import io
6
+ import os
7
+ from pprint import pformat
8
+ import sys
9
+ from warnings import warn
10
+
11
+ from traitlets.utils.importstring import import_item
12
+ from IPython.core import magic_arguments, page
13
+ from IPython.core.error import UsageError
14
+ from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15
+ from IPython.utils.text import format_screen, dedent, indent
16
+ from IPython.testing.skipdoctest import skip_doctest
17
+ from IPython.utils.ipstruct import Struct
18
+
19
+
20
+ class MagicsDisplay:
21
+ def __init__(self, magics_manager, ignore=None):
22
+ self.ignore = ignore if ignore else []
23
+ self.magics_manager = magics_manager
24
+
25
+ def _lsmagic(self):
26
+ """The main implementation of the %lsmagic"""
27
+ mesc = magic_escapes['line']
28
+ cesc = magic_escapes['cell']
29
+ mman = self.magics_manager
30
+ magics = mman.lsmagic()
31
+ out = ['Available line magics:',
32
+ mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33
+ '',
34
+ 'Available cell magics:',
35
+ cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36
+ '',
37
+ mman.auto_status()]
38
+ return '\n'.join(out)
39
+
40
+ def _repr_pretty_(self, p, cycle):
41
+ p.text(self._lsmagic())
42
+
43
+ def __repr__(self):
44
+ return self.__str__()
45
+
46
+ def __str__(self):
47
+ return self._lsmagic()
48
+
49
+ def _jsonable(self):
50
+ """turn magics dict into jsonable dict of the same structure
51
+
52
+ replaces object instances with their class names as strings
53
+ """
54
+ magic_dict = {}
55
+ mman = self.magics_manager
56
+ magics = mman.lsmagic()
57
+ for key, subdict in magics.items():
58
+ d = {}
59
+ magic_dict[key] = d
60
+ for name, obj in subdict.items():
61
+ try:
62
+ classname = obj.__self__.__class__.__name__
63
+ except AttributeError:
64
+ classname = 'Other'
65
+
66
+ d[name] = classname
67
+ return magic_dict
68
+
69
+ def _repr_json_(self):
70
+ return self._jsonable()
71
+
72
+
73
+ @magics_class
74
+ class BasicMagics(Magics):
75
+ """Magics that provide central IPython functionality.
76
+
77
+ These are various magics that don't fit into specific categories but that
78
+ are all part of the base 'IPython experience'."""
79
+
80
+ @skip_doctest
81
+ @magic_arguments.magic_arguments()
82
+ @magic_arguments.argument(
83
+ '-l', '--line', action='store_true',
84
+ help="""Create a line magic alias."""
85
+ )
86
+ @magic_arguments.argument(
87
+ '-c', '--cell', action='store_true',
88
+ help="""Create a cell magic alias."""
89
+ )
90
+ @magic_arguments.argument(
91
+ 'name',
92
+ help="""Name of the magic to be created."""
93
+ )
94
+ @magic_arguments.argument(
95
+ 'target',
96
+ help="""Name of the existing line or cell magic."""
97
+ )
98
+ @magic_arguments.argument(
99
+ '-p', '--params', default=None,
100
+ help="""Parameters passed to the magic function."""
101
+ )
102
+ @line_magic
103
+ def alias_magic(self, line=''):
104
+ """Create an alias for an existing line or cell magic.
105
+
106
+ Examples
107
+ --------
108
+ ::
109
+
110
+ In [1]: %alias_magic t timeit
111
+ Created `%t` as an alias for `%timeit`.
112
+ Created `%%t` as an alias for `%%timeit`.
113
+
114
+ In [2]: %t -n1 pass
115
+ 107 ns ± 43.6 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
116
+
117
+ In [3]: %%t -n1
118
+ ...: pass
119
+ ...:
120
+ 107 ns ± 58.3 ns per loop (mean ± std. dev. of 7 runs, 1 loop each)
121
+
122
+ In [4]: %alias_magic --cell whereami pwd
123
+ UsageError: Cell magic function `%%pwd` not found.
124
+ In [5]: %alias_magic --line whereami pwd
125
+ Created `%whereami` as an alias for `%pwd`.
126
+
127
+ In [6]: %whereami
128
+ Out[6]: '/home/testuser'
129
+
130
+ In [7]: %alias_magic h history -p "-l 30" --line
131
+ Created `%h` as an alias for `%history -l 30`.
132
+ """
133
+
134
+ args = magic_arguments.parse_argstring(self.alias_magic, line)
135
+ shell = self.shell
136
+ mman = self.shell.magics_manager
137
+ escs = ''.join(magic_escapes.values())
138
+
139
+ target = args.target.lstrip(escs)
140
+ name = args.name.lstrip(escs)
141
+
142
+ params = args.params
143
+ if (params and
144
+ ((params.startswith('"') and params.endswith('"'))
145
+ or (params.startswith("'") and params.endswith("'")))):
146
+ params = params[1:-1]
147
+
148
+ # Find the requested magics.
149
+ m_line = shell.find_magic(target, 'line')
150
+ m_cell = shell.find_magic(target, 'cell')
151
+ if args.line and m_line is None:
152
+ raise UsageError('Line magic function `%s%s` not found.' %
153
+ (magic_escapes['line'], target))
154
+ if args.cell and m_cell is None:
155
+ raise UsageError('Cell magic function `%s%s` not found.' %
156
+ (magic_escapes['cell'], target))
157
+
158
+ # If --line and --cell are not specified, default to the ones
159
+ # that are available.
160
+ if not args.line and not args.cell:
161
+ if not m_line and not m_cell:
162
+ raise UsageError(
163
+ 'No line or cell magic with name `%s` found.' % target
164
+ )
165
+ args.line = bool(m_line)
166
+ args.cell = bool(m_cell)
167
+
168
+ params_str = "" if params is None else " " + params
169
+
170
+ if args.line:
171
+ mman.register_alias(name, target, 'line', params)
172
+ print('Created `%s%s` as an alias for `%s%s%s`.' % (
173
+ magic_escapes['line'], name,
174
+ magic_escapes['line'], target, params_str))
175
+
176
+ if args.cell:
177
+ mman.register_alias(name, target, 'cell', params)
178
+ print('Created `%s%s` as an alias for `%s%s%s`.' % (
179
+ magic_escapes['cell'], name,
180
+ magic_escapes['cell'], target, params_str))
181
+
182
+ @line_magic
183
+ def lsmagic(self, parameter_s=''):
184
+ """List currently available magic functions."""
185
+ return MagicsDisplay(self.shell.magics_manager, ignore=[])
186
+
187
+ def _magic_docs(self, brief=False, rest=False):
188
+ """Return docstrings from magic functions."""
189
+ mman = self.shell.magics_manager
190
+ docs = mman.lsmagic_docs(brief, missing='No documentation')
191
+
192
+ if rest:
193
+ format_string = '**%s%s**::\n\n%s\n\n'
194
+ else:
195
+ format_string = '%s%s:\n%s\n'
196
+
197
+ return ''.join(
198
+ [format_string % (magic_escapes['line'], fname,
199
+ indent(dedent(fndoc)))
200
+ for fname, fndoc in sorted(docs['line'].items())]
201
+ +
202
+ [format_string % (magic_escapes['cell'], fname,
203
+ indent(dedent(fndoc)))
204
+ for fname, fndoc in sorted(docs['cell'].items())]
205
+ )
206
+
207
+ @line_magic
208
+ def magic(self, parameter_s=''):
209
+ """Print information about the magic function system.
210
+
211
+ Supported formats: -latex, -brief, -rest
212
+ """
213
+
214
+ mode = ''
215
+ try:
216
+ mode = parameter_s.split()[0][1:]
217
+ except IndexError:
218
+ pass
219
+
220
+ brief = (mode == 'brief')
221
+ rest = (mode == 'rest')
222
+ magic_docs = self._magic_docs(brief, rest)
223
+
224
+ if mode == 'latex':
225
+ print(self.format_latex(magic_docs))
226
+ return
227
+ else:
228
+ magic_docs = format_screen(magic_docs)
229
+
230
+ out = ["""
231
+ IPython's 'magic' functions
232
+ ===========================
233
+
234
+ The magic function system provides a series of functions which allow you to
235
+ control the behavior of IPython itself, plus a lot of system-type
236
+ features. There are two kinds of magics, line-oriented and cell-oriented.
237
+
238
+ Line magics are prefixed with the % character and work much like OS
239
+ command-line calls: they get as an argument the rest of the line, where
240
+ arguments are passed without parentheses or quotes. For example, this will
241
+ time the given statement::
242
+
243
+ %timeit range(1000)
244
+
245
+ Cell magics are prefixed with a double %%, and they are functions that get as
246
+ an argument not only the rest of the line, but also the lines below it in a
247
+ separate argument. These magics are called with two arguments: the rest of the
248
+ call line and the body of the cell, consisting of the lines below the first.
249
+ For example::
250
+
251
+ %%timeit x = numpy.random.randn((100, 100))
252
+ numpy.linalg.svd(x)
253
+
254
+ will time the execution of the numpy svd routine, running the assignment of x
255
+ as part of the setup phase, which is not timed.
256
+
257
+ In a line-oriented client (the terminal or Qt console IPython), starting a new
258
+ input with %% will automatically enter cell mode, and IPython will continue
259
+ reading input until a blank line is given. In the notebook, simply type the
260
+ whole cell as one entity, but keep in mind that the %% escape can only be at
261
+ the very start of the cell.
262
+
263
+ NOTE: If you have 'automagic' enabled (via the command line option or with the
264
+ %automagic function), you don't need to type in the % explicitly for line
265
+ magics; cell magics always require an explicit '%%' escape. By default,
266
+ IPython ships with automagic on, so you should only rarely need the % escape.
267
+
268
+ Example: typing '%cd mydir' (without the quotes) changes your working directory
269
+ to 'mydir', if it exists.
270
+
271
+ For a list of the available magic functions, use %lsmagic. For a description
272
+ of any of them, type %magic_name?, e.g. '%cd?'.
273
+
274
+ Currently the magic system has the following functions:""",
275
+ magic_docs,
276
+ "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
277
+ str(self.lsmagic()),
278
+ ]
279
+ page.page('\n'.join(out))
280
+
281
+
282
+ @line_magic
283
+ def page(self, parameter_s=''):
284
+ """Pretty print the object and display it through a pager.
285
+
286
+ %page [options] OBJECT
287
+
288
+ If no object is given, use _ (last output).
289
+
290
+ Options:
291
+
292
+ -r: page str(object), don't pretty-print it."""
293
+
294
+ # After a function contributed by Olivier Aubert, slightly modified.
295
+
296
+ # Process options/args
297
+ opts, args = self.parse_options(parameter_s, 'r')
298
+ raw = 'r' in opts
299
+
300
+ oname = args and args or '_'
301
+ info = self.shell._ofind(oname)
302
+ if info.found:
303
+ if raw:
304
+ txt = str(info.obj)
305
+ else:
306
+ txt = pformat(info.obj)
307
+ page.page(txt)
308
+ else:
309
+ print('Object `%s` not found' % oname)
310
+
311
+ @line_magic
312
+ def pprint(self, parameter_s=''):
313
+ """Toggle pretty printing on/off."""
314
+ ptformatter = self.shell.display_formatter.formatters['text/plain']
315
+ ptformatter.pprint = bool(1 - ptformatter.pprint)
316
+ print('Pretty printing has been turned',
317
+ ['OFF','ON'][ptformatter.pprint])
318
+
319
+ @line_magic
320
+ def colors(self, parameter_s=''):
321
+ """Switch color scheme/theme globally for IPython
322
+
323
+ Examples
324
+ --------
325
+ To get a plain black and white terminal::
326
+
327
+ %colors nocolor
328
+ """
329
+
330
+
331
+ new_theme = parameter_s.strip()
332
+ if not new_theme:
333
+ from IPython.utils.PyColorize import theme_table
334
+
335
+ raise UsageError(
336
+ "%colors: you must specify a color theme. See '%colors?'."
337
+ f" Available themes: {list(theme_table.keys())}"
338
+ )
339
+
340
+ self.shell.colors = new_theme
341
+
342
+ @line_magic
343
+ def xmode(self, parameter_s=''):
344
+ """Switch modes for the exception handlers.
345
+
346
+ Valid modes: Plain, Context, Verbose, and Minimal.
347
+
348
+ If called without arguments, acts as a toggle.
349
+
350
+ When in verbose mode the value `--show` (and `--hide`)
351
+ will respectively show (or hide) frames with ``__tracebackhide__ =
352
+ True`` value set.
353
+ """
354
+
355
+ def xmode_switch_err(name):
356
+ warn('Error changing %s exception modes.\n%s' %
357
+ (name,sys.exc_info()[1]))
358
+
359
+ shell = self.shell
360
+ if parameter_s.strip() == "--show":
361
+ shell.InteractiveTB.skip_hidden = False
362
+ return
363
+ if parameter_s.strip() == "--hide":
364
+ shell.InteractiveTB.skip_hidden = True
365
+ return
366
+
367
+ new_mode = parameter_s.strip().capitalize()
368
+ try:
369
+ shell.InteractiveTB.set_mode(mode=new_mode)
370
+ print('Exception reporting mode:',shell.InteractiveTB.mode)
371
+ except:
372
+ raise
373
+ xmode_switch_err('user')
374
+
375
+ @line_magic
376
+ def quickref(self, arg):
377
+ """ Show a quick reference sheet """
378
+ from IPython.core.usage import quick_reference
379
+ qr = quick_reference + self._magic_docs(brief=True)
380
+ page.page(qr)
381
+
382
+ @line_magic
383
+ def doctest_mode(self, parameter_s=''):
384
+ """Toggle doctest mode on and off.
385
+
386
+ This mode is intended to make IPython behave as much as possible like a
387
+ plain Python shell, from the perspective of how its prompts, exceptions
388
+ and output look. This makes it easy to copy and paste parts of a
389
+ session into doctests. It does so by:
390
+
391
+ - Changing the prompts to the classic ``>>>`` ones.
392
+ - Changing the exception reporting mode to 'Plain'.
393
+ - Disabling pretty-printing of output.
394
+
395
+ Note that IPython also supports the pasting of code snippets that have
396
+ leading '>>>' and '...' prompts in them. This means that you can paste
397
+ doctests from files or docstrings (even if they have leading
398
+ whitespace), and the code will execute correctly. You can then use
399
+ '%history -t' to see the translated history; this will give you the
400
+ input after removal of all the leading prompts and whitespace, which
401
+ can be pasted back into an editor.
402
+
403
+ With these features, you can switch into this mode easily whenever you
404
+ need to do testing and changes to doctests, without having to leave
405
+ your existing IPython session.
406
+ """
407
+
408
+ # Shorthands
409
+ shell = self.shell
410
+ meta = shell.meta
411
+ disp_formatter = self.shell.display_formatter
412
+ ptformatter = disp_formatter.formatters['text/plain']
413
+ # dstore is a data store kept in the instance metadata bag to track any
414
+ # changes we make, so we can undo them later.
415
+ dstore = meta.setdefault('doctest_mode',Struct())
416
+ save_dstore = dstore.setdefault
417
+
418
+ # save a few values we'll need to recover later
419
+ mode = save_dstore('mode',False)
420
+ save_dstore('rc_pprint',ptformatter.pprint)
421
+ save_dstore('xmode',shell.InteractiveTB.mode)
422
+ save_dstore('rc_separate_out',shell.separate_out)
423
+ save_dstore('rc_separate_out2',shell.separate_out2)
424
+ save_dstore('rc_separate_in',shell.separate_in)
425
+ save_dstore('rc_active_types',disp_formatter.active_types)
426
+
427
+ if not mode:
428
+ # turn on
429
+
430
+ # Prompt separators like plain python
431
+ shell.separate_in = ''
432
+ shell.separate_out = ''
433
+ shell.separate_out2 = ''
434
+
435
+
436
+ ptformatter.pprint = False
437
+ disp_formatter.active_types = ['text/plain']
438
+
439
+ shell.run_line_magic("xmode", "Plain")
440
+ else:
441
+ # turn off
442
+ shell.separate_in = dstore.rc_separate_in
443
+
444
+ shell.separate_out = dstore.rc_separate_out
445
+ shell.separate_out2 = dstore.rc_separate_out2
446
+
447
+ ptformatter.pprint = dstore.rc_pprint
448
+ disp_formatter.active_types = dstore.rc_active_types
449
+
450
+ shell.run_line_magic("xmode", dstore.xmode)
451
+
452
+ # mode here is the state before we switch; switch_doctest_mode takes
453
+ # the mode we're switching to.
454
+ shell.switch_doctest_mode(not mode)
455
+
456
+ # Store new mode and inform
457
+ dstore.mode = bool(not mode)
458
+ mode_label = ['OFF','ON'][dstore.mode]
459
+ print('Doctest mode is:', mode_label)
460
+
461
+ @line_magic
462
+ def gui(self, parameter_s=''):
463
+ """Enable or disable IPython GUI event loop integration.
464
+
465
+ %gui [GUINAME]
466
+
467
+ This magic replaces IPython's threaded shells that were activated
468
+ using the (pylab/wthread/etc.) command line flags. GUI toolkits
469
+ can now be enabled at runtime and keyboard
470
+ interrupts should work without any problems. The following toolkits
471
+ are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
472
+
473
+ %gui wx # enable wxPython event loop integration
474
+ %gui qt # enable PyQt/PySide event loop integration
475
+ # with the latest version available.
476
+ %gui qt6 # enable PyQt6/PySide6 event loop integration
477
+ %gui qt5 # enable PyQt5/PySide2 event loop integration
478
+ %gui gtk # enable PyGTK event loop integration
479
+ %gui gtk3 # enable Gtk3 event loop integration
480
+ %gui gtk4 # enable Gtk4 event loop integration
481
+ %gui tk # enable Tk event loop integration
482
+ %gui osx # enable Cocoa event loop integration
483
+ # (requires %matplotlib 1.1)
484
+ %gui # disable all event loop integration
485
+
486
+ WARNING: after any of these has been called you can simply create
487
+ an application object, but DO NOT start the event loop yourself, as
488
+ we have already handled that.
489
+ """
490
+ opts, arg = self.parse_options(parameter_s, '')
491
+ if arg=='': arg = None
492
+ try:
493
+ return self.shell.enable_gui(arg)
494
+ except Exception as e:
495
+ # print simple error message, rather than traceback if we can't
496
+ # hook up the GUI
497
+ error(str(e))
498
+
499
+ @skip_doctest
500
+ @line_magic
501
+ def precision(self, s=''):
502
+ """Set floating point precision for pretty printing.
503
+
504
+ Can set either integer precision or a format string.
505
+
506
+ If numpy has been imported and precision is an int,
507
+ numpy display precision will also be set, via ``numpy.set_printoptions``.
508
+
509
+ If no argument is given, defaults will be restored.
510
+
511
+ Examples
512
+ --------
513
+ ::
514
+
515
+ In [1]: from math import pi
516
+
517
+ In [2]: %precision 3
518
+ Out[2]: '%.3f'
519
+
520
+ In [3]: pi
521
+ Out[3]: 3.142
522
+
523
+ In [4]: %precision %i
524
+ Out[4]: '%i'
525
+
526
+ In [5]: pi
527
+ Out[5]: 3
528
+
529
+ In [6]: %precision %e
530
+ Out[6]: '%e'
531
+
532
+ In [7]: pi**10
533
+ Out[7]: 9.364805e+04
534
+
535
+ In [8]: %precision
536
+ Out[8]: '%r'
537
+
538
+ In [9]: pi**10
539
+ Out[9]: 93648.047476082982
540
+ """
541
+ ptformatter = self.shell.display_formatter.formatters['text/plain']
542
+ ptformatter.float_precision = s
543
+ return ptformatter.float_format
544
+
545
+ @magic_arguments.magic_arguments()
546
+ @magic_arguments.argument(
547
+ 'filename', type=str,
548
+ help='Notebook name or filename'
549
+ )
550
+ @line_magic
551
+ def notebook(self, s):
552
+ """Export and convert IPython notebooks.
553
+
554
+ This function can export the current IPython history to a notebook file.
555
+ For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
556
+ """
557
+ args = magic_arguments.parse_argstring(self.notebook, s)
558
+ outfname = os.path.expanduser(args.filename)
559
+
560
+ from nbformat import write, v4
561
+
562
+ cells = []
563
+ hist = list(self.shell.history_manager.get_range())
564
+ outputs = self.shell.history_manager.outputs
565
+ exceptions = self.shell.history_manager.exceptions
566
+
567
+ if(len(hist)<=1):
568
+ raise ValueError('History is empty, cannot export')
569
+ for session, execution_count, source in hist[:-1]:
570
+ cell = v4.new_code_cell(execution_count=execution_count, source=source)
571
+ for output in outputs[execution_count]:
572
+ for mime_type, data in output.bundle.items():
573
+ if output.output_type == "out_stream":
574
+ cell.outputs.append(v4.new_output("stream", text=[data]))
575
+ elif output.output_type == "err_stream":
576
+ err_output = v4.new_output("stream", text=[data])
577
+ err_output.name = "stderr"
578
+ cell.outputs.append(err_output)
579
+ elif output.output_type == "execute_result":
580
+ cell.outputs.append(
581
+ v4.new_output(
582
+ "execute_result",
583
+ data={mime_type: data},
584
+ execution_count=execution_count,
585
+ )
586
+ )
587
+ elif output.output_type == "display_data":
588
+ cell.outputs.append(
589
+ v4.new_output(
590
+ "display_data",
591
+ data={mime_type: data},
592
+ )
593
+ )
594
+ else:
595
+ raise ValueError(f"Unknown output type: {output.output_type}")
596
+
597
+ # Check if this execution_count is in exceptions (current session)
598
+ if execution_count in exceptions:
599
+ cell.outputs.append(
600
+ v4.new_output("error", **exceptions[execution_count])
601
+ )
602
+ cells.append(cell)
603
+
604
+ nb = v4.new_notebook(cells=cells)
605
+ with io.open(outfname, "w", encoding="utf-8") as f:
606
+ write(nb, f, version=4)
607
+
608
+ @magics_class
609
+ class AsyncMagics(BasicMagics):
610
+
611
+ @line_magic
612
+ def autoawait(self, parameter_s):
613
+ """
614
+ Allow to change the status of the autoawait option.
615
+
616
+ This allow you to set a specific asynchronous code runner.
617
+
618
+ If no value is passed, print the currently used asynchronous integration
619
+ and whether it is activated.
620
+
621
+ It can take a number of value evaluated in the following order:
622
+
623
+ - False/false/off deactivate autoawait integration
624
+ - True/true/on activate autoawait integration using configured default
625
+ loop
626
+ - asyncio/curio/trio activate autoawait integration and use integration
627
+ with said library.
628
+
629
+ - `sync` turn on the pseudo-sync integration (mostly used for
630
+ `IPython.embed()` which does not run IPython with a real eventloop and
631
+ deactivate running asynchronous code. Turning on Asynchronous code with
632
+ the pseudo sync loop is undefined behavior and may lead IPython to crash.
633
+
634
+ If the passed parameter does not match any of the above and is a python
635
+ identifier, get said object from user namespace and set it as the
636
+ runner, and activate autoawait.
637
+
638
+ If the object is a fully qualified object name, attempt to import it and
639
+ set it as the runner, and activate autoawait.
640
+
641
+ The exact behavior of autoawait is experimental and subject to change
642
+ across version of IPython and Python.
643
+ """
644
+
645
+ param = parameter_s.strip()
646
+ d = {True: "on", False: "off"}
647
+
648
+ if not param:
649
+ print("IPython autoawait is `{}`, and set to use `{}`".format(
650
+ d[self.shell.autoawait],
651
+ self.shell.loop_runner
652
+ ))
653
+ return None
654
+
655
+ if param.lower() in ('false', 'off'):
656
+ self.shell.autoawait = False
657
+ return None
658
+ if param.lower() in ('true', 'on'):
659
+ self.shell.autoawait = True
660
+ return None
661
+
662
+ if param in self.shell.loop_runner_map:
663
+ self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
664
+ return None
665
+
666
+ if param in self.shell.user_ns :
667
+ self.shell.loop_runner = self.shell.user_ns[param]
668
+ self.shell.autoawait = True
669
+ return None
670
+
671
+ runner = import_item(param)
672
+
673
+ self.shell.loop_runner = runner
674
+ self.shell.autoawait = True
temp_venv/lib/python3.13/site-packages/IPython/core/magics/code.py ADDED
@@ -0,0 +1,757 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of code management magic functions.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Stdlib
16
+ import inspect
17
+ import io
18
+ import os
19
+ import re
20
+ import sys
21
+ import ast
22
+ from itertools import chain
23
+ from urllib.request import Request, urlopen
24
+ from urllib.parse import urlencode
25
+ from pathlib import Path
26
+
27
+ # Our own packages
28
+ from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
29
+ from IPython.core.macro import Macro
30
+ from IPython.core.magic import Magics, magics_class, line_magic
31
+ from IPython.core.oinspect import find_file, find_source_lines
32
+ from IPython.core.release import version
33
+ from IPython.testing.skipdoctest import skip_doctest
34
+ from IPython.utils.contexts import preserve_keys
35
+ from IPython.utils.path import get_py_filename
36
+ from warnings import warn
37
+ from logging import error
38
+ from IPython.utils.text import get_text_list
39
+
40
+ #-----------------------------------------------------------------------------
41
+ # Magic implementation classes
42
+ #-----------------------------------------------------------------------------
43
+
44
+ # Used for exception handling in magic_edit
45
+ class MacroToEdit(ValueError): pass
46
+
47
+ ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
48
+
49
+ # To match, e.g. 8-10 1:5 :10 3-
50
+ range_re = re.compile(r"""
51
+ (?P<start>\d+)?
52
+ ((?P<sep>[\-:])
53
+ (?P<end>\d+)?)?
54
+ $""", re.VERBOSE)
55
+
56
+
57
+ def extract_code_ranges(ranges_str):
58
+ """Turn a string of range for %%load into 2-tuples of (start, stop)
59
+ ready to use as a slice of the content split by lines.
60
+
61
+ Examples
62
+ --------
63
+ list(extract_input_ranges("5-10 2"))
64
+ [(4, 10), (1, 2)]
65
+ """
66
+ for range_str in ranges_str.split():
67
+ rmatch = range_re.match(range_str)
68
+ if not rmatch:
69
+ continue
70
+ sep = rmatch.group("sep")
71
+ start = rmatch.group("start")
72
+ end = rmatch.group("end")
73
+
74
+ if sep == '-':
75
+ start = int(start) - 1 if start else None
76
+ end = int(end) if end else None
77
+ elif sep == ':':
78
+ start = int(start) - 1 if start else None
79
+ end = int(end) - 1 if end else None
80
+ else:
81
+ end = int(start)
82
+ start = int(start) - 1
83
+ yield (start, end)
84
+
85
+
86
+ def extract_symbols(code, symbols):
87
+ """
88
+ Return a tuple (blocks, not_found)
89
+ where ``blocks`` is a list of code fragments
90
+ for each symbol parsed from code, and ``not_found`` are
91
+ symbols not found in the code.
92
+
93
+ For example::
94
+
95
+ In [1]: code = '''a = 10
96
+ ...: def b(): return 42
97
+ ...: class A: pass'''
98
+
99
+ In [2]: extract_symbols(code, 'A,b,z')
100
+ Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
101
+ """
102
+ symbols = symbols.split(',')
103
+
104
+ # this will raise SyntaxError if code isn't valid Python
105
+ py_code = ast.parse(code)
106
+
107
+ marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
108
+ code = code.split('\n')
109
+
110
+ symbols_lines = {}
111
+
112
+ # we already know the start_lineno of each symbol (marks).
113
+ # To find each end_lineno, we traverse in reverse order until each
114
+ # non-blank line
115
+ end = len(code)
116
+ for name, start in reversed(marks):
117
+ while not code[end - 1].strip():
118
+ end -= 1
119
+ if name:
120
+ symbols_lines[name] = (start - 1, end)
121
+ end = start - 1
122
+
123
+ # Now symbols_lines is a map
124
+ # {'symbol_name': (start_lineno, end_lineno), ...}
125
+
126
+ # fill a list with chunks of codes for each requested symbol
127
+ blocks = []
128
+ not_found = []
129
+ for symbol in symbols:
130
+ if symbol in symbols_lines:
131
+ start, end = symbols_lines[symbol]
132
+ blocks.append('\n'.join(code[start:end]) + '\n')
133
+ else:
134
+ not_found.append(symbol)
135
+
136
+ return blocks, not_found
137
+
138
+ def strip_initial_indent(lines):
139
+ """For %load, strip indent from lines until finding an unindented line.
140
+
141
+ https://github.com/ipython/ipython/issues/9775
142
+ """
143
+ indent_re = re.compile(r'\s+')
144
+
145
+ it = iter(lines)
146
+ first_line = next(it)
147
+ indent_match = indent_re.match(first_line)
148
+
149
+ if indent_match:
150
+ # First line was indented
151
+ indent = indent_match.group()
152
+ yield first_line[len(indent):]
153
+
154
+ for line in it:
155
+ if line.startswith(indent):
156
+ yield line[len(indent) :]
157
+ elif line in ("\n", "\r\n") or len(line) == 0:
158
+ yield line
159
+ else:
160
+ # Less indented than the first line - stop dedenting
161
+ yield line
162
+ break
163
+ else:
164
+ yield first_line
165
+
166
+ # Pass the remaining lines through without dedenting
167
+ for line in it:
168
+ yield line
169
+
170
+
171
+ class InteractivelyDefined(Exception):
172
+ """Exception for interactively defined variable in magic_edit"""
173
+ def __init__(self, index):
174
+ self.index = index
175
+
176
+
177
+ @magics_class
178
+ class CodeMagics(Magics):
179
+ """Magics related to code management (loading, saving, editing, ...)."""
180
+
181
+ def __init__(self, *args, **kwargs):
182
+ self._knowntemps = set()
183
+ super(CodeMagics, self).__init__(*args, **kwargs)
184
+
185
+ @line_magic
186
+ def save(self, parameter_s=''):
187
+ """Save a set of lines or a macro to a given filename.
188
+
189
+ Usage:\\
190
+ %save [options] filename [history]
191
+
192
+ Options:
193
+
194
+ -r: use 'raw' input. By default, the 'processed' history is used,
195
+ so that magics are loaded in their transformed version to valid
196
+ Python. If this option is given, the raw input as typed at the
197
+ command line is used instead.
198
+
199
+ -f: force overwrite. If file exists, %save will prompt for overwrite
200
+ unless -f is given.
201
+
202
+ -a: append to the file instead of overwriting it.
203
+
204
+ The history argument uses the same syntax as %history for input ranges,
205
+ then saves the lines to the filename you specify.
206
+
207
+ If no ranges are specified, saves history of the current session up to
208
+ this point.
209
+
210
+ It adds a '.py' extension to the file if you don't do so yourself, and
211
+ it asks for confirmation before overwriting existing files.
212
+
213
+ If `-r` option is used, the default extension is `.ipy`.
214
+ """
215
+
216
+ opts,args = self.parse_options(parameter_s,'fra',mode='list')
217
+ if not args:
218
+ raise UsageError('Missing filename.')
219
+ raw = 'r' in opts
220
+ force = 'f' in opts
221
+ append = 'a' in opts
222
+ mode = 'a' if append else 'w'
223
+ ext = '.ipy' if raw else '.py'
224
+ fname, codefrom = args[0], " ".join(args[1:])
225
+ if not fname.endswith(('.py','.ipy')):
226
+ fname += ext
227
+ fname = os.path.expanduser(fname)
228
+ file_exists = os.path.isfile(fname)
229
+ if file_exists and not force and not append:
230
+ try:
231
+ overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
232
+ except StdinNotImplementedError:
233
+ print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
234
+ return
235
+ if not overwrite :
236
+ print('Operation cancelled.')
237
+ return
238
+ try:
239
+ cmds = self.shell.find_user_code(codefrom,raw)
240
+ except (TypeError, ValueError) as e:
241
+ print(e.args[0])
242
+ return
243
+ with io.open(fname, mode, encoding="utf-8") as f:
244
+ if not file_exists or not append:
245
+ f.write("# coding: utf-8\n")
246
+ f.write(cmds)
247
+ # make sure we end on a newline
248
+ if not cmds.endswith('\n'):
249
+ f.write('\n')
250
+ print('The following commands were written to file `%s`:' % fname)
251
+ print(cmds)
252
+
253
+ @line_magic
254
+ def pastebin(self, parameter_s=''):
255
+ """Upload code to dpaste.com, returning the URL.
256
+
257
+ Usage:\\
258
+ %pastebin [-d "Custom description"][-e 24] 1-7
259
+
260
+ The argument can be an input history range, a filename, or the name of a
261
+ string or macro.
262
+
263
+ If no arguments are given, uploads the history of this session up to
264
+ this point.
265
+
266
+ Options:
267
+
268
+ -d: Pass a custom description. The default will say
269
+ "Pasted from IPython".
270
+ -e: Pass number of days for the link to be expired.
271
+ The default will be 7 days.
272
+ """
273
+ opts, args = self.parse_options(parameter_s, "d:e:")
274
+
275
+ try:
276
+ code = self.shell.find_user_code(args)
277
+ except (ValueError, TypeError) as e:
278
+ print(e.args[0])
279
+ return
280
+
281
+ expiry_days = 7
282
+ try:
283
+ expiry_days = int(opts.get("e", 7))
284
+ except ValueError as e:
285
+ print(e.args[0].capitalize())
286
+ return
287
+ if expiry_days < 1 or expiry_days > 365:
288
+ print("Expiry days should be in range of 1 to 365")
289
+ return
290
+
291
+ post_data = urlencode(
292
+ {
293
+ "title": opts.get("d", "Pasted from IPython"),
294
+ "syntax": "python",
295
+ "content": code,
296
+ "expiry_days": expiry_days,
297
+ }
298
+ ).encode("utf-8")
299
+
300
+ request = Request(
301
+ "https://dpaste.com/api/v2/",
302
+ headers={"User-Agent": "IPython v{}".format(version)},
303
+ )
304
+ response = urlopen(request, post_data)
305
+ return response.headers.get('Location')
306
+
307
+ @line_magic
308
+ def loadpy(self, arg_s):
309
+ """Alias of `%load`
310
+
311
+ `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
312
+ extension. So it has been renamed simply into %load. You can look at
313
+ `%load`'s docstring for more info.
314
+ """
315
+ self.load(arg_s)
316
+
317
+ @line_magic
318
+ def load(self, arg_s):
319
+ """Load code into the current frontend.
320
+
321
+ Usage:\\
322
+ %load [options] source
323
+
324
+ where source can be a filename, URL, input history range, macro, or
325
+ element in the user namespace
326
+
327
+ If no arguments are given, loads the history of this session up to this
328
+ point.
329
+
330
+ Options:
331
+
332
+ -r <lines>: Specify lines or ranges of lines to load from the source.
333
+ Ranges could be specified as x-y (x..y) or in python-style x:y
334
+ (x..(y-1)). Both limits x and y can be left blank (meaning the
335
+ beginning and end of the file, respectively).
336
+
337
+ -s <symbols>: Specify function or classes to load from python source.
338
+
339
+ -y : Don't ask confirmation for loading source above 200 000 characters.
340
+
341
+ -n : Include the user's namespace when searching for source code.
342
+
343
+ This magic command can either take a local filename, a URL, an history
344
+ range (see %history) or a macro as argument, it will prompt for
345
+ confirmation before loading source with more than 200 000 characters, unless
346
+ -y flag is passed or if the frontend does not support raw_input::
347
+
348
+ %load
349
+ %load myscript.py
350
+ %load 7-27
351
+ %load myMacro
352
+ %load http://www.example.com/myscript.py
353
+ %load -r 5-10 myscript.py
354
+ %load -r 10-20,30,40: foo.py
355
+ %load -s MyClass,wonder_function myscript.py
356
+ %load -n MyClass
357
+ %load -n my_module.wonder_function
358
+ """
359
+ opts,args = self.parse_options(arg_s,'yns:r:')
360
+ search_ns = 'n' in opts
361
+ contents = self.shell.find_user_code(args, search_ns=search_ns)
362
+
363
+ if 's' in opts:
364
+ try:
365
+ blocks, not_found = extract_symbols(contents, opts['s'])
366
+ except SyntaxError:
367
+ # non python code
368
+ error("Unable to parse the input as valid Python code")
369
+ return
370
+
371
+ if len(not_found) == 1:
372
+ warn('The symbol `%s` was not found' % not_found[0])
373
+ elif len(not_found) > 1:
374
+ warn('The symbols %s were not found' % get_text_list(not_found,
375
+ wrap_item_with='`')
376
+ )
377
+
378
+ contents = '\n'.join(blocks)
379
+
380
+ if 'r' in opts:
381
+ ranges = opts['r'].replace(',', ' ')
382
+ lines = contents.split('\n')
383
+ slices = extract_code_ranges(ranges)
384
+ contents = [lines[slice(*slc)] for slc in slices]
385
+ contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
386
+
387
+ l = len(contents)
388
+
389
+ # 200 000 is ~ 2500 full 80 character lines
390
+ # so in average, more than 5000 lines
391
+ if l > 200000 and 'y' not in opts:
392
+ try:
393
+ ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
394
+ " (%d characters). Continue (y/[N]) ?" % l), default='n' )
395
+ except StdinNotImplementedError:
396
+ #assume yes if raw input not implemented
397
+ ans = True
398
+
399
+ if ans is False :
400
+ print('Operation cancelled.')
401
+ return
402
+
403
+ contents = "# %load {}\n".format(arg_s) + contents
404
+
405
+ self.shell.set_next_input(contents, replace=True)
406
+
407
+ @staticmethod
408
+ def _find_edit_target(shell, args, opts, last_call):
409
+ """Utility method used by magic_edit to find what to edit."""
410
+
411
+ def make_filename(arg):
412
+ "Make a filename from the given args"
413
+ try:
414
+ filename = get_py_filename(arg)
415
+ except IOError:
416
+ # If it ends with .py but doesn't already exist, assume we want
417
+ # a new file.
418
+ if arg.endswith('.py'):
419
+ filename = arg
420
+ else:
421
+ filename = None
422
+ return filename
423
+
424
+ # Set a few locals from the options for convenience:
425
+ opts_prev = 'p' in opts
426
+ opts_raw = 'r' in opts
427
+
428
+ # custom exceptions
429
+ class DataIsObject(Exception): pass
430
+
431
+ # Default line number value
432
+ lineno = opts.get('n',None)
433
+
434
+ if opts_prev:
435
+ args = '_%s' % last_call[0]
436
+ if args not in shell.user_ns:
437
+ args = last_call[1]
438
+
439
+ # by default this is done with temp files, except when the given
440
+ # arg is a filename
441
+ use_temp = True
442
+
443
+ data = ''
444
+
445
+ # First, see if the arguments should be a filename.
446
+ filename = make_filename(args)
447
+ if filename:
448
+ use_temp = False
449
+ elif args:
450
+ # Mode where user specifies ranges of lines, like in %macro.
451
+ data = shell.extract_input_lines(args, opts_raw)
452
+ if not data:
453
+ try:
454
+ # Load the parameter given as a variable. If not a string,
455
+ # process it as an object instead (below)
456
+
457
+ # print('*** args',args,'type',type(args)) # dbg
458
+ data = eval(args, shell.user_ns)
459
+ if not isinstance(data, str):
460
+ raise DataIsObject
461
+
462
+ except (NameError,SyntaxError):
463
+ # given argument is not a variable, try as a filename
464
+ filename = make_filename(args)
465
+ if filename is None:
466
+ warn("Argument given (%s) can't be found as a variable "
467
+ "or as a filename." % args)
468
+ return (None, None, None)
469
+ use_temp = False
470
+
471
+ except DataIsObject as e:
472
+ # macros have a special edit function
473
+ if isinstance(data, Macro):
474
+ raise MacroToEdit(data) from e
475
+
476
+ # For objects, try to edit the file where they are defined
477
+ filename = find_file(data)
478
+ if filename:
479
+ if 'fakemodule' in filename.lower() and \
480
+ inspect.isclass(data):
481
+ # class created by %edit? Try to find source
482
+ # by looking for method definitions instead, the
483
+ # __module__ in those classes is FakeModule.
484
+ attrs = [getattr(data, aname) for aname in dir(data)]
485
+ for attr in attrs:
486
+ if not inspect.ismethod(attr):
487
+ continue
488
+ filename = find_file(attr)
489
+ if filename and \
490
+ 'fakemodule' not in filename.lower():
491
+ # change the attribute to be the edit
492
+ # target instead
493
+ data = attr
494
+ break
495
+
496
+ m = ipython_input_pat.match(os.path.basename(filename))
497
+ if m:
498
+ raise InteractivelyDefined(int(m.groups()[0])) from e
499
+
500
+ datafile = 1
501
+ if filename is None:
502
+ filename = make_filename(args)
503
+ datafile = 1
504
+ if filename is not None:
505
+ # only warn about this if we get a real name
506
+ warn('Could not find file where `%s` is defined.\n'
507
+ 'Opening a file named `%s`' % (args, filename))
508
+ # Now, make sure we can actually read the source (if it was
509
+ # in a temp file it's gone by now).
510
+ if datafile:
511
+ if lineno is None:
512
+ lineno = find_source_lines(data)
513
+ if lineno is None:
514
+ filename = make_filename(args)
515
+ if filename is None:
516
+ warn('The file where `%s` was defined '
517
+ 'cannot be read or found.' % data)
518
+ return (None, None, None)
519
+ use_temp = False
520
+
521
+ if use_temp:
522
+ filename = shell.mktempfile(data)
523
+ print('IPython will make a temporary file named:',filename)
524
+
525
+ # use last_call to remember the state of the previous call, but don't
526
+ # let it be clobbered by successive '-p' calls.
527
+ try:
528
+ last_call[0] = shell.displayhook.prompt_count
529
+ if not opts_prev:
530
+ last_call[1] = args
531
+ except:
532
+ pass
533
+
534
+
535
+ return filename, lineno, use_temp
536
+
537
+ def _edit_macro(self,mname,macro):
538
+ """open an editor with the macro data in a file"""
539
+ filename = self.shell.mktempfile(macro.value)
540
+ self.shell.hooks.editor(filename)
541
+
542
+ # and make a new macro object, to replace the old one
543
+ mvalue = Path(filename).read_text(encoding="utf-8")
544
+ self.shell.user_ns[mname] = Macro(mvalue)
545
+
546
+ @skip_doctest
547
+ @line_magic
548
+ def edit(self, parameter_s='',last_call=['','']):
549
+ """Bring up an editor and execute the resulting code.
550
+
551
+ Usage:
552
+ %edit [options] [args]
553
+
554
+ %edit runs IPython's editor hook. The default version of this hook is
555
+ set to call the editor specified by your $EDITOR environment variable.
556
+ If this isn't found, it will default to vi under Linux/Unix and to
557
+ notepad under Windows. See the end of this docstring for how to change
558
+ the editor hook.
559
+
560
+ You can also set the value of this editor via the
561
+ ``TerminalInteractiveShell.editor`` option in your configuration file.
562
+ This is useful if you wish to use a different editor from your typical
563
+ default with IPython (and for Windows users who typically don't set
564
+ environment variables).
565
+
566
+ This command allows you to conveniently edit multi-line code right in
567
+ your IPython session.
568
+
569
+ If called without arguments, %edit opens up an empty editor with a
570
+ temporary file and will execute the contents of this file when you
571
+ close it (don't forget to save it!).
572
+
573
+
574
+ Options:
575
+
576
+ -n <number>: open the editor at a specified line number. By default,
577
+ the IPython editor hook uses the unix syntax 'editor +N filename', but
578
+ you can configure this by providing your own modified hook if your
579
+ favorite editor supports line-number specifications with a different
580
+ syntax.
581
+
582
+ -p: this will call the editor with the same data as the previous time
583
+ it was used, regardless of how long ago (in your current session) it
584
+ was.
585
+
586
+ -r: use 'raw' input. This option only applies to input taken from the
587
+ user's history. By default, the 'processed' history is used, so that
588
+ magics are loaded in their transformed version to valid Python. If
589
+ this option is given, the raw input as typed as the command line is
590
+ used instead. When you exit the editor, it will be executed by
591
+ IPython's own processor.
592
+
593
+ -x: do not execute the edited code immediately upon exit. This is
594
+ mainly useful if you are editing programs which need to be called with
595
+ command line arguments, which you can then do using %run.
596
+
597
+
598
+ Arguments:
599
+
600
+ If arguments are given, the following possibilities exist:
601
+
602
+ - If the argument is a filename, IPython will load that into the
603
+ editor. It will execute its contents with execfile() when you exit,
604
+ loading any code in the file into your interactive namespace.
605
+
606
+ - The arguments are ranges of input history, e.g. "7 ~1/4-6".
607
+ The syntax is the same as in the %history magic.
608
+
609
+ - If the argument is a string variable, its contents are loaded
610
+ into the editor. You can thus edit any string which contains
611
+ python code (including the result of previous edits).
612
+
613
+ - If the argument is the name of an object (other than a string),
614
+ IPython will try to locate the file where it was defined and open the
615
+ editor at the point where it is defined. You can use `%edit function`
616
+ to load an editor exactly at the point where 'function' is defined,
617
+ edit it and have the file be executed automatically.
618
+
619
+ - If the object is a macro (see %macro for details), this opens up your
620
+ specified editor with a temporary file containing the macro's data.
621
+ Upon exit, the macro is reloaded with the contents of the file.
622
+
623
+ Note: opening at an exact line is only supported under Unix, and some
624
+ editors (like kedit and gedit up to Gnome 2.8) do not understand the
625
+ '+NUMBER' parameter necessary for this feature. Good editors like
626
+ (X)Emacs, vi, jed, pico and joe all do.
627
+
628
+ After executing your code, %edit will return as output the code you
629
+ typed in the editor (except when it was an existing file). This way
630
+ you can reload the code in further invocations of %edit as a variable,
631
+ via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
632
+ the output.
633
+
634
+ Note that %edit is also available through the alias %ed.
635
+
636
+ This is an example of creating a simple function inside the editor and
637
+ then modifying it. First, start up the editor::
638
+
639
+ In [1]: edit
640
+ Editing... done. Executing edited code...
641
+ Out[1]: 'def foo():\\n print("foo() was defined in an editing
642
+ session")\\n'
643
+
644
+ We can then call the function foo()::
645
+
646
+ In [2]: foo()
647
+ foo() was defined in an editing session
648
+
649
+ Now we edit foo. IPython automatically loads the editor with the
650
+ (temporary) file where foo() was previously defined::
651
+
652
+ In [3]: edit foo
653
+ Editing... done. Executing edited code...
654
+
655
+ And if we call foo() again we get the modified version::
656
+
657
+ In [4]: foo()
658
+ foo() has now been changed!
659
+
660
+ Here is an example of how to edit a code snippet successive
661
+ times. First we call the editor::
662
+
663
+ In [5]: edit
664
+ Editing... done. Executing edited code...
665
+ hello
666
+ Out[5]: "print('hello')\\n"
667
+
668
+ Now we call it again with the previous output (stored in _)::
669
+
670
+ In [6]: edit _
671
+ Editing... done. Executing edited code...
672
+ hello world
673
+ Out[6]: "print('hello world')\\n"
674
+
675
+ Now we call it with the output #8 (stored in _8, also as Out[8])::
676
+
677
+ In [7]: edit _8
678
+ Editing... done. Executing edited code...
679
+ hello again
680
+ Out[7]: "print('hello again')\\n"
681
+
682
+
683
+ Changing the default editor hook:
684
+
685
+ If you wish to write your own editor hook, you can put it in a
686
+ configuration file which you load at startup time. The default hook
687
+ is defined in the IPython.core.hooks module, and you can use that as a
688
+ starting example for further modifications. That file also has
689
+ general instructions on how to set a new hook for use once you've
690
+ defined it."""
691
+ opts,args = self.parse_options(parameter_s,'prxn:')
692
+
693
+ try:
694
+ filename, lineno, is_temp = self._find_edit_target(self.shell,
695
+ args, opts, last_call)
696
+ except MacroToEdit as e:
697
+ self._edit_macro(args, e.args[0])
698
+ return
699
+ except InteractivelyDefined as e:
700
+ print("Editing In[%i]" % e.index)
701
+ args = str(e.index)
702
+ filename, lineno, is_temp = self._find_edit_target(self.shell,
703
+ args, opts, last_call)
704
+ if filename is None:
705
+ # nothing was found, warnings have already been issued,
706
+ # just give up.
707
+ return
708
+
709
+ if is_temp:
710
+ self._knowntemps.add(filename)
711
+ elif (filename in self._knowntemps):
712
+ is_temp = True
713
+
714
+
715
+ # do actual editing here
716
+ print('Editing...', end=' ')
717
+ sys.stdout.flush()
718
+ filepath = Path(filename)
719
+ try:
720
+ # Quote filenames that may have spaces in them when opening
721
+ # the editor
722
+ quoted = filename = str(filepath.absolute())
723
+ if " " in quoted:
724
+ quoted = "'%s'" % quoted
725
+ self.shell.hooks.editor(quoted, lineno)
726
+ except TryNext:
727
+ warn('Could not open editor')
728
+ return
729
+
730
+ # XXX TODO: should this be generalized for all string vars?
731
+ # For now, this is special-cased to blocks created by cpaste
732
+ if args.strip() == "pasted_block":
733
+ self.shell.user_ns["pasted_block"] = filepath.read_text(encoding="utf-8")
734
+
735
+ if 'x' in opts: # -x prevents actual execution
736
+ print()
737
+ else:
738
+ print('done. Executing edited code...')
739
+ with preserve_keys(self.shell.user_ns, '__file__'):
740
+ if not is_temp:
741
+ self.shell.user_ns["__file__"] = filename
742
+ if "r" in opts: # Untranslated IPython code
743
+ source = filepath.read_text(encoding="utf-8")
744
+ self.shell.run_cell(source, store_history=False)
745
+ else:
746
+ self.shell.safe_execfile(filename, self.shell.user_ns,
747
+ self.shell.user_ns)
748
+
749
+ if is_temp:
750
+ try:
751
+ return filepath.read_text(encoding="utf-8")
752
+ except IOError as msg:
753
+ if Path(msg.filename) == filepath:
754
+ warn('File not found. Did you forget to save?')
755
+ return
756
+ else:
757
+ self.shell.showtraceback()
temp_venv/lib/python3.13/site-packages/IPython/core/magics/config.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of configuration-related magic functions.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Stdlib
16
+ import re
17
+
18
+ # Our own packages
19
+ from IPython.core.error import UsageError
20
+ from IPython.core.magic import Magics, magics_class, line_magic
21
+ from logging import error
22
+
23
+ #-----------------------------------------------------------------------------
24
+ # Magic implementation classes
25
+ #-----------------------------------------------------------------------------
26
+
27
+ reg = re.compile(r'^\w+\.\w+$')
28
+ @magics_class
29
+ class ConfigMagics(Magics):
30
+
31
+ def __init__(self, shell):
32
+ super(ConfigMagics, self).__init__(shell)
33
+ self.configurables = []
34
+
35
+ @line_magic
36
+ def config(self, s):
37
+ """configure IPython
38
+
39
+ %config Class[.trait=value]
40
+
41
+ This magic exposes most of the IPython config system. Any
42
+ Configurable class should be able to be configured with the simple
43
+ line::
44
+
45
+ %config Class.trait=value
46
+
47
+ Where `value` will be resolved in the user's namespace, if it is an
48
+ expression or variable name.
49
+
50
+ Examples
51
+ --------
52
+
53
+ To see what classes are available for config, pass no arguments::
54
+
55
+ In [1]: %config
56
+ Available objects for config:
57
+ AliasManager
58
+ DisplayFormatter
59
+ HistoryManager
60
+ IPCompleter
61
+ LoggingMagics
62
+ MagicsManager
63
+ OSMagics
64
+ PrefilterManager
65
+ ScriptMagics
66
+ TerminalInteractiveShell
67
+
68
+ To view what is configurable on a given class, just pass the class
69
+ name::
70
+
71
+ In [2]: %config LoggingMagics
72
+ LoggingMagics(Magics) options
73
+ ---------------------------
74
+ LoggingMagics.quiet=<Bool>
75
+ Suppress output of log state when logging is enabled
76
+ Current: False
77
+
78
+ but the real use is in setting values::
79
+
80
+ In [3]: %config LoggingMagics.quiet = True
81
+
82
+ and these values are read from the user_ns if they are variables::
83
+
84
+ In [4]: feeling_quiet=False
85
+
86
+ In [5]: %config LoggingMagics.quiet = feeling_quiet
87
+
88
+ """
89
+ from traitlets.config.loader import Config
90
+ # some IPython objects are Configurable, but do not yet have
91
+ # any configurable traits. Exclude them from the effects of
92
+ # this magic, as their presence is just noise:
93
+ configurables = sorted(set([ c for c in self.shell.configurables
94
+ if c.__class__.class_traits(config=True)
95
+ ]), key=lambda x: x.__class__.__name__)
96
+ classnames = [ c.__class__.__name__ for c in configurables ]
97
+
98
+ line = s.strip()
99
+ if not line:
100
+ # print available configurable names
101
+ print("Available objects for config:")
102
+ for name in classnames:
103
+ print(" ", name)
104
+ return
105
+ elif line in classnames:
106
+ # `%config TerminalInteractiveShell` will print trait info for
107
+ # TerminalInteractiveShell
108
+ c = configurables[classnames.index(line)]
109
+ cls = c.__class__
110
+ help = cls.class_get_help(c)
111
+ # strip leading '--' from cl-args:
112
+ help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
113
+ print(help)
114
+ return
115
+ elif reg.match(line):
116
+ cls, attr = line.split('.')
117
+ return getattr(configurables[classnames.index(cls)],attr)
118
+ elif '=' not in line:
119
+ msg = "Invalid config statement: %r, "\
120
+ "should be `Class.trait = value`."
121
+
122
+ ll = line.lower()
123
+ for classname in classnames:
124
+ if ll == classname.lower():
125
+ msg = msg + '\nDid you mean %s (note the case)?' % classname
126
+ break
127
+
128
+ raise UsageError( msg % line)
129
+
130
+ # otherwise, assume we are setting configurables.
131
+ # leave quotes on args when splitting, because we want
132
+ # unquoted args to eval in user_ns
133
+ cfg = Config()
134
+ exec("cfg."+line, self.shell.user_ns, locals())
135
+
136
+ for configurable in configurables:
137
+ try:
138
+ configurable.update_config(cfg)
139
+ except Exception as e:
140
+ error(e)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/display.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Simple magics for display formats"""
2
+ #-----------------------------------------------------------------------------
3
+ # Copyright (c) 2012 The IPython Development Team.
4
+ #
5
+ # Distributed under the terms of the Modified BSD License.
6
+ #
7
+ # The full license is in the file COPYING.txt, distributed with this software.
8
+ #-----------------------------------------------------------------------------
9
+
10
+ #-----------------------------------------------------------------------------
11
+ # Imports
12
+ #-----------------------------------------------------------------------------
13
+
14
+ # Our own packages
15
+ from IPython.display import display, Javascript, Latex, SVG, HTML, Markdown
16
+ from IPython.core.magic import (
17
+ Magics, magics_class, cell_magic
18
+ )
19
+ from IPython.core import magic_arguments
20
+
21
+ #-----------------------------------------------------------------------------
22
+ # Magic implementation classes
23
+ #-----------------------------------------------------------------------------
24
+
25
+
26
+ @magics_class
27
+ class DisplayMagics(Magics):
28
+ """Magics for displaying various output types with literals
29
+
30
+ Defines javascript/latex/svg/html cell magics for writing
31
+ blocks in those languages, to be rendered in the frontend.
32
+ """
33
+
34
+ @cell_magic
35
+ def js(self, line, cell):
36
+ """Run the cell block of Javascript code
37
+
38
+ Alias of `%%javascript`
39
+
40
+ Starting with IPython 8.0 %%javascript is pending deprecation to be replaced
41
+ by a more flexible system
42
+
43
+ Please See https://github.com/ipython/ipython/issues/13376
44
+ """
45
+ self.javascript(line, cell)
46
+
47
+ @cell_magic
48
+ def javascript(self, line, cell):
49
+ """Run the cell block of Javascript code
50
+
51
+ Starting with IPython 8.0 %%javascript is pending deprecation to be replaced
52
+ by a more flexible system
53
+
54
+ Please See https://github.com/ipython/ipython/issues/13376
55
+ """
56
+ display(Javascript(cell))
57
+
58
+
59
+ @cell_magic
60
+ def latex(self, line, cell):
61
+ """Render the cell as a block of LaTeX
62
+
63
+ The subset of LaTeX which is supported depends on the implementation in
64
+ the client. In the Jupyter Notebook, this magic only renders the subset
65
+ of LaTeX defined by MathJax
66
+ [here](https://docs.mathjax.org/en/v2.5-latest/tex.html)."""
67
+ display(Latex(cell))
68
+
69
+ @cell_magic
70
+ def svg(self, line, cell):
71
+ """Render the cell as an SVG literal"""
72
+ display(SVG(cell))
73
+
74
+ @magic_arguments.magic_arguments()
75
+ @magic_arguments.argument(
76
+ '--isolated', action='store_true', default=False,
77
+ help="""Annotate the cell as 'isolated'.
78
+ Isolated cells are rendered inside their own <iframe> tag"""
79
+ )
80
+ @cell_magic
81
+ def html(self, line, cell):
82
+ """Render the cell as a block of HTML"""
83
+ args = magic_arguments.parse_argstring(self.html, line)
84
+ html = HTML(cell)
85
+ if args.isolated:
86
+ display(html, metadata={'text/html':{'isolated':True}})
87
+ else:
88
+ display(html)
89
+
90
+ @cell_magic
91
+ def markdown(self, line, cell):
92
+ """Render the cell as Markdown text block"""
93
+ display(Markdown(cell))
temp_venv/lib/python3.13/site-packages/IPython/core/magics/execution.py ADDED
@@ -0,0 +1,1677 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Implementation of execution-related magic functions."""
3
+
4
+ # Copyright (c) IPython Development Team.
5
+ # Distributed under the terms of the Modified BSD License.
6
+
7
+
8
+ import ast
9
+ import bdb
10
+ import builtins as builtin_mod
11
+ import copy
12
+ import cProfile as profile
13
+ import gc
14
+ import itertools
15
+ import math
16
+ import os
17
+ import pstats
18
+ import re
19
+ import shlex
20
+ import sys
21
+ import time
22
+ import timeit
23
+ from typing import Dict, Any
24
+ from ast import (
25
+ Assign,
26
+ Call,
27
+ Expr,
28
+ Load,
29
+ Module,
30
+ Name,
31
+ NodeTransformer,
32
+ Store,
33
+ parse,
34
+ unparse,
35
+ )
36
+ from io import StringIO
37
+ from logging import error
38
+ from pathlib import Path
39
+ from pdb import Restart
40
+ from textwrap import dedent, indent
41
+ from warnings import warn
42
+
43
+ from IPython.core import magic_arguments, oinspect, page
44
+ from IPython.core.displayhook import DisplayHook
45
+ from IPython.core.error import UsageError
46
+ from IPython.core.macro import Macro
47
+ from IPython.core.magic import (
48
+ Magics,
49
+ cell_magic,
50
+ line_cell_magic,
51
+ line_magic,
52
+ magics_class,
53
+ needs_local_scope,
54
+ no_var_expand,
55
+ on_off,
56
+ output_can_be_silenced,
57
+ )
58
+ from IPython.testing.skipdoctest import skip_doctest
59
+ from IPython.utils.capture import capture_output
60
+ from IPython.utils.contexts import preserve_keys
61
+ from IPython.utils.ipstruct import Struct
62
+ from IPython.utils.module_paths import find_mod
63
+ from IPython.utils.path import get_py_filename, shellglob
64
+ from IPython.utils.timing import clock, clock2
65
+ from IPython.core.magics.ast_mod import ReplaceCodeTransformer
66
+
67
+ #-----------------------------------------------------------------------------
68
+ # Magic implementation classes
69
+ #-----------------------------------------------------------------------------
70
+
71
+
72
+ class TimeitResult:
73
+ """
74
+ Object returned by the timeit magic with info about the run.
75
+
76
+ Contains the following attributes:
77
+
78
+ loops: int
79
+ number of loops done per measurement
80
+
81
+ repeat: int
82
+ number of times the measurement was repeated
83
+
84
+ best: float
85
+ best execution time / number
86
+
87
+ all_runs : list[float]
88
+ execution time of each run (in s)
89
+
90
+ compile_time: float
91
+ time of statement compilation (s)
92
+
93
+ """
94
+ def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
95
+ self.loops = loops
96
+ self.repeat = repeat
97
+ self.best = best
98
+ self.worst = worst
99
+ self.all_runs = all_runs
100
+ self.compile_time = compile_time
101
+ self._precision = precision
102
+ self.timings = [dt / self.loops for dt in all_runs]
103
+
104
+ @property
105
+ def average(self):
106
+ return math.fsum(self.timings) / len(self.timings)
107
+
108
+ @property
109
+ def stdev(self):
110
+ mean = self.average
111
+ return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
112
+
113
+ def __str__(self):
114
+ pm = '+-'
115
+ if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
116
+ try:
117
+ "\xb1".encode(sys.stdout.encoding)
118
+ pm = "\xb1"
119
+ except:
120
+ pass
121
+ return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
122
+ pm=pm,
123
+ runs=self.repeat,
124
+ loops=self.loops,
125
+ loop_plural="" if self.loops == 1 else "s",
126
+ run_plural="" if self.repeat == 1 else "s",
127
+ mean=_format_time(self.average, self._precision),
128
+ std=_format_time(self.stdev, self._precision),
129
+ )
130
+
131
+ def _repr_pretty_(self, p , cycle):
132
+ unic = self.__str__()
133
+ p.text("<TimeitResult : " + unic + ">")
134
+
135
+
136
+ class TimeitTemplateFiller(ast.NodeTransformer):
137
+ """Fill in the AST template for timing execution.
138
+
139
+ This is quite closely tied to the template definition, which is in
140
+ :meth:`ExecutionMagics.timeit`.
141
+ """
142
+ def __init__(self, ast_setup, ast_stmt):
143
+ self.ast_setup = ast_setup
144
+ self.ast_stmt = ast_stmt
145
+
146
+ def visit_FunctionDef(self, node):
147
+ "Fill in the setup statement"
148
+ self.generic_visit(node)
149
+ if node.name == "inner":
150
+ node.body[:1] = self.ast_setup.body
151
+
152
+ return node
153
+
154
+ def visit_For(self, node):
155
+ "Fill in the statement to be timed"
156
+ if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
157
+ node.body = self.ast_stmt.body
158
+ return node
159
+
160
+
161
+ class Timer(timeit.Timer):
162
+ """Timer class that explicitly uses self.inner
163
+
164
+ which is an undocumented implementation detail of CPython,
165
+ not shared by PyPy.
166
+ """
167
+
168
+ # Timer.timeit copied from CPython 3.4.2
169
+ def timeit(self, number=timeit.default_number):
170
+ """Time 'number' executions of the main statement.
171
+
172
+ To be precise, this executes the setup statement once, and
173
+ then returns the time it takes to execute the main statement
174
+ a number of times, as a float measured in seconds. The
175
+ argument is the number of times through the loop, defaulting
176
+ to one million. The main statement, the setup statement and
177
+ the timer function to be used are passed to the constructor.
178
+ """
179
+ it = itertools.repeat(None, number)
180
+ gcold = gc.isenabled()
181
+ gc.disable()
182
+ try:
183
+ timing = self.inner(it, self.timer)
184
+ finally:
185
+ if gcold:
186
+ gc.enable()
187
+ return timing
188
+
189
+
190
+ @magics_class
191
+ class ExecutionMagics(Magics):
192
+ """Magics related to code execution, debugging, profiling, etc."""
193
+
194
+ _transformers: Dict[str, Any] = {}
195
+
196
+ def __init__(self, shell):
197
+ super(ExecutionMagics, self).__init__(shell)
198
+ # Default execution function used to actually run user code.
199
+ self.default_runner = None
200
+
201
+ @skip_doctest
202
+ @no_var_expand
203
+ @line_cell_magic
204
+ def prun(self, parameter_s='', cell=None):
205
+ """Run a statement through the python code profiler.
206
+
207
+ **Usage, in line mode**::
208
+
209
+ %prun [options] statement
210
+
211
+ **Usage, in cell mode**::
212
+
213
+ %%prun [options] [statement]
214
+ code...
215
+ code...
216
+
217
+ In cell mode, the additional code lines are appended to the (possibly
218
+ empty) statement in the first line. Cell mode allows you to easily
219
+ profile multiline blocks without having to put them in a separate
220
+ function.
221
+
222
+ The given statement (which doesn't require quote marks) is run via the
223
+ python profiler in a manner similar to the profile.run() function.
224
+ Namespaces are internally managed to work correctly; profile.run
225
+ cannot be used in IPython because it makes certain assumptions about
226
+ namespaces which do not hold under IPython.
227
+
228
+ Options:
229
+
230
+ -l <limit>
231
+ you can place restrictions on what or how much of the
232
+ profile gets printed. The limit value can be:
233
+
234
+ * A string: only information for function names containing this string
235
+ is printed.
236
+
237
+ * An integer: only these many lines are printed.
238
+
239
+ * A float (between 0 and 1): this fraction of the report is printed
240
+ (for example, use a limit of 0.4 to see the topmost 40% only).
241
+
242
+ You can combine several limits with repeated use of the option. For
243
+ example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
244
+ information about class constructors.
245
+
246
+ -r
247
+ return the pstats.Stats object generated by the profiling. This
248
+ object has all the information about the profile in it, and you can
249
+ later use it for further analysis or in other functions.
250
+
251
+ -s <key>
252
+ sort profile by given key. You can provide more than one key
253
+ by using the option several times: '-s key1 -s key2 -s key3...'. The
254
+ default sorting key is 'time'.
255
+
256
+ The following is copied verbatim from the profile documentation
257
+ referenced below:
258
+
259
+ When more than one key is provided, additional keys are used as
260
+ secondary criteria when the there is equality in all keys selected
261
+ before them.
262
+
263
+ Abbreviations can be used for any key names, as long as the
264
+ abbreviation is unambiguous. The following are the keys currently
265
+ defined:
266
+
267
+ ============ =====================
268
+ Valid Arg Meaning
269
+ ============ =====================
270
+ "calls" call count
271
+ "cumulative" cumulative time
272
+ "file" file name
273
+ "module" file name
274
+ "pcalls" primitive call count
275
+ "line" line number
276
+ "name" function name
277
+ "nfl" name/file/line
278
+ "stdname" standard name
279
+ "time" internal time
280
+ ============ =====================
281
+
282
+ Note that all sorts on statistics are in descending order (placing
283
+ most time consuming items first), where as name, file, and line number
284
+ searches are in ascending order (i.e., alphabetical). The subtle
285
+ distinction between "nfl" and "stdname" is that the standard name is a
286
+ sort of the name as printed, which means that the embedded line
287
+ numbers get compared in an odd way. For example, lines 3, 20, and 40
288
+ would (if the file names were the same) appear in the string order
289
+ "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
290
+ line numbers. In fact, sort_stats("nfl") is the same as
291
+ sort_stats("name", "file", "line").
292
+
293
+ -T <filename>
294
+ save profile results as shown on screen to a text
295
+ file. The profile is still shown on screen.
296
+
297
+ -D <filename>
298
+ save (via dump_stats) profile statistics to given
299
+ filename. This data is in a format understood by the pstats module, and
300
+ is generated by a call to the dump_stats() method of profile
301
+ objects. The profile is still shown on screen.
302
+
303
+ -q
304
+ suppress output to the pager. Best used with -T and/or -D above.
305
+
306
+ If you want to run complete programs under the profiler's control, use
307
+ ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
308
+ contains profiler specific options as described here.
309
+
310
+ You can read the complete documentation for the profile module with::
311
+
312
+ In [1]: import profile; profile.help()
313
+
314
+ .. versionchanged:: 7.3
315
+ User variables are no longer expanded,
316
+ the magic line is always left unmodified.
317
+
318
+ """
319
+ opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
320
+ list_all=True, posix=False)
321
+ if cell is not None:
322
+ arg_str += '\n' + cell
323
+ arg_str = self.shell.transform_cell(arg_str)
324
+ return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
325
+
326
+ def _run_with_profiler(self, code, opts, namespace):
327
+ """
328
+ Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
329
+
330
+ Parameters
331
+ ----------
332
+ code : str
333
+ Code to be executed.
334
+ opts : Struct
335
+ Options parsed by `self.parse_options`.
336
+ namespace : dict
337
+ A dictionary for Python namespace (e.g., `self.shell.user_ns`).
338
+
339
+ """
340
+
341
+ # Fill default values for unspecified options:
342
+ opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
343
+
344
+ prof = profile.Profile()
345
+ try:
346
+ prof = prof.runctx(code, namespace, namespace)
347
+ sys_exit = ''
348
+ except SystemExit:
349
+ sys_exit = """*** SystemExit exception caught in code being profiled."""
350
+
351
+ stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
352
+
353
+ lims = opts.l
354
+ if lims:
355
+ lims = [] # rebuild lims with ints/floats/strings
356
+ for lim in opts.l:
357
+ try:
358
+ lims.append(int(lim))
359
+ except ValueError:
360
+ try:
361
+ lims.append(float(lim))
362
+ except ValueError:
363
+ lims.append(lim)
364
+
365
+ # Trap output.
366
+ stdout_trap = StringIO()
367
+ stats_stream = stats.stream
368
+ try:
369
+ stats.stream = stdout_trap
370
+ stats.print_stats(*lims)
371
+ finally:
372
+ stats.stream = stats_stream
373
+
374
+ output = stdout_trap.getvalue()
375
+ output = output.rstrip()
376
+
377
+ if 'q' not in opts:
378
+ page.page(output)
379
+ print(sys_exit, end=' ')
380
+
381
+ dump_file = opts.D[0]
382
+ text_file = opts.T[0]
383
+ if dump_file:
384
+ prof.dump_stats(dump_file)
385
+ print(
386
+ f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
387
+ )
388
+ if text_file:
389
+ pfile = Path(text_file)
390
+ pfile.touch(exist_ok=True)
391
+ pfile.write_text(output, encoding="utf-8")
392
+
393
+ print(
394
+ f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
395
+ )
396
+
397
+ if 'r' in opts:
398
+ return stats
399
+
400
+ return None
401
+
402
+ @line_magic
403
+ def pdb(self, parameter_s=''):
404
+ """Control the automatic calling of the pdb interactive debugger.
405
+
406
+ Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
407
+ argument it works as a toggle.
408
+
409
+ When an exception is triggered, IPython can optionally call the
410
+ interactive pdb debugger after the traceback printout. %pdb toggles
411
+ this feature on and off.
412
+
413
+ The initial state of this feature is set in your configuration
414
+ file (the option is ``InteractiveShell.pdb``).
415
+
416
+ If you want to just activate the debugger AFTER an exception has fired,
417
+ without having to type '%pdb on' and rerunning your code, you can use
418
+ the %debug magic."""
419
+
420
+ par = parameter_s.strip().lower()
421
+
422
+ if par:
423
+ try:
424
+ new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
425
+ except KeyError:
426
+ print ('Incorrect argument. Use on/1, off/0, '
427
+ 'or nothing for a toggle.')
428
+ return
429
+ else:
430
+ # toggle
431
+ new_pdb = not self.shell.call_pdb
432
+
433
+ # set on the shell
434
+ self.shell.call_pdb = new_pdb
435
+ print('Automatic pdb calling has been turned',on_off(new_pdb))
436
+
437
+ @magic_arguments.magic_arguments()
438
+ @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
439
+ help="""
440
+ Set break point at LINE in FILE.
441
+ """
442
+ )
443
+ @magic_arguments.argument('statement', nargs='*',
444
+ help="""
445
+ Code to run in debugger.
446
+ You can omit this in cell magic mode.
447
+ """
448
+ )
449
+ @no_var_expand
450
+ @line_cell_magic
451
+ @needs_local_scope
452
+ def debug(self, line="", cell=None, local_ns=None):
453
+ """Activate the interactive debugger.
454
+
455
+ This magic command support two ways of activating debugger.
456
+ One is to activate debugger before executing code. This way, you
457
+ can set a break point, to step through the code from the point.
458
+ You can use this mode by giving statements to execute and optionally
459
+ a breakpoint.
460
+
461
+ The other one is to activate debugger in post-mortem mode. You can
462
+ activate this mode simply running %debug without any argument.
463
+ If an exception has just occurred, this lets you inspect its stack
464
+ frames interactively. Note that this will always work only on the last
465
+ traceback that occurred, so you must call this quickly after an
466
+ exception that you wish to inspect has fired, because if another one
467
+ occurs, it clobbers the previous one.
468
+
469
+ If you want IPython to automatically do this on every exception, see
470
+ the %pdb magic for more details.
471
+
472
+ .. versionchanged:: 7.3
473
+ When running code, user variables are no longer expanded,
474
+ the magic line is always left unmodified.
475
+
476
+ """
477
+ args = magic_arguments.parse_argstring(self.debug, line)
478
+
479
+ if not (args.breakpoint or args.statement or cell):
480
+ self._debug_post_mortem()
481
+ elif not (args.breakpoint or cell):
482
+ # If there is no breakpoints, the line is just code to execute
483
+ self._debug_exec(line, None, local_ns)
484
+ else:
485
+ # Here we try to reconstruct the code from the output of
486
+ # parse_argstring. This might not work if the code has spaces
487
+ # For example this fails for `print("a b")`
488
+ code = "\n".join(args.statement)
489
+ if cell:
490
+ code += "\n" + cell
491
+ self._debug_exec(code, args.breakpoint, local_ns)
492
+
493
+ def _debug_post_mortem(self):
494
+ self.shell.debugger(force=True)
495
+
496
+ def _debug_exec(self, code, breakpoint, local_ns=None):
497
+ if breakpoint:
498
+ (filename, bp_line) = breakpoint.rsplit(':', 1)
499
+ bp_line = int(bp_line)
500
+ else:
501
+ (filename, bp_line) = (None, None)
502
+ self._run_with_debugger(
503
+ code, self.shell.user_ns, filename, bp_line, local_ns=local_ns
504
+ )
505
+
506
+ @line_magic
507
+ def tb(self, s):
508
+ """Print the last traceback.
509
+
510
+ Optionally, specify an exception reporting mode, tuning the
511
+ verbosity of the traceback. By default the currently-active exception
512
+ mode is used. See %xmode for changing exception reporting modes.
513
+
514
+ Valid modes: Plain, Context, Verbose, and Minimal.
515
+ """
516
+ interactive_tb = self.shell.InteractiveTB
517
+ if s:
518
+ # Switch exception reporting mode for this one call.
519
+ # Ensure it is switched back.
520
+ def xmode_switch_err(name):
521
+ warn('Error changing %s exception modes.\n%s' %
522
+ (name,sys.exc_info()[1]))
523
+
524
+ new_mode = s.strip().capitalize()
525
+ original_mode = interactive_tb.mode
526
+ try:
527
+ try:
528
+ interactive_tb.set_mode(mode=new_mode)
529
+ except Exception:
530
+ xmode_switch_err('user')
531
+ else:
532
+ self.shell.showtraceback()
533
+ finally:
534
+ interactive_tb.set_mode(mode=original_mode)
535
+ else:
536
+ self.shell.showtraceback()
537
+
538
+ @skip_doctest
539
+ @line_magic
540
+ def run(self, parameter_s='', runner=None,
541
+ file_finder=get_py_filename):
542
+ """Run the named file inside IPython as a program.
543
+
544
+ Usage::
545
+
546
+ %run [-n -i -e -G]
547
+ [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
548
+ ( -m mod | filename ) [args]
549
+
550
+ The filename argument should be either a pure Python script (with
551
+ extension ``.py``), or a file with custom IPython syntax (such as
552
+ magics). If the latter, the file can be either a script with ``.ipy``
553
+ extension, or a Jupyter notebook with ``.ipynb`` extension. When running
554
+ a Jupyter notebook, the output from print statements and other
555
+ displayed objects will appear in the terminal (even matplotlib figures
556
+ will open, if a terminal-compliant backend is being used). Note that,
557
+ at the system command line, the ``jupyter run`` command offers similar
558
+ functionality for executing notebooks (albeit currently with some
559
+ differences in supported options).
560
+
561
+ Parameters after the filename are passed as command-line arguments to
562
+ the program (put in sys.argv). Then, control returns to IPython's
563
+ prompt.
564
+
565
+ This is similar to running at a system prompt ``python file args``,
566
+ but with the advantage of giving you IPython's tracebacks, and of
567
+ loading all variables into your interactive namespace for further use
568
+ (unless -p is used, see below).
569
+
570
+ The file is executed in a namespace initially consisting only of
571
+ ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
572
+ sees its environment as if it were being run as a stand-alone program
573
+ (except for sharing global objects such as previously imported
574
+ modules). But after execution, the IPython interactive namespace gets
575
+ updated with all variables defined in the program (except for ``__name__``
576
+ and ``sys.argv``). This allows for very convenient loading of code for
577
+ interactive work, while giving each program a 'clean sheet' to run in.
578
+
579
+ Arguments are expanded using shell-like glob match. Patterns
580
+ '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
581
+ tilde '~' will be expanded into user's home directory. Unlike
582
+ real shells, quotation does not suppress expansions. Use
583
+ *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
584
+ To completely disable these expansions, you can use -G flag.
585
+
586
+ On Windows systems, the use of single quotes `'` when specifying
587
+ a file is not supported. Use double quotes `"`.
588
+
589
+ Options:
590
+
591
+ -n
592
+ __name__ is NOT set to '__main__', but to the running file's name
593
+ without extension (as python does under import). This allows running
594
+ scripts and reloading the definitions in them without calling code
595
+ protected by an ``if __name__ == "__main__"`` clause.
596
+
597
+ -i
598
+ run the file in IPython's namespace instead of an empty one. This
599
+ is useful if you are experimenting with code written in a text editor
600
+ which depends on variables defined interactively.
601
+
602
+ -e
603
+ ignore sys.exit() calls or SystemExit exceptions in the script
604
+ being run. This is particularly useful if IPython is being used to
605
+ run unittests, which always exit with a sys.exit() call. In such
606
+ cases you are interested in the output of the test results, not in
607
+ seeing a traceback of the unittest module.
608
+
609
+ -t
610
+ print timing information at the end of the run. IPython will give
611
+ you an estimated CPU time consumption for your script, which under
612
+ Unix uses the resource module to avoid the wraparound problems of
613
+ time.clock(). Under Unix, an estimate of time spent on system tasks
614
+ is also given (for Windows platforms this is reported as 0.0).
615
+
616
+ If -t is given, an additional ``-N<N>`` option can be given, where <N>
617
+ must be an integer indicating how many times you want the script to
618
+ run. The final timing report will include total and per run results.
619
+
620
+ For example (testing the script uniq_stable.py)::
621
+
622
+ In [1]: run -t uniq_stable
623
+
624
+ IPython CPU timings (estimated):
625
+ User : 0.19597 s.
626
+ System: 0.0 s.
627
+
628
+ In [2]: run -t -N5 uniq_stable
629
+
630
+ IPython CPU timings (estimated):
631
+ Total runs performed: 5
632
+ Times : Total Per run
633
+ User : 0.910862 s, 0.1821724 s.
634
+ System: 0.0 s, 0.0 s.
635
+
636
+ -d
637
+ run your program under the control of pdb, the Python debugger.
638
+ This allows you to execute your program step by step, watch variables,
639
+ etc. Internally, what IPython does is similar to calling::
640
+
641
+ pdb.run('execfile("YOURFILENAME")')
642
+
643
+ with a breakpoint set on line 1 of your file. You can change the line
644
+ number for this automatic breakpoint to be <N> by using the -bN option
645
+ (where N must be an integer). For example::
646
+
647
+ %run -d -b40 myscript
648
+
649
+ will set the first breakpoint at line 40 in myscript.py. Note that
650
+ the first breakpoint must be set on a line which actually does
651
+ something (not a comment or docstring) for it to stop execution.
652
+
653
+ Or you can specify a breakpoint in a different file::
654
+
655
+ %run -d -b myotherfile.py:20 myscript
656
+
657
+ When the pdb debugger starts, you will see a (Pdb) prompt. You must
658
+ first enter 'c' (without quotes) to start execution up to the first
659
+ breakpoint.
660
+
661
+ Entering 'help' gives information about the use of the debugger. You
662
+ can easily see pdb's full documentation with "import pdb;pdb.help()"
663
+ at a prompt.
664
+
665
+ -p
666
+ run program under the control of the Python profiler module (which
667
+ prints a detailed report of execution times, function calls, etc).
668
+
669
+ You can pass other options after -p which affect the behavior of the
670
+ profiler itself. See the docs for %prun for details.
671
+
672
+ In this mode, the program's variables do NOT propagate back to the
673
+ IPython interactive namespace (because they remain in the namespace
674
+ where the profiler executes them).
675
+
676
+ Internally this triggers a call to %prun, see its documentation for
677
+ details on the options available specifically for profiling.
678
+
679
+ There is one special usage for which the text above doesn't apply:
680
+ if the filename ends with .ipy[nb], the file is run as ipython script,
681
+ just as if the commands were written on IPython prompt.
682
+
683
+ -m
684
+ specify module name to load instead of script path. Similar to
685
+ the -m option for the python interpreter. Use this option last if you
686
+ want to combine with other %run options. Unlike the python interpreter
687
+ only source modules are allowed no .pyc or .pyo files.
688
+ For example::
689
+
690
+ %run -m example
691
+
692
+ will run the example module.
693
+
694
+ -G
695
+ disable shell-like glob expansion of arguments.
696
+
697
+ """
698
+
699
+ # Logic to handle issue #3664
700
+ # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
701
+ if '-m' in parameter_s and '--' not in parameter_s:
702
+ argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
703
+ for idx, arg in enumerate(argv):
704
+ if arg and arg.startswith('-') and arg != '-':
705
+ if arg == '-m':
706
+ argv.insert(idx + 2, '--')
707
+ break
708
+ else:
709
+ # Positional arg, break
710
+ break
711
+ parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
712
+
713
+ # get arguments and set sys.argv for program to be run.
714
+ opts, arg_lst = self.parse_options(parameter_s,
715
+ 'nidtN:b:pD:l:rs:T:em:G',
716
+ mode='list', list_all=1)
717
+ if "m" in opts:
718
+ modulename = opts["m"][0]
719
+ modpath = find_mod(modulename)
720
+ if modpath is None:
721
+ msg = '%r is not a valid modulename on sys.path'%modulename
722
+ raise Exception(msg)
723
+ arg_lst = [modpath] + arg_lst
724
+ try:
725
+ fpath = None # initialize to make sure fpath is in scope later
726
+ fpath = arg_lst[0]
727
+ filename = file_finder(fpath)
728
+ except IndexError as e:
729
+ msg = 'you must provide at least a filename.'
730
+ raise Exception(msg) from e
731
+ except IOError as e:
732
+ try:
733
+ msg = str(e)
734
+ except UnicodeError:
735
+ msg = e.message
736
+ if os.name == 'nt' and re.match(r"^'.*'$",fpath):
737
+ warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
738
+ raise Exception(msg) from e
739
+ except TypeError:
740
+ if fpath in sys.meta_path:
741
+ filename = ""
742
+ else:
743
+ raise
744
+
745
+ if filename.lower().endswith(('.ipy', '.ipynb')):
746
+ with preserve_keys(self.shell.user_ns, '__file__'):
747
+ self.shell.user_ns['__file__'] = filename
748
+ self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
749
+ return
750
+
751
+ # Control the response to exit() calls made by the script being run
752
+ exit_ignore = 'e' in opts
753
+
754
+ # Make sure that the running script gets a proper sys.argv as if it
755
+ # were run from a system shell.
756
+ save_argv = sys.argv # save it for later restoring
757
+
758
+ if 'G' in opts:
759
+ args = arg_lst[1:]
760
+ else:
761
+ # tilde and glob expansion
762
+ args = shellglob(map(os.path.expanduser, arg_lst[1:]))
763
+
764
+ sys.argv = [filename] + args # put in the proper filename
765
+
766
+ if 'n' in opts:
767
+ name = Path(filename).stem
768
+ else:
769
+ name = '__main__'
770
+
771
+ if 'i' in opts:
772
+ # Run in user's interactive namespace
773
+ prog_ns = self.shell.user_ns
774
+ __name__save = self.shell.user_ns['__name__']
775
+ prog_ns['__name__'] = name
776
+ main_mod = self.shell.user_module
777
+
778
+ # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
779
+ # set the __file__ global in the script's namespace
780
+ # TK: Is this necessary in interactive mode?
781
+ prog_ns['__file__'] = filename
782
+ else:
783
+ # Run in a fresh, empty namespace
784
+
785
+ # The shell MUST hold a reference to prog_ns so after %run
786
+ # exits, the python deletion mechanism doesn't zero it out
787
+ # (leaving dangling references). See interactiveshell for details
788
+ main_mod = self.shell.new_main_mod(filename, name)
789
+ prog_ns = main_mod.__dict__
790
+
791
+ # pickle fix. See interactiveshell for an explanation. But we need to
792
+ # make sure that, if we overwrite __main__, we replace it at the end
793
+ main_mod_name = prog_ns['__name__']
794
+
795
+ if main_mod_name == '__main__':
796
+ restore_main = sys.modules['__main__']
797
+ else:
798
+ restore_main = False
799
+
800
+ # This needs to be undone at the end to prevent holding references to
801
+ # every single object ever created.
802
+ sys.modules[main_mod_name] = main_mod
803
+
804
+ if 'p' in opts or 'd' in opts:
805
+ if 'm' in opts:
806
+ code = 'run_module(modulename, prog_ns)'
807
+ code_ns = {
808
+ 'run_module': self.shell.safe_run_module,
809
+ 'prog_ns': prog_ns,
810
+ 'modulename': modulename,
811
+ }
812
+ else:
813
+ if 'd' in opts:
814
+ # allow exceptions to raise in debug mode
815
+ code = 'execfile(filename, prog_ns, raise_exceptions=True)'
816
+ else:
817
+ code = 'execfile(filename, prog_ns)'
818
+ code_ns = {
819
+ 'execfile': self.shell.safe_execfile,
820
+ 'prog_ns': prog_ns,
821
+ 'filename': get_py_filename(filename),
822
+ }
823
+
824
+ try:
825
+ stats = None
826
+ if 'p' in opts:
827
+ stats = self._run_with_profiler(code, opts, code_ns)
828
+ else:
829
+ if 'd' in opts:
830
+ bp_file, bp_line = parse_breakpoint(
831
+ opts.get('b', ['1'])[0], filename)
832
+ self._run_with_debugger(
833
+ code, code_ns, filename, bp_line, bp_file)
834
+ else:
835
+ if 'm' in opts:
836
+ def run():
837
+ self.shell.safe_run_module(modulename, prog_ns)
838
+ else:
839
+ if runner is None:
840
+ runner = self.default_runner
841
+ if runner is None:
842
+ runner = self.shell.safe_execfile
843
+
844
+ def run():
845
+ runner(filename, prog_ns, prog_ns,
846
+ exit_ignore=exit_ignore)
847
+
848
+ if 't' in opts:
849
+ # timed execution
850
+ try:
851
+ nruns = int(opts['N'][0])
852
+ if nruns < 1:
853
+ error('Number of runs must be >=1')
854
+ return
855
+ except (KeyError):
856
+ nruns = 1
857
+ self._run_with_timing(run, nruns)
858
+ else:
859
+ # regular execution
860
+ run()
861
+
862
+ if 'i' in opts:
863
+ self.shell.user_ns['__name__'] = __name__save
864
+ else:
865
+ # update IPython interactive namespace
866
+
867
+ # Some forms of read errors on the file may mean the
868
+ # __name__ key was never set; using pop we don't have to
869
+ # worry about a possible KeyError.
870
+ prog_ns.pop('__name__', None)
871
+
872
+ with preserve_keys(self.shell.user_ns, '__file__'):
873
+ self.shell.user_ns.update(prog_ns)
874
+ finally:
875
+ # It's a bit of a mystery why, but __builtins__ can change from
876
+ # being a module to becoming a dict missing some key data after
877
+ # %run. As best I can see, this is NOT something IPython is doing
878
+ # at all, and similar problems have been reported before:
879
+ # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
880
+ # Since this seems to be done by the interpreter itself, the best
881
+ # we can do is to at least restore __builtins__ for the user on
882
+ # exit.
883
+ self.shell.user_ns['__builtins__'] = builtin_mod
884
+
885
+ # Ensure key global structures are restored
886
+ sys.argv = save_argv
887
+ if restore_main:
888
+ sys.modules['__main__'] = restore_main
889
+ if '__mp_main__' in sys.modules:
890
+ sys.modules['__mp_main__'] = restore_main
891
+ else:
892
+ # Remove from sys.modules the reference to main_mod we'd
893
+ # added. Otherwise it will trap references to objects
894
+ # contained therein.
895
+ del sys.modules[main_mod_name]
896
+
897
+ return stats
898
+
899
+ def _run_with_debugger(
900
+ self, code, code_ns, filename=None, bp_line=None, bp_file=None, local_ns=None
901
+ ):
902
+ """
903
+ Run `code` in debugger with a break point.
904
+
905
+ Parameters
906
+ ----------
907
+ code : str
908
+ Code to execute.
909
+ code_ns : dict
910
+ A namespace in which `code` is executed.
911
+ filename : str
912
+ `code` is ran as if it is in `filename`.
913
+ bp_line : int, optional
914
+ Line number of the break point.
915
+ bp_file : str, optional
916
+ Path to the file in which break point is specified.
917
+ `filename` is used if not given.
918
+ local_ns : dict, optional
919
+ A local namespace in which `code` is executed.
920
+
921
+ Raises
922
+ ------
923
+ UsageError
924
+ If the break point given by `bp_line` is not valid.
925
+
926
+ """
927
+ deb = self.shell.InteractiveTB.pdb
928
+ if not deb:
929
+ self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
930
+ deb = self.shell.InteractiveTB.pdb
931
+
932
+ # deb.checkline() fails if deb.curframe exists but is None; it can
933
+ # handle it not existing. https://github.com/ipython/ipython/issues/10028
934
+ if hasattr(deb, 'curframe'):
935
+ del deb.curframe
936
+
937
+ # reset Breakpoint state, which is moronically kept
938
+ # in a class
939
+ bdb.Breakpoint.next = 1
940
+ bdb.Breakpoint.bplist = {}
941
+ bdb.Breakpoint.bpbynumber = [None]
942
+ deb.clear_all_breaks()
943
+ if bp_line is not None:
944
+ # Set an initial breakpoint to stop execution
945
+ maxtries = 10
946
+ bp_file = bp_file or filename
947
+ checkline = deb.checkline(bp_file, bp_line)
948
+ if not checkline:
949
+ for bp in range(bp_line + 1, bp_line + maxtries + 1):
950
+ if deb.checkline(bp_file, bp):
951
+ break
952
+ else:
953
+ msg = ("\nI failed to find a valid line to set "
954
+ "a breakpoint\n"
955
+ "after trying up to line: %s.\n"
956
+ "Please set a valid breakpoint manually "
957
+ "with the -b option." % bp)
958
+ raise UsageError(msg)
959
+ # if we find a good linenumber, set the breakpoint
960
+ deb.do_break('%s:%s' % (bp_file, bp_line))
961
+
962
+ if filename:
963
+ # Mimic Pdb._runscript(...)
964
+ deb._wait_for_mainpyfile = True
965
+ deb.mainpyfile = deb.canonic(filename)
966
+
967
+ # Start file run
968
+ print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
969
+ try:
970
+ if filename:
971
+ # save filename so it can be used by methods on the deb object
972
+ deb._exec_filename = filename
973
+ while True:
974
+ try:
975
+ trace = sys.gettrace()
976
+ deb.run(code, code_ns, local_ns)
977
+ except Restart:
978
+ print("Restarting")
979
+ if filename:
980
+ deb._wait_for_mainpyfile = True
981
+ deb.mainpyfile = deb.canonic(filename)
982
+ continue
983
+ else:
984
+ break
985
+ finally:
986
+ sys.settrace(trace)
987
+
988
+ # Perform proper cleanup of the session in case if
989
+ # it exited with "continue" and not "quit" command
990
+ if hasattr(deb, "rcLines"):
991
+ # Run this code defensively in case if custom debugger
992
+ # class does not implement rcLines, which although public
993
+ # is an implementation detail of `pdb.Pdb` and not part of
994
+ # the more generic basic debugger framework (`bdb.Bdb`).
995
+ deb.set_quit()
996
+ deb.rcLines.extend(["q"])
997
+ try:
998
+ deb.run("", code_ns, local_ns)
999
+ except StopIteration:
1000
+ # Stop iteration is raised on quit command
1001
+ pass
1002
+
1003
+ except Exception:
1004
+ etype, value, tb = sys.exc_info()
1005
+ # Skip three frames in the traceback: the %run one,
1006
+ # one inside bdb.py, and the command-line typed by the
1007
+ # user (run by exec in pdb itself).
1008
+ self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
1009
+
1010
+ @staticmethod
1011
+ def _run_with_timing(run, nruns):
1012
+ """
1013
+ Run function `run` and print timing information.
1014
+
1015
+ Parameters
1016
+ ----------
1017
+ run : callable
1018
+ Any callable object which takes no argument.
1019
+ nruns : int
1020
+ Number of times to execute `run`.
1021
+
1022
+ """
1023
+ twall0 = time.perf_counter()
1024
+ if nruns == 1:
1025
+ t0 = clock2()
1026
+ run()
1027
+ t1 = clock2()
1028
+ t_usr = t1[0] - t0[0]
1029
+ t_sys = t1[1] - t0[1]
1030
+ print("\nIPython CPU timings (estimated):")
1031
+ print(" User : %10.2f s." % t_usr)
1032
+ print(" System : %10.2f s." % t_sys)
1033
+ else:
1034
+ runs = range(nruns)
1035
+ t0 = clock2()
1036
+ for nr in runs:
1037
+ run()
1038
+ t1 = clock2()
1039
+ t_usr = t1[0] - t0[0]
1040
+ t_sys = t1[1] - t0[1]
1041
+ print("\nIPython CPU timings (estimated):")
1042
+ print("Total runs performed:", nruns)
1043
+ print(" Times : %10s %10s" % ('Total', 'Per run'))
1044
+ print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
1045
+ print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
1046
+ twall1 = time.perf_counter()
1047
+ print("Wall time: %10.2f s." % (twall1 - twall0))
1048
+
1049
+ @skip_doctest
1050
+ @no_var_expand
1051
+ @line_cell_magic
1052
+ @needs_local_scope
1053
+ def timeit(self, line='', cell=None, local_ns=None):
1054
+ """Time execution of a Python statement or expression
1055
+
1056
+ **Usage, in line mode**::
1057
+
1058
+ %timeit [-n<N> -r<R> [-t|-c] -q -p<P> [-o|-v <V>]] statement
1059
+
1060
+ **or in cell mode**::
1061
+
1062
+ %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> [-o|-v <V>]] setup_code
1063
+ code
1064
+ code...
1065
+
1066
+ Time execution of a Python statement or expression using the timeit
1067
+ module. This function can be used both as a line and cell magic:
1068
+
1069
+ - In line mode you can time a single-line statement (though multiple
1070
+ ones can be chained with using semicolons).
1071
+
1072
+ - In cell mode, the statement in the first line is used as setup code
1073
+ (executed but not timed) and the body of the cell is timed. The cell
1074
+ body has access to any variables created in the setup code.
1075
+
1076
+ Options:
1077
+
1078
+ -n<N>
1079
+ Execute the given statement N times in a loop. If N is not
1080
+ provided, N is determined so as to get sufficient accuracy.
1081
+
1082
+ -r<R>
1083
+ Number of repeats R, each consisting of N loops, and take the
1084
+ average result.
1085
+ Default: 7
1086
+
1087
+ -t
1088
+ Use ``time.time`` to measure the time, which is the default on Unix.
1089
+ This function measures wall time.
1090
+
1091
+ -c
1092
+ Use ``time.clock`` to measure the time, which is the default on
1093
+ Windows and measures wall time. On Unix, ``resource.getrusage`` is used
1094
+ instead and returns the CPU user time.
1095
+
1096
+ -p<P>
1097
+ Use a precision of P digits to display the timing result.
1098
+ Default: 3
1099
+
1100
+ -q
1101
+ Quiet, do not print result.
1102
+
1103
+ -o
1104
+ Return a ``TimeitResult`` that can be stored in a variable to inspect
1105
+ the result in more details.
1106
+
1107
+ -v <V>
1108
+ Like ``-o``, but save the ``TimeitResult`` directly to variable <V>.
1109
+
1110
+ .. versionchanged:: 7.3
1111
+ User variables are no longer expanded,
1112
+ the magic line is always left unmodified.
1113
+
1114
+ Examples
1115
+ --------
1116
+ ::
1117
+
1118
+ In [1]: %timeit pass
1119
+ 8.26 ns ± 0.12 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
1120
+
1121
+ In [2]: u = None
1122
+
1123
+ In [3]: %timeit u is None
1124
+ 29.9 ns ± 0.643 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
1125
+
1126
+ In [4]: %timeit -r 4 u == None
1127
+
1128
+ In [5]: import time
1129
+
1130
+ In [6]: %timeit -n1 time.sleep(2)
1131
+
1132
+ The times reported by ``%timeit`` will be slightly higher than those
1133
+ reported by the timeit.py script when variables are accessed. This is
1134
+ due to the fact that ``%timeit`` executes the statement in the namespace
1135
+ of the shell, compared with timeit.py, which uses a single setup
1136
+ statement to import function or create variables. Generally, the bias
1137
+ does not matter as long as results from timeit.py are not mixed with
1138
+ those from ``%timeit``."""
1139
+
1140
+ opts, stmt = self.parse_options(
1141
+ line, "n:r:tcp:qov:", posix=False, strict=False, preserve_non_opts=True
1142
+ )
1143
+ if stmt == "" and cell is None:
1144
+ return
1145
+
1146
+ timefunc = timeit.default_timer
1147
+ number = int(getattr(opts, "n", 0))
1148
+ default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1149
+ repeat = int(getattr(opts, "r", default_repeat))
1150
+ precision = int(getattr(opts, "p", 3))
1151
+ quiet = "q" in opts
1152
+ return_result = "o" in opts
1153
+ save_result = "v" in opts
1154
+ if hasattr(opts, "t"):
1155
+ timefunc = time.time
1156
+ if hasattr(opts, "c"):
1157
+ timefunc = clock
1158
+
1159
+ timer = Timer(timer=timefunc)
1160
+ # this code has tight coupling to the inner workings of timeit.Timer,
1161
+ # but is there a better way to achieve that the code stmt has access
1162
+ # to the shell namespace?
1163
+ transform = self.shell.transform_cell
1164
+
1165
+ if cell is None:
1166
+ # called as line magic
1167
+ ast_setup = self.shell.compile.ast_parse("pass")
1168
+ ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1169
+ else:
1170
+ ast_setup = self.shell.compile.ast_parse(transform(stmt))
1171
+ ast_stmt = self.shell.compile.ast_parse(transform(cell))
1172
+
1173
+ ast_setup = self.shell.transform_ast(ast_setup)
1174
+ ast_stmt = self.shell.transform_ast(ast_stmt)
1175
+
1176
+ # Check that these compile to valid Python code *outside* the timer func
1177
+ # Invalid code may become valid when put inside the function & loop,
1178
+ # which messes up error messages.
1179
+ # https://github.com/ipython/ipython/issues/10636
1180
+ self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1181
+ self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1182
+
1183
+ # This codestring is taken from timeit.template - we fill it in as an
1184
+ # AST, so that we can apply our AST transformations to the user code
1185
+ # without affecting the timing code.
1186
+ timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1187
+ ' setup\n'
1188
+ ' _t0 = _timer()\n'
1189
+ ' for _i in _it:\n'
1190
+ ' stmt\n'
1191
+ ' _t1 = _timer()\n'
1192
+ ' return _t1 - _t0\n')
1193
+
1194
+ timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1195
+ timeit_ast = ast.fix_missing_locations(timeit_ast)
1196
+
1197
+ # Track compilation time so it can be reported if too long
1198
+ # Minimum time above which compilation time will be reported
1199
+ tc_min = 0.1
1200
+
1201
+ t0 = clock()
1202
+ code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1203
+ tc = clock()-t0
1204
+
1205
+ ns = {}
1206
+ glob = self.shell.user_ns
1207
+ # handles global vars with same name as local vars. We store them in conflict_globs.
1208
+ conflict_globs = {}
1209
+ if local_ns and cell is None:
1210
+ for var_name, var_val in glob.items():
1211
+ if var_name in local_ns:
1212
+ conflict_globs[var_name] = var_val
1213
+ glob.update(local_ns)
1214
+
1215
+ exec(code, glob, ns)
1216
+ timer.inner = ns["inner"]
1217
+
1218
+ # This is used to check if there is a huge difference between the
1219
+ # best and worst timings.
1220
+ # Issue: https://github.com/ipython/ipython/issues/6471
1221
+ if number == 0:
1222
+ # determine number so that 0.2 <= total time < 2.0
1223
+ for index in range(0, 10):
1224
+ number = 10 ** index
1225
+ time_number = timer.timeit(number)
1226
+ if time_number >= 0.2:
1227
+ break
1228
+
1229
+ all_runs = timer.repeat(repeat, number)
1230
+ best = min(all_runs) / number
1231
+ worst = max(all_runs) / number
1232
+ timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1233
+
1234
+ # Restore global vars from conflict_globs
1235
+ if conflict_globs:
1236
+ glob.update(conflict_globs)
1237
+
1238
+ if not quiet:
1239
+ # Check best timing is greater than zero to avoid a
1240
+ # ZeroDivisionError.
1241
+ # In cases where the slowest timing is lesser than a microsecond
1242
+ # we assume that it does not really matter if the fastest
1243
+ # timing is 4 times faster than the slowest timing or not.
1244
+ if worst > 4 * best and best > 0 and worst > 1e-6:
1245
+ print("The slowest run took %0.2f times longer than the "
1246
+ "fastest. This could mean that an intermediate result "
1247
+ "is being cached." % (worst / best))
1248
+
1249
+ print( timeit_result )
1250
+
1251
+ if tc > tc_min:
1252
+ print("Compiler time: %.2f s" % tc)
1253
+
1254
+ if save_result:
1255
+ self.shell.user_ns[opts.v] = timeit_result
1256
+
1257
+ if return_result:
1258
+ return timeit_result
1259
+
1260
+ @skip_doctest
1261
+ @no_var_expand
1262
+ @needs_local_scope
1263
+ @line_cell_magic
1264
+ @output_can_be_silenced
1265
+ def time(self, line="", cell=None, local_ns=None):
1266
+ """Time execution of a Python statement or expression.
1267
+
1268
+ The CPU and wall clock times are printed, and the value of the
1269
+ expression (if any) is returned. Note that under Win32, system time
1270
+ is always reported as 0, since it can not be measured.
1271
+
1272
+ This function can be used both as a line and cell magic:
1273
+
1274
+ - In line mode you can time a single-line statement (though multiple
1275
+ ones can be chained with using semicolons).
1276
+
1277
+ - In cell mode, you can time the cell body (a directly
1278
+ following statement raises an error).
1279
+
1280
+ This function provides very basic timing functionality. Use the timeit
1281
+ magic for more control over the measurement.
1282
+
1283
+ .. versionchanged:: 7.3
1284
+ User variables are no longer expanded,
1285
+ the magic line is always left unmodified.
1286
+
1287
+ .. versionchanged:: 8.3
1288
+ The time magic now correctly propagates system-exiting exceptions
1289
+ (such as ``KeyboardInterrupt`` invoked when interrupting execution)
1290
+ rather than just printing out the exception traceback.
1291
+ The non-system-exception will still be caught as before.
1292
+
1293
+ Examples
1294
+ --------
1295
+ ::
1296
+
1297
+ In [1]: %time 2**128
1298
+ CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1299
+ Wall time: 0.00
1300
+ Out[1]: 340282366920938463463374607431768211456L
1301
+
1302
+ In [2]: n = 1000000
1303
+
1304
+ In [3]: %time sum(range(n))
1305
+ CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1306
+ Wall time: 1.37
1307
+ Out[3]: 499999500000L
1308
+
1309
+ In [4]: %time print('hello world')
1310
+ hello world
1311
+ CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1312
+ Wall time: 0.00
1313
+
1314
+ .. note::
1315
+ The time needed by Python to compile the given expression will be
1316
+ reported if it is more than 0.1s.
1317
+
1318
+ In the example below, the actual exponentiation is done by Python
1319
+ at compilation time, so while the expression can take a noticeable
1320
+ amount of time to compute, that time is purely due to the
1321
+ compilation::
1322
+
1323
+ In [5]: %time 3**9999;
1324
+ CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1325
+ Wall time: 0.00 s
1326
+
1327
+ In [6]: %time 3**999999;
1328
+ CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1329
+ Wall time: 0.00 s
1330
+ Compiler : 0.78 s
1331
+ """
1332
+ # fail immediately if the given expression can't be compiled
1333
+
1334
+ if line and cell:
1335
+ raise UsageError("Can't use statement directly after '%%time'!")
1336
+
1337
+ if cell:
1338
+ expr = self.shell.transform_cell(cell)
1339
+ else:
1340
+ expr = self.shell.transform_cell(line)
1341
+
1342
+ # Minimum time above which parse time will be reported
1343
+ tp_min = 0.1
1344
+
1345
+ t0 = clock()
1346
+ expr_ast = self.shell.compile.ast_parse(expr)
1347
+ tp = clock() - t0
1348
+
1349
+ # Apply AST transformations
1350
+ expr_ast = self.shell.transform_ast(expr_ast)
1351
+
1352
+ # Minimum time above which compilation time will be reported
1353
+ tc_min = 0.1
1354
+
1355
+ expr_val = None
1356
+ if len(expr_ast.body) == 1 and isinstance(expr_ast.body[0], ast.Expr):
1357
+ mode = 'eval'
1358
+ source = '<timed eval>'
1359
+ expr_ast = ast.Expression(expr_ast.body[0].value)
1360
+ else:
1361
+ mode = 'exec'
1362
+ source = '<timed exec>'
1363
+ # multi-line %%time case
1364
+ if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1365
+ expr_val = expr_ast.body[-1]
1366
+ expr_ast = expr_ast.body[:-1]
1367
+ expr_ast = Module(expr_ast, [])
1368
+ expr_val = ast.Expression(expr_val.value)
1369
+
1370
+ t0 = clock()
1371
+ code = self.shell.compile(expr_ast, source, mode)
1372
+ tc = clock() - t0
1373
+
1374
+ # skew measurement as little as possible
1375
+ glob = self.shell.user_ns
1376
+ wtime = time.time
1377
+ # time execution
1378
+ wall_st = wtime()
1379
+ if mode == "eval":
1380
+ st = clock2()
1381
+ try:
1382
+ out = eval(code, glob, local_ns)
1383
+ except Exception:
1384
+ self.shell.showtraceback()
1385
+ return
1386
+ end = clock2()
1387
+ else:
1388
+ st = clock2()
1389
+ try:
1390
+ exec(code, glob, local_ns)
1391
+ out = None
1392
+ # multi-line %%time case
1393
+ if expr_val is not None:
1394
+ code_2 = self.shell.compile(expr_val, source, 'eval')
1395
+ out = eval(code_2, glob, local_ns)
1396
+ except Exception:
1397
+ self.shell.showtraceback()
1398
+ return
1399
+ end = clock2()
1400
+
1401
+ wall_end = wtime()
1402
+ # Compute actual times and report
1403
+ wall_time = wall_end - wall_st
1404
+ cpu_user = end[0] - st[0]
1405
+ cpu_sys = end[1] - st[1]
1406
+ cpu_tot = cpu_user + cpu_sys
1407
+ # On windows cpu_sys is always zero, so only total is displayed
1408
+ if sys.platform != "win32":
1409
+ print(
1410
+ f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1411
+ )
1412
+ else:
1413
+ print(f"CPU times: total: {_format_time(cpu_tot)}")
1414
+ print(f"Wall time: {_format_time(wall_time)}")
1415
+ if tc > tc_min:
1416
+ print(f"Compiler : {_format_time(tc)}")
1417
+ if tp > tp_min:
1418
+ print(f"Parser : {_format_time(tp)}")
1419
+ return out
1420
+
1421
+ @skip_doctest
1422
+ @line_magic
1423
+ def macro(self, parameter_s=''):
1424
+ """Define a macro for future re-execution. It accepts ranges of history,
1425
+ filenames or string objects.
1426
+
1427
+ Usage::
1428
+
1429
+ %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1430
+
1431
+ Options:
1432
+
1433
+ -r
1434
+ Use 'raw' input. By default, the 'processed' history is used,
1435
+ so that magics are loaded in their transformed version to valid
1436
+ Python. If this option is given, the raw input as typed at the
1437
+ command line is used instead.
1438
+
1439
+ -q
1440
+ Quiet macro definition. By default, a tag line is printed
1441
+ to indicate the macro has been created, and then the contents of
1442
+ the macro are printed. If this option is given, then no printout
1443
+ is produced once the macro is created.
1444
+
1445
+ This will define a global variable called `name` which is a string
1446
+ made of joining the slices and lines you specify (n1,n2,... numbers
1447
+ above) from your input history into a single string. This variable
1448
+ acts like an automatic function which re-executes those lines as if
1449
+ you had typed them. You just type 'name' at the prompt and the code
1450
+ executes.
1451
+
1452
+ The syntax for indicating input ranges is described in %history.
1453
+
1454
+ Note: as a 'hidden' feature, you can also use traditional python slice
1455
+ notation, where N:M means numbers N through M-1.
1456
+
1457
+ For example, if your history contains (print using %hist -n )::
1458
+
1459
+ 44: x=1
1460
+ 45: y=3
1461
+ 46: z=x+y
1462
+ 47: print(x)
1463
+ 48: a=5
1464
+ 49: print('x',x,'y',y)
1465
+
1466
+ you can create a macro with lines 44 through 47 (included) and line 49
1467
+ called my_macro with::
1468
+
1469
+ In [55]: %macro my_macro 44-47 49
1470
+
1471
+ Now, typing `my_macro` (without quotes) will re-execute all this code
1472
+ in one pass.
1473
+
1474
+ You don't need to give the line-numbers in order, and any given line
1475
+ number can appear multiple times. You can assemble macros with any
1476
+ lines from your input history in any order.
1477
+
1478
+ The macro is a simple object which holds its value in an attribute,
1479
+ but IPython's display system checks for macros and executes them as
1480
+ code instead of printing them when you type their name.
1481
+
1482
+ You can view a macro's contents by explicitly printing it with::
1483
+
1484
+ print(macro_name)
1485
+
1486
+ """
1487
+ opts,args = self.parse_options(parameter_s,'rq',mode='list')
1488
+ if not args: # List existing macros
1489
+ return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1490
+ if len(args) == 1:
1491
+ raise UsageError(
1492
+ "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1493
+ name, codefrom = args[0], " ".join(args[1:])
1494
+
1495
+ # print('rng',ranges) # dbg
1496
+ try:
1497
+ lines = self.shell.find_user_code(codefrom, 'r' in opts)
1498
+ except (ValueError, TypeError) as e:
1499
+ print(e.args[0])
1500
+ return
1501
+ macro = Macro(lines)
1502
+ self.shell.define_macro(name, macro)
1503
+ if "q" not in opts:
1504
+ print(
1505
+ "Macro `%s` created. To execute, type its name (without quotes)." % name
1506
+ )
1507
+ print("=== Macro contents: ===")
1508
+ print(macro, end=" ")
1509
+
1510
+ @magic_arguments.magic_arguments()
1511
+ @magic_arguments.argument(
1512
+ "output",
1513
+ type=str,
1514
+ default="",
1515
+ nargs="?",
1516
+ help="""
1517
+
1518
+ The name of the variable in which to store output.
1519
+ This is a ``utils.io.CapturedIO`` object with stdout/err attributes
1520
+ for the text of the captured output.
1521
+
1522
+ CapturedOutput also has a ``show()`` method for displaying the output,
1523
+ and ``__call__`` as well, so you can use that to quickly display the
1524
+ output.
1525
+
1526
+ If unspecified, captured output is discarded.
1527
+ """,
1528
+ )
1529
+ @magic_arguments.argument(
1530
+ "--no-stderr", action="store_true", help="""Don't capture stderr."""
1531
+ )
1532
+ @magic_arguments.argument(
1533
+ "--no-stdout", action="store_true", help="""Don't capture stdout."""
1534
+ )
1535
+ @magic_arguments.argument(
1536
+ "--no-display",
1537
+ action="store_true",
1538
+ help="""Don't capture IPython's rich display."""
1539
+ )
1540
+ @cell_magic
1541
+ def capture(self, line, cell):
1542
+ """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1543
+ args = magic_arguments.parse_argstring(self.capture, line)
1544
+ out = not args.no_stdout
1545
+ err = not args.no_stderr
1546
+ disp = not args.no_display
1547
+ with capture_output(out, err, disp) as io:
1548
+ self.shell.run_cell(cell)
1549
+ if DisplayHook.semicolon_at_end_of_expression(cell):
1550
+ if args.output in self.shell.user_ns:
1551
+ del self.shell.user_ns[args.output]
1552
+ elif args.output:
1553
+ self.shell.user_ns[args.output] = io
1554
+
1555
+ @skip_doctest
1556
+ @magic_arguments.magic_arguments()
1557
+ @magic_arguments.argument("name", type=str, default="default", nargs="?")
1558
+ @magic_arguments.argument(
1559
+ "--remove", action="store_true", help="remove the current transformer"
1560
+ )
1561
+ @magic_arguments.argument(
1562
+ "--list", action="store_true", help="list existing transformers name"
1563
+ )
1564
+ @magic_arguments.argument(
1565
+ "--list-all",
1566
+ action="store_true",
1567
+ help="list existing transformers name and code template",
1568
+ )
1569
+ @line_cell_magic
1570
+ def code_wrap(self, line, cell=None):
1571
+ """
1572
+ Simple magic to quickly define a code transformer for all IPython's future input.
1573
+
1574
+ ``__code__`` and ``__ret__`` are special variable that represent the code to run
1575
+ and the value of the last expression of ``__code__`` respectively.
1576
+
1577
+ Examples
1578
+ --------
1579
+
1580
+ .. ipython::
1581
+
1582
+ In [1]: %%code_wrap before_after
1583
+ ...: print('before')
1584
+ ...: __code__
1585
+ ...: print('after')
1586
+ ...: __ret__
1587
+
1588
+
1589
+ In [2]: 1
1590
+ before
1591
+ after
1592
+ Out[2]: 1
1593
+
1594
+ In [3]: %code_wrap --list
1595
+ before_after
1596
+
1597
+ In [4]: %code_wrap --list-all
1598
+ before_after :
1599
+ print('before')
1600
+ __code__
1601
+ print('after')
1602
+ __ret__
1603
+
1604
+ In [5]: %code_wrap --remove before_after
1605
+
1606
+ """
1607
+ args = magic_arguments.parse_argstring(self.code_wrap, line)
1608
+
1609
+ if args.list:
1610
+ for name in self._transformers.keys():
1611
+ print(name)
1612
+ return
1613
+ if args.list_all:
1614
+ for name, _t in self._transformers.items():
1615
+ print(name, ":")
1616
+ print(indent(ast.unparse(_t.template), " "))
1617
+ print()
1618
+ return
1619
+
1620
+ to_remove = self._transformers.pop(args.name, None)
1621
+ if to_remove in self.shell.ast_transformers:
1622
+ self.shell.ast_transformers.remove(to_remove)
1623
+ if cell is None or args.remove:
1624
+ return
1625
+
1626
+ _trs = ReplaceCodeTransformer(ast.parse(cell))
1627
+
1628
+ self._transformers[args.name] = _trs
1629
+ self.shell.ast_transformers.append(_trs)
1630
+
1631
+
1632
+ def parse_breakpoint(text, current_file):
1633
+ '''Returns (file, line) for file:line and (current_file, line) for line'''
1634
+ colon = text.find(':')
1635
+ if colon == -1:
1636
+ return current_file, int(text)
1637
+ else:
1638
+ return text[:colon], int(text[colon+1:])
1639
+
1640
+
1641
+ def _format_time(timespan, precision=3):
1642
+ """Formats the timespan in a human readable form"""
1643
+
1644
+ if timespan >= 60.0:
1645
+ # we have more than a minute, format that in a human readable form
1646
+ # Idea from http://snipplr.com/view/5713/
1647
+ parts = [("d", 60 * 60 * 24), ("h", 60 * 60), ("min", 60), ("s", 1)]
1648
+ time = []
1649
+ leftover = timespan
1650
+ for suffix, length in parts:
1651
+ value = int(leftover / length)
1652
+ if value > 0:
1653
+ leftover = leftover % length
1654
+ time.append("%s%s" % (str(value), suffix))
1655
+ if leftover < 1:
1656
+ break
1657
+ return " ".join(time)
1658
+
1659
+ # Unfortunately characters outside of range(128) can cause problems in
1660
+ # certain terminals.
1661
+ # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1662
+ # Try to prevent crashes by being more secure than it needs to
1663
+ # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1664
+ units = ["s", "ms", "us", "ns"] # the safe value
1665
+ if hasattr(sys.stdout, "encoding") and sys.stdout.encoding:
1666
+ try:
1667
+ "μ".encode(sys.stdout.encoding)
1668
+ units = ["s", "ms", "μs", "ns"]
1669
+ except:
1670
+ pass
1671
+ scaling = [1, 1e3, 1e6, 1e9]
1672
+
1673
+ if timespan > 0.0:
1674
+ order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1675
+ else:
1676
+ order = 3
1677
+ return "%.*g %s" % (precision, timespan * scaling[order], units[order])
temp_venv/lib/python3.13/site-packages/IPython/core/magics/extension.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions for the extension machinery.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+
16
+ # Our own packages
17
+ from IPython.core.error import UsageError
18
+ from IPython.core.magic import Magics, magics_class, line_magic
19
+
20
+ #-----------------------------------------------------------------------------
21
+ # Magic implementation classes
22
+ #-----------------------------------------------------------------------------
23
+
24
+ @magics_class
25
+ class ExtensionMagics(Magics):
26
+ """Magics to manage the IPython extensions system."""
27
+
28
+ @line_magic
29
+ def load_ext(self, module_str):
30
+ """Load an IPython extension by its module name."""
31
+ if not module_str:
32
+ raise UsageError('Missing module name.')
33
+ res = self.shell.extension_manager.load_extension(module_str)
34
+
35
+ if res == 'already loaded':
36
+ print("The %s extension is already loaded. To reload it, use:" % module_str)
37
+ print(" %reload_ext", module_str)
38
+ elif res == 'no load function':
39
+ print("The %s module is not an IPython extension." % module_str)
40
+
41
+ @line_magic
42
+ def unload_ext(self, module_str):
43
+ """Unload an IPython extension by its module name.
44
+
45
+ Not all extensions can be unloaded, only those which define an
46
+ ``unload_ipython_extension`` function.
47
+ """
48
+ if not module_str:
49
+ raise UsageError('Missing module name.')
50
+
51
+ res = self.shell.extension_manager.unload_extension(module_str)
52
+
53
+ if res == 'no unload function':
54
+ print("The %s extension doesn't define how to unload it." % module_str)
55
+ elif res == "not loaded":
56
+ print("The %s extension is not loaded." % module_str)
57
+
58
+ @line_magic
59
+ def reload_ext(self, module_str):
60
+ """Reload an IPython extension by its module name."""
61
+ if not module_str:
62
+ raise UsageError('Missing module name.')
63
+ self.shell.extension_manager.reload_extension(module_str)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/history.py ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions related to History.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012, IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Stdlib
16
+ import os
17
+ import sys
18
+ from io import open as io_open
19
+ import fnmatch
20
+
21
+ # Our own packages
22
+ from IPython.core.error import StdinNotImplementedError
23
+ from IPython.core.magic import Magics, magics_class, line_magic
24
+ from IPython.core.magic_arguments import (argument, magic_arguments,
25
+ parse_argstring)
26
+ from IPython.testing.skipdoctest import skip_doctest
27
+ from IPython.utils import io
28
+
29
+ #-----------------------------------------------------------------------------
30
+ # Magics class implementation
31
+ #-----------------------------------------------------------------------------
32
+
33
+
34
+ _unspecified = object()
35
+
36
+
37
+ @magics_class
38
+ class HistoryMagics(Magics):
39
+
40
+ @magic_arguments()
41
+ @argument(
42
+ '-n', dest='print_nums', action='store_true', default=False,
43
+ help="""
44
+ print line numbers for each input.
45
+ This feature is only available if numbered prompts are in use.
46
+ """)
47
+ @argument(
48
+ '-o', dest='get_output', action='store_true', default=False,
49
+ help="also print outputs for each input.")
50
+ @argument(
51
+ '-p', dest='pyprompts', action='store_true', default=False,
52
+ help="""
53
+ print classic '>>>' python prompts before each input.
54
+ This is useful for making documentation, and in conjunction
55
+ with -o, for producing doctest-ready output.
56
+ """)
57
+ @argument(
58
+ '-t', dest='raw', action='store_false', default=True,
59
+ help="""
60
+ print the 'translated' history, as IPython understands it.
61
+ IPython filters your input and converts it all into valid Python
62
+ source before executing it (things like magics or aliases are turned
63
+ into function calls, for example). With this option, you'll see the
64
+ native history instead of the user-entered version: '%%cd /' will be
65
+ seen as 'get_ipython().run_line_magic("cd", "/")' instead of '%%cd /'.
66
+ """)
67
+ @argument(
68
+ '-f', dest='filename',
69
+ help="""
70
+ FILENAME: instead of printing the output to the screen, redirect
71
+ it to the given file. The file is always overwritten, though *when
72
+ it can*, IPython asks for confirmation first. In particular, running
73
+ the command 'history -f FILENAME' from the IPython Notebook
74
+ interface will replace FILENAME even if it already exists *without*
75
+ confirmation.
76
+ """)
77
+ @argument(
78
+ '-g', dest='pattern', nargs='*', default=None,
79
+ help="""
80
+ treat the arg as a glob pattern to search for in (full) history.
81
+ This includes the saved history (almost all commands ever written).
82
+ The pattern may contain '?' to match one unknown character and '*'
83
+ to match any number of unknown characters. Use '%%hist -g' to show
84
+ full saved history (may be very long).
85
+ """)
86
+ @argument(
87
+ '-l', dest='limit', type=int, nargs='?', default=_unspecified,
88
+ help="""
89
+ get the last n lines from all sessions. Specify n as a single
90
+ arg, or the default is the last 10 lines.
91
+ """)
92
+ @argument(
93
+ '-u', dest='unique', action='store_true',
94
+ help="""
95
+ when searching history using `-g`, show only unique history.
96
+ """)
97
+ @argument('range', nargs='*')
98
+ @skip_doctest
99
+ @line_magic
100
+ def history(self, parameter_s = ''):
101
+ """Print input history (_i<n> variables), with most recent last.
102
+
103
+ By default, input history is printed without line numbers so it can be
104
+ directly pasted into an editor. Use -n to show them.
105
+
106
+ By default, all input history from the current session is displayed.
107
+ Ranges of history can be indicated using the syntax:
108
+
109
+ ``4``
110
+ Line 4, current session
111
+ ``4-6``
112
+ Lines 4-6, current session
113
+ ``243/1-5``
114
+ Lines 1-5, session 243
115
+ ``~2/7``
116
+ Line 7, session 2 before current
117
+ ``~8/1-~6/5``
118
+ From the first line of 8 sessions ago, to the fifth line of 6
119
+ sessions ago.
120
+
121
+ Multiple ranges can be entered, separated by spaces
122
+
123
+ The same syntax is used by %macro, %save, %edit, %rerun
124
+
125
+ Examples
126
+ --------
127
+ ::
128
+
129
+ In [6]: %history -n 4-6
130
+ 4:a = 12
131
+ 5:print(a**2)
132
+ 6:%history -n 4-6
133
+
134
+ """
135
+
136
+ args = parse_argstring(self.history, parameter_s)
137
+
138
+ # For brevity
139
+ history_manager = self.shell.history_manager
140
+
141
+ def _format_lineno(session, line):
142
+ """Helper function to format line numbers properly."""
143
+ if session in (0, history_manager.session_number):
144
+ return str(line)
145
+ return "%s/%s" % (session, line)
146
+
147
+ # Check if output to specific file was requested.
148
+ outfname = args.filename
149
+ if not outfname:
150
+ outfile = sys.stdout # default
151
+ # We don't want to close stdout at the end!
152
+ close_at_end = False
153
+ else:
154
+ outfname = os.path.expanduser(outfname)
155
+ if os.path.exists(outfname):
156
+ try:
157
+ ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
158
+ except StdinNotImplementedError:
159
+ ans = True
160
+ if not ans:
161
+ print('Aborting.')
162
+ return
163
+ print("Overwriting file.")
164
+ outfile = io_open(outfname, 'w', encoding='utf-8')
165
+ close_at_end = True
166
+
167
+ print_nums = args.print_nums
168
+ get_output = args.get_output
169
+ pyprompts = args.pyprompts
170
+ raw = args.raw
171
+
172
+ pattern = None
173
+ limit = None if args.limit is _unspecified else args.limit
174
+
175
+ range_pattern = False
176
+ if args.pattern is not None and not args.range:
177
+ if args.pattern:
178
+ pattern = "*" + " ".join(args.pattern) + "*"
179
+ else:
180
+ pattern = "*"
181
+ hist = history_manager.search(pattern, raw=raw, output=get_output,
182
+ n=limit, unique=args.unique)
183
+ print_nums = True
184
+ elif args.limit is not _unspecified:
185
+ n = 10 if limit is None else limit
186
+ hist = history_manager.get_tail(n, raw=raw, output=get_output)
187
+ else:
188
+ if args.pattern:
189
+ range_pattern = "*" + " ".join(args.pattern) + "*"
190
+ print_nums = True
191
+ hist = history_manager.get_range_by_str(
192
+ " ".join(args.range), raw, get_output
193
+ )
194
+
195
+ # We could be displaying the entire history, so let's not try to pull
196
+ # it into a list in memory. Anything that needs more space will just
197
+ # misalign.
198
+ width = 4
199
+
200
+ for session, lineno, inline in hist:
201
+ # Print user history with tabs expanded to 4 spaces. The GUI
202
+ # clients use hard tabs for easier usability in auto-indented code,
203
+ # but we want to produce PEP-8 compliant history for safe pasting
204
+ # into an editor.
205
+ if get_output:
206
+ inline, output = inline
207
+ if range_pattern:
208
+ if not fnmatch.fnmatch(inline, range_pattern):
209
+ continue
210
+ inline = inline.expandtabs(4).rstrip()
211
+
212
+ multiline = "\n" in inline
213
+ line_sep = '\n' if multiline else ' '
214
+ if print_nums:
215
+ print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
216
+ line_sep), file=outfile, end=u'')
217
+ if pyprompts:
218
+ print(u">>> ", end=u"", file=outfile)
219
+ if multiline:
220
+ inline = "\n... ".join(inline.splitlines()) + "\n..."
221
+ print(inline, file=outfile)
222
+ if get_output and output:
223
+ print(output, file=outfile)
224
+
225
+ if close_at_end:
226
+ outfile.close()
227
+
228
+ @line_magic
229
+ def recall(self, arg):
230
+ r"""Repeat a command, or get command to input line for editing.
231
+
232
+ %recall and %rep are equivalent.
233
+
234
+ - %recall (no arguments):
235
+
236
+ Place a string version of last computation result (stored in the
237
+ special '_' variable) to the next input prompt. Allows you to create
238
+ elaborate command lines without using copy-paste::
239
+
240
+ In[1]: l = ["hei", "vaan"]
241
+ In[2]: "".join(l)
242
+ Out[2]: heivaan
243
+ In[3]: %recall
244
+ In[4]: heivaan_ <== cursor blinking
245
+
246
+ %recall 45
247
+
248
+ Place history line 45 on the next input prompt. Use %hist to find
249
+ out the number.
250
+
251
+ %recall 1-4
252
+
253
+ Combine the specified lines into one cell, and place it on the next
254
+ input prompt. See %history for the slice syntax.
255
+
256
+ %recall foo+bar
257
+
258
+ If foo+bar can be evaluated in the user namespace, the result is
259
+ placed at the next input prompt. Otherwise, the history is searched
260
+ for lines which contain that substring, and the most recent one is
261
+ placed at the next input prompt.
262
+ """
263
+ if not arg: # Last output
264
+ self.shell.set_next_input(str(self.shell.user_ns["_"]))
265
+ return
266
+ # Get history range
267
+ histlines = self.shell.history_manager.get_range_by_str(arg)
268
+ cmd = "\n".join(x[2] for x in histlines)
269
+ if cmd:
270
+ self.shell.set_next_input(cmd.rstrip())
271
+ return
272
+
273
+ try: # Variable in user namespace
274
+ cmd = str(eval(arg, self.shell.user_ns))
275
+ except Exception: # Search for term in history
276
+ histlines = self.shell.history_manager.search("*"+arg+"*")
277
+ for h in reversed([x[2] for x in histlines]):
278
+ if 'recall' in h or 'rep' in h:
279
+ continue
280
+ self.shell.set_next_input(h.rstrip())
281
+ return
282
+ else:
283
+ self.shell.set_next_input(cmd.rstrip())
284
+ return
285
+ print("Couldn't evaluate or find in history:", arg)
286
+
287
+ @line_magic
288
+ def rerun(self, parameter_s=''):
289
+ """Re-run previous input
290
+
291
+ By default, you can specify ranges of input history to be repeated
292
+ (as with %history). With no arguments, it will repeat the last line.
293
+
294
+ Options:
295
+
296
+ -l <n> : Repeat the last n lines of input, not including the
297
+ current command.
298
+
299
+ -g foo : Repeat the most recent line which contains foo
300
+ """
301
+ opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
302
+ if "l" in opts: # Last n lines
303
+ try:
304
+ n = int(opts["l"])
305
+ except ValueError:
306
+ print("Number of lines must be an integer")
307
+ return
308
+
309
+ if n == 0:
310
+ print("Requested 0 last lines - nothing to run")
311
+ return
312
+ elif n < 0:
313
+ print("Number of lines to rerun cannot be negative")
314
+ return
315
+
316
+ hist = self.shell.history_manager.get_tail(n)
317
+ elif "g" in opts: # Search
318
+ p = "*"+opts['g']+"*"
319
+ hist = list(self.shell.history_manager.search(p))
320
+ for l in reversed(hist):
321
+ if "rerun" not in l[2]:
322
+ hist = [l] # The last match which isn't a %rerun
323
+ break
324
+ else:
325
+ hist = [] # No matches except %rerun
326
+ elif args: # Specify history ranges
327
+ hist = self.shell.history_manager.get_range_by_str(args)
328
+ else: # Last line
329
+ hist = self.shell.history_manager.get_tail(1)
330
+ hist = [x[2] for x in hist]
331
+ if not hist:
332
+ print("No lines in history match specification")
333
+ return
334
+ histlines = "\n".join(hist)
335
+ print("=== Executing: ===")
336
+ print(histlines)
337
+ print("=== Output: ===")
338
+ self.shell.run_cell("\n".join(hist), store_history=False)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/logging.py ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions for IPython's own logging.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Stdlib
16
+ import os
17
+ import sys
18
+
19
+ # Our own packages
20
+ from IPython.core.magic import Magics, magics_class, line_magic
21
+ from warnings import warn
22
+ from traitlets import Bool
23
+
24
+ #-----------------------------------------------------------------------------
25
+ # Magic implementation classes
26
+ #-----------------------------------------------------------------------------
27
+
28
+ @magics_class
29
+ class LoggingMagics(Magics):
30
+ """Magics related to all logging machinery."""
31
+
32
+ quiet = Bool(False, help=
33
+ """
34
+ Suppress output of log state when logging is enabled
35
+ """
36
+ ).tag(config=True)
37
+
38
+ @line_magic
39
+ def logstart(self, parameter_s=''):
40
+ """Start logging anywhere in a session.
41
+
42
+ %logstart [-o|-r|-t|-q] [log_name [log_mode]]
43
+
44
+ If no name is given, it defaults to a file named 'ipython_log.py' in your
45
+ current directory, in 'rotate' mode (see below).
46
+
47
+ '%logstart name' saves to file 'name' in 'backup' mode. It saves your
48
+ history up to that point and then continues logging.
49
+
50
+ %logstart takes a second optional parameter: logging mode. This can be one
51
+ of (note that the modes are given unquoted):
52
+
53
+ append
54
+ Keep logging at the end of any existing file.
55
+
56
+ backup
57
+ Rename any existing file to name~ and start name.
58
+
59
+ global
60
+ Append to a single logfile in your home directory.
61
+
62
+ over
63
+ Overwrite any existing log.
64
+
65
+ rotate
66
+ Create rotating logs: name.1~, name.2~, etc.
67
+
68
+ Options:
69
+
70
+ -o
71
+ log also IPython's output. In this mode, all commands which
72
+ generate an Out[NN] prompt are recorded to the logfile, right after
73
+ their corresponding input line. The output lines are always
74
+ prepended with a '#[Out]# ' marker, so that the log remains valid
75
+ Python code.
76
+
77
+ Since this marker is always the same, filtering only the output from
78
+ a log is very easy, using for example a simple awk call::
79
+
80
+ awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
81
+
82
+ -r
83
+ log 'raw' input. Normally, IPython's logs contain the processed
84
+ input, so that user lines are logged in their final form, converted
85
+ into valid Python. For example, %Exit is logged as
86
+ _ip.run_line_magic("Exit"). If the -r flag is given, all input is logged
87
+ exactly as typed, with no transformations applied.
88
+
89
+ -t
90
+ put timestamps before each input line logged (these are put in
91
+ comments).
92
+
93
+ -q
94
+ suppress output of logstate message when logging is invoked
95
+ """
96
+
97
+ opts,par = self.parse_options(parameter_s,'ortq')
98
+ log_output = 'o' in opts
99
+ log_raw_input = 'r' in opts
100
+ timestamp = 't' in opts
101
+ quiet = 'q' in opts
102
+
103
+ logger = self.shell.logger
104
+
105
+ # if no args are given, the defaults set in the logger constructor by
106
+ # ipython remain valid
107
+ if par:
108
+ try:
109
+ logfname,logmode = par.split()
110
+ except:
111
+ logfname = par
112
+ logmode = 'backup'
113
+ else:
114
+ logfname = logger.logfname
115
+ logmode = logger.logmode
116
+ # put logfname into rc struct as if it had been called on the command
117
+ # line, so it ends up saved in the log header Save it in case we need
118
+ # to restore it...
119
+ old_logfile = self.shell.logfile
120
+ if logfname:
121
+ logfname = os.path.expanduser(logfname)
122
+ self.shell.logfile = logfname
123
+
124
+ loghead = u'# IPython log file\n\n'
125
+ try:
126
+ logger.logstart(logfname, loghead, logmode, log_output, timestamp,
127
+ log_raw_input)
128
+ except:
129
+ self.shell.logfile = old_logfile
130
+ warn("Couldn't start log: %s" % sys.exc_info()[1])
131
+ else:
132
+ # log input history up to this point, optionally interleaving
133
+ # output if requested
134
+
135
+ if timestamp:
136
+ # disable timestamping for the previous history, since we've
137
+ # lost those already (no time machine here).
138
+ logger.timestamp = False
139
+
140
+ if log_raw_input:
141
+ input_hist = self.shell.history_manager.input_hist_raw
142
+ else:
143
+ input_hist = self.shell.history_manager.input_hist_parsed
144
+
145
+ if log_output:
146
+ log_write = logger.log_write
147
+ output_hist = self.shell.history_manager.output_hist
148
+ for n in range(1,len(input_hist)-1):
149
+ log_write(input_hist[n].rstrip() + u'\n')
150
+ if n in output_hist:
151
+ log_write(repr(output_hist[n]),'output')
152
+ else:
153
+ logger.log_write(u'\n'.join(input_hist[1:]))
154
+ logger.log_write(u'\n')
155
+ if timestamp:
156
+ # re-enable timestamping
157
+ logger.timestamp = True
158
+
159
+ if not (self.quiet or quiet):
160
+ print ('Activating auto-logging. '
161
+ 'Current session state plus future input saved.')
162
+ logger.logstate()
163
+
164
+ @line_magic
165
+ def logstop(self, parameter_s=''):
166
+ """Fully stop logging and close log file.
167
+
168
+ In order to start logging again, a new %logstart call needs to be made,
169
+ possibly (though not necessarily) with a new filename, mode and other
170
+ options."""
171
+ self.shell.logger.logstop()
172
+
173
+ @line_magic
174
+ def logoff(self, parameter_s=''):
175
+ """Temporarily stop logging.
176
+
177
+ You must have previously started logging."""
178
+ self.shell.logger.switch_log(0)
179
+
180
+ @line_magic
181
+ def logon(self, parameter_s=''):
182
+ """Restart logging.
183
+
184
+ This function is for restarting logging which you've temporarily
185
+ stopped with %logoff. For starting logging for the first time, you
186
+ must use the %logstart function, which allows you to specify an
187
+ optional log filename."""
188
+
189
+ self.shell.logger.switch_log(1)
190
+
191
+ @line_magic
192
+ def logstate(self, parameter_s=''):
193
+ """Print the status of the logging system."""
194
+
195
+ self.shell.logger.logstate()
temp_venv/lib/python3.13/site-packages/IPython/core/magics/namespace.py ADDED
@@ -0,0 +1,711 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of namespace-related magic functions.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Stdlib
16
+ import gc
17
+ import re
18
+ import sys
19
+
20
+ # Our own packages
21
+ from IPython.core import page
22
+ from IPython.core.error import StdinNotImplementedError, UsageError
23
+ from IPython.core.magic import Magics, magics_class, line_magic
24
+ from IPython.testing.skipdoctest import skip_doctest
25
+ from IPython.utils.encoding import DEFAULT_ENCODING
26
+ from IPython.utils.openpy import read_py_file
27
+ from IPython.utils.path import get_py_filename
28
+
29
+ #-----------------------------------------------------------------------------
30
+ # Magic implementation classes
31
+ #-----------------------------------------------------------------------------
32
+
33
+ @magics_class
34
+ class NamespaceMagics(Magics):
35
+ """Magics to manage various aspects of the user's namespace.
36
+
37
+ These include listing variables, introspecting into them, etc.
38
+ """
39
+
40
+ @line_magic
41
+ def pinfo(self, parameter_s='', namespaces=None):
42
+ """Provide detailed information about an object.
43
+
44
+ '%pinfo object' is just a synonym for object? or ?object."""
45
+
46
+ # print('pinfo par: <%s>' % parameter_s) # dbg
47
+ # detail_level: 0 -> obj? , 1 -> obj??
48
+ detail_level = 0
49
+ # We need to detect if we got called as 'pinfo pinfo foo', which can
50
+ # happen if the user types 'pinfo foo?' at the cmd line.
51
+ pinfo,qmark1,oname,qmark2 = \
52
+ re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
53
+ if pinfo or qmark1 or qmark2:
54
+ detail_level = 1
55
+ if "*" in oname:
56
+ self.psearch(oname)
57
+ else:
58
+ self.shell._inspect('pinfo', oname, detail_level=detail_level,
59
+ namespaces=namespaces)
60
+
61
+ @line_magic
62
+ def pinfo2(self, parameter_s='', namespaces=None):
63
+ """Provide extra detailed information about an object.
64
+
65
+ '%pinfo2 object' is just a synonym for object?? or ??object."""
66
+ self.shell._inspect('pinfo', parameter_s, detail_level=1,
67
+ namespaces=namespaces)
68
+
69
+ @skip_doctest
70
+ @line_magic
71
+ def pdef(self, parameter_s='', namespaces=None):
72
+ """Print the call signature for any callable object.
73
+
74
+ If the object is a class, print the constructor information.
75
+
76
+ Examples
77
+ --------
78
+ ::
79
+
80
+ In [3]: %pdef urllib.urlopen
81
+ urllib.urlopen(url, data=None, proxies=None)
82
+ """
83
+ self.shell._inspect('pdef',parameter_s, namespaces)
84
+
85
+ @line_magic
86
+ def pdoc(self, parameter_s='', namespaces=None):
87
+ """Print the docstring for an object.
88
+
89
+ If the given object is a class, it will print both the class and the
90
+ constructor docstrings."""
91
+ self.shell._inspect('pdoc',parameter_s, namespaces)
92
+
93
+ @line_magic
94
+ def psource(self, parameter_s='', namespaces=None):
95
+ """Print (or run through pager) the source code for an object."""
96
+ if not parameter_s:
97
+ raise UsageError('Missing object name.')
98
+ self.shell._inspect('psource',parameter_s, namespaces)
99
+
100
+ @line_magic
101
+ def pfile(self, parameter_s='', namespaces=None):
102
+ """Print (or run through pager) the file where an object is defined.
103
+
104
+ The file opens at the line where the object definition begins. IPython
105
+ will honor the environment variable PAGER if set, and otherwise will
106
+ do its best to print the file in a convenient form.
107
+
108
+ If the given argument is not an object currently defined, IPython will
109
+ try to interpret it as a filename (automatically adding a .py extension
110
+ if needed). You can thus use %pfile as a syntax highlighting code
111
+ viewer."""
112
+
113
+ # first interpret argument as an object name
114
+ out = self.shell._inspect('pfile',parameter_s, namespaces)
115
+ # if not, try the input as a filename
116
+ if out == 'not found':
117
+ try:
118
+ filename = get_py_filename(parameter_s)
119
+ except IOError as msg:
120
+ print(msg)
121
+ return
122
+ page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
123
+
124
+ @line_magic
125
+ def psearch(self, parameter_s=''):
126
+ """Search for object in namespaces by wildcard.
127
+
128
+ %psearch [options] PATTERN [OBJECT TYPE]
129
+
130
+ Note: ? can be used as a synonym for %psearch, at the beginning or at
131
+ the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
132
+ rest of the command line must be unchanged (options come first), so
133
+ for example the following forms are equivalent
134
+
135
+ %psearch -i a* function
136
+ -i a* function?
137
+ ?-i a* function
138
+
139
+ Arguments:
140
+
141
+ PATTERN
142
+
143
+ where PATTERN is a string containing * as a wildcard similar to its
144
+ use in a shell. The pattern is matched in all namespaces on the
145
+ search path. By default objects starting with a single _ are not
146
+ matched, many IPython generated objects have a single
147
+ underscore. The default is case insensitive matching. Matching is
148
+ also done on the attributes of objects and not only on the objects
149
+ in a module.
150
+
151
+ [OBJECT TYPE]
152
+
153
+ Is the name of a python type from the types module. The name is
154
+ given in lowercase without the ending type, ex. StringType is
155
+ written string. By adding a type here only objects matching the
156
+ given type are matched. Using all here makes the pattern match all
157
+ types (this is the default).
158
+
159
+ Options:
160
+
161
+ -a: makes the pattern match even objects whose names start with a
162
+ single underscore. These names are normally omitted from the
163
+ search.
164
+
165
+ -i/-c: make the pattern case insensitive/sensitive. If neither of
166
+ these options are given, the default is read from your configuration
167
+ file, with the option ``InteractiveShell.wildcards_case_sensitive``.
168
+ If this option is not specified in your configuration file, IPython's
169
+ internal default is to do a case sensitive search.
170
+
171
+ -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
172
+ specify can be searched in any of the following namespaces:
173
+ 'builtin', 'user', 'user_global','internal', 'alias', where
174
+ 'builtin' and 'user' are the search defaults. Note that you should
175
+ not use quotes when specifying namespaces.
176
+
177
+ -l: List all available object types for object matching. This function
178
+ can be used without arguments.
179
+
180
+ 'Builtin' contains the python module builtin, 'user' contains all
181
+ user data, 'alias' only contain the shell aliases and no python
182
+ objects, 'internal' contains objects used by IPython. The
183
+ 'user_global' namespace is only used by embedded IPython instances,
184
+ and it contains module-level globals. You can add namespaces to the
185
+ search with -s or exclude them with -e (these options can be given
186
+ more than once).
187
+
188
+ Examples
189
+ --------
190
+ ::
191
+
192
+ %psearch a* -> objects beginning with an a
193
+ %psearch -e builtin a* -> objects NOT in the builtin space starting in a
194
+ %psearch a* function -> all functions beginning with an a
195
+ %psearch re.e* -> objects beginning with an e in module re
196
+ %psearch r*.e* -> objects that start with e in modules starting in r
197
+ %psearch r*.* string -> all strings in modules beginning with r
198
+
199
+ Case sensitive search::
200
+
201
+ %psearch -c a* list all object beginning with lower case a
202
+
203
+ Show objects beginning with a single _::
204
+
205
+ %psearch -a _* list objects beginning with a single underscore
206
+
207
+ List available objects::
208
+
209
+ %psearch -l list all available object types
210
+ """
211
+ # default namespaces to be searched
212
+ def_search = ['user_local', 'user_global', 'builtin']
213
+
214
+ # Process options/args
215
+ opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True)
216
+ opt = opts.get
217
+ shell = self.shell
218
+ psearch = shell.inspector.psearch
219
+
220
+ # select list object types
221
+ list_types = False
222
+ if 'l' in opts:
223
+ list_types = True
224
+
225
+ # select case options
226
+ if 'i' in opts:
227
+ ignore_case = True
228
+ elif 'c' in opts:
229
+ ignore_case = False
230
+ else:
231
+ ignore_case = not shell.wildcards_case_sensitive
232
+
233
+ # Build list of namespaces to search from user options
234
+ def_search.extend(opt('s',[]))
235
+ ns_exclude = ns_exclude=opt('e',[])
236
+ ns_search = [nm for nm in def_search if nm not in ns_exclude]
237
+
238
+ # Call the actual search
239
+ try:
240
+ psearch(args,shell.ns_table,ns_search,
241
+ show_all=opt('a'),ignore_case=ignore_case, list_types=list_types)
242
+ except:
243
+ shell.showtraceback()
244
+
245
+ @skip_doctest
246
+ @line_magic
247
+ def who_ls(self, parameter_s=''):
248
+ """Return a sorted list of all interactive variables.
249
+
250
+ If arguments are given, only variables of types matching these
251
+ arguments are returned.
252
+
253
+ Examples
254
+ --------
255
+ Define two variables and list them with who_ls::
256
+
257
+ In [1]: alpha = 123
258
+
259
+ In [2]: beta = 'test'
260
+
261
+ In [3]: %who_ls
262
+ Out[3]: ['alpha', 'beta']
263
+
264
+ In [4]: %who_ls int
265
+ Out[4]: ['alpha']
266
+
267
+ In [5]: %who_ls str
268
+ Out[5]: ['beta']
269
+ """
270
+
271
+ user_ns = self.shell.user_ns
272
+ user_ns_hidden = self.shell.user_ns_hidden
273
+ nonmatching = object() # This can never be in user_ns
274
+ out = [ i for i in user_ns
275
+ if not i.startswith('_') \
276
+ and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
277
+
278
+ typelist = parameter_s.split()
279
+ if typelist:
280
+ typeset = set(typelist)
281
+ out = [i for i in out if type(user_ns[i]).__name__ in typeset]
282
+
283
+ out.sort()
284
+ return out
285
+
286
+ @skip_doctest
287
+ @line_magic
288
+ def who(self, parameter_s=''):
289
+ """Print all interactive variables, with some minimal formatting.
290
+
291
+ If any arguments are given, only variables whose type matches one of
292
+ these are printed. For example::
293
+
294
+ %who function str
295
+
296
+ will only list functions and strings, excluding all other types of
297
+ variables. To find the proper type names, simply use type(var) at a
298
+ command line to see how python prints type names. For example:
299
+
300
+ ::
301
+
302
+ In [1]: type('hello')\\
303
+ Out[1]: <type 'str'>
304
+
305
+ indicates that the type name for strings is 'str'.
306
+
307
+ ``%who`` always excludes executed names loaded through your configuration
308
+ file and things which are internal to IPython.
309
+
310
+ This is deliberate, as typically you may load many modules and the
311
+ purpose of %who is to show you only what you've manually defined.
312
+
313
+ Examples
314
+ --------
315
+
316
+ Define two variables and list them with who::
317
+
318
+ In [1]: alpha = 123
319
+
320
+ In [2]: beta = 'test'
321
+
322
+ In [3]: %who
323
+ alpha beta
324
+
325
+ In [4]: %who int
326
+ alpha
327
+
328
+ In [5]: %who str
329
+ beta
330
+ """
331
+
332
+ varlist = self.who_ls(parameter_s)
333
+ if not varlist:
334
+ if parameter_s:
335
+ print('No variables match your requested type.')
336
+ else:
337
+ print('Interactive namespace is empty.')
338
+ return
339
+
340
+ # if we have variables, move on...
341
+ count = 0
342
+ for i in varlist:
343
+ print(i+'\t', end=' ')
344
+ count += 1
345
+ if count > 8:
346
+ count = 0
347
+ print()
348
+ print()
349
+
350
+ @skip_doctest
351
+ @line_magic
352
+ def whos(self, parameter_s=''):
353
+ """Like %who, but gives some extra information about each variable.
354
+
355
+ The same type filtering of %who can be applied here.
356
+
357
+ For all variables, the type is printed. Additionally it prints:
358
+
359
+ - For {},[],(): their length.
360
+
361
+ - For numpy arrays, a summary with shape, number of
362
+ elements, typecode and size in memory.
363
+
364
+ - Everything else: a string representation, snipping their middle if
365
+ too long.
366
+
367
+ Examples
368
+ --------
369
+ Define two variables and list them with whos::
370
+
371
+ In [1]: alpha = 123
372
+
373
+ In [2]: beta = 'test'
374
+
375
+ In [3]: %whos
376
+ Variable Type Data/Info
377
+ --------------------------------
378
+ alpha int 123
379
+ beta str test
380
+ """
381
+
382
+ varnames = self.who_ls(parameter_s)
383
+ if not varnames:
384
+ if parameter_s:
385
+ print('No variables match your requested type.')
386
+ else:
387
+ print('Interactive namespace is empty.')
388
+ return
389
+
390
+ # if we have variables, move on...
391
+
392
+ # for these types, show len() instead of data:
393
+ seq_types = ['dict', 'list', 'tuple']
394
+
395
+ # for numpy arrays, display summary info
396
+ ndarray_type = None
397
+ if 'numpy' in sys.modules:
398
+ try:
399
+ from numpy import ndarray
400
+ except ImportError:
401
+ pass
402
+ else:
403
+ ndarray_type = ndarray.__name__
404
+
405
+ # Find all variable names and types so we can figure out column sizes
406
+
407
+ # some types are well known and can be shorter
408
+ abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
409
+ def type_name(v):
410
+ tn = type(v).__name__
411
+ return abbrevs.get(tn,tn)
412
+
413
+ varlist = [self.shell.user_ns[n] for n in varnames]
414
+
415
+ typelist = []
416
+ for vv in varlist:
417
+ tt = type_name(vv)
418
+
419
+ if tt=='instance':
420
+ typelist.append( abbrevs.get(str(vv.__class__),
421
+ str(vv.__class__)))
422
+ else:
423
+ typelist.append(tt)
424
+
425
+ # column labels and # of spaces as separator
426
+ varlabel = 'Variable'
427
+ typelabel = 'Type'
428
+ datalabel = 'Data/Info'
429
+ colsep = 3
430
+ # variable format strings
431
+ vformat = "{0:<{varwidth}}{1:<{typewidth}}"
432
+ aformat = "%s: %s elems, type `%s`, %s bytes"
433
+ # find the size of the columns to format the output nicely
434
+ varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
435
+ typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
436
+ # table header
437
+ print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
438
+ ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
439
+ # and the table itself
440
+ kb = 1024
441
+ Mb = 1048576 # kb**2
442
+ for vname,var,vtype in zip(varnames,varlist,typelist):
443
+ print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
444
+ if vtype in seq_types:
445
+ print("n="+str(len(var)))
446
+ elif vtype == ndarray_type:
447
+ vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
448
+ if vtype==ndarray_type:
449
+ # numpy
450
+ vsize = var.size
451
+ vbytes = vsize*var.itemsize
452
+ vdtype = var.dtype
453
+
454
+ if vbytes < 100000:
455
+ print(aformat % (vshape, vsize, vdtype, vbytes))
456
+ else:
457
+ print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
458
+ if vbytes < Mb:
459
+ print('(%s kb)' % (vbytes/kb,))
460
+ else:
461
+ print('(%s Mb)' % (vbytes/Mb,))
462
+ else:
463
+ try:
464
+ vstr = str(var)
465
+ except UnicodeEncodeError:
466
+ vstr = var.encode(DEFAULT_ENCODING,
467
+ 'backslashreplace')
468
+ except:
469
+ vstr = "<object with id %d (str() failed)>" % id(var)
470
+ vstr = vstr.replace('\n', '\\n')
471
+ if len(vstr) < 50:
472
+ print(vstr)
473
+ else:
474
+ print(vstr[:25] + "<...>" + vstr[-25:])
475
+
476
+ @line_magic
477
+ def reset(self, parameter_s=''):
478
+ """Resets the namespace by removing all names defined by the user, if
479
+ called without arguments, or by removing some types of objects, such
480
+ as everything currently in IPython's In[] and Out[] containers (see
481
+ the parameters for details).
482
+
483
+ Parameters
484
+ ----------
485
+ -f
486
+ force reset without asking for confirmation.
487
+ -s
488
+ 'Soft' reset: Only clears your namespace, leaving history intact.
489
+ References to objects may be kept. By default (without this option),
490
+ we do a 'hard' reset, giving you a new session and removing all
491
+ references to objects from the current session.
492
+ --aggressive
493
+ Try to aggressively remove modules from sys.modules ; this
494
+ may allow you to reimport Python modules that have been updated and
495
+ pick up changes, but can have unintended consequences.
496
+
497
+ in
498
+ reset input history
499
+ out
500
+ reset output history
501
+ dhist
502
+ reset directory history
503
+ array
504
+ reset only variables that are NumPy arrays
505
+
506
+ See Also
507
+ --------
508
+ reset_selective : invoked as ``%reset_selective``
509
+
510
+ Examples
511
+ --------
512
+ ::
513
+
514
+ In [6]: a = 1
515
+
516
+ In [7]: a
517
+ Out[7]: 1
518
+
519
+ In [8]: 'a' in get_ipython().user_ns
520
+ Out[8]: True
521
+
522
+ In [9]: %reset -f
523
+
524
+ In [1]: 'a' in get_ipython().user_ns
525
+ Out[1]: False
526
+
527
+ In [2]: %reset -f in
528
+ Flushing input history
529
+
530
+ In [3]: %reset -f dhist in
531
+ Flushing directory history
532
+ Flushing input history
533
+
534
+ Notes
535
+ -----
536
+ Calling this magic from clients that do not implement standard input,
537
+ such as the ipython notebook interface, will reset the namespace
538
+ without confirmation.
539
+ """
540
+ opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list")
541
+ if "f" in opts:
542
+ ans = True
543
+ else:
544
+ try:
545
+ ans = self.shell.ask_yes_no(
546
+ "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
547
+ default='n')
548
+ except StdinNotImplementedError:
549
+ ans = True
550
+ if not ans:
551
+ print('Nothing done.')
552
+ return
553
+
554
+ if 's' in opts: # Soft reset
555
+ user_ns = self.shell.user_ns
556
+ for i in self.who_ls():
557
+ del(user_ns[i])
558
+ elif len(args) == 0: # Hard reset
559
+ self.shell.reset(new_session=False, aggressive=("aggressive" in opts))
560
+
561
+ # reset in/out/dhist/array: previously extensinions/clearcmd.py
562
+ ip = self.shell
563
+ user_ns = self.shell.user_ns # local lookup, heavily used
564
+
565
+ for target in args:
566
+ target = target.lower() # make matches case insensitive
567
+ if target == 'out':
568
+ print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
569
+ self.shell.displayhook.flush()
570
+
571
+ elif target == 'in':
572
+ print("Flushing input history")
573
+ pc = self.shell.displayhook.prompt_count + 1
574
+ for n in range(1, pc):
575
+ key = '_i'+repr(n)
576
+ user_ns.pop(key,None)
577
+ user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
578
+ hm = ip.history_manager
579
+ # don't delete these, as %save and %macro depending on the
580
+ # length of these lists to be preserved
581
+ hm.input_hist_parsed[:] = [''] * pc
582
+ hm.input_hist_raw[:] = [''] * pc
583
+ # hm has internal machinery for _i,_ii,_iii, clear it out
584
+ hm._i = hm._ii = hm._iii = hm._i00 = u''
585
+
586
+ elif target == 'array':
587
+ # Support cleaning up numpy arrays
588
+ try:
589
+ from numpy import ndarray
590
+ # This must be done with items and not iteritems because
591
+ # we're going to modify the dict in-place.
592
+ for x,val in list(user_ns.items()):
593
+ if isinstance(val,ndarray):
594
+ del user_ns[x]
595
+ except ImportError:
596
+ print("reset array only works if Numpy is available.")
597
+
598
+ elif target == 'dhist':
599
+ print("Flushing directory history")
600
+ del user_ns['_dh'][:]
601
+
602
+ else:
603
+ print("Don't know how to reset ", end=' ')
604
+ print(target + ", please run `%reset?` for details")
605
+
606
+ gc.collect()
607
+
608
+ @line_magic
609
+ def reset_selective(self, parameter_s=''):
610
+ """Resets the namespace by removing names defined by the user.
611
+
612
+ Input/Output history are left around in case you need them.
613
+
614
+ %reset_selective [-f] regex
615
+
616
+ No action is taken if regex is not included
617
+
618
+ Options
619
+ -f : force reset without asking for confirmation.
620
+
621
+ See Also
622
+ --------
623
+ reset : invoked as ``%reset``
624
+
625
+ Examples
626
+ --------
627
+ We first fully reset the namespace so your output looks identical to
628
+ this example for pedagogical reasons; in practice you do not need a
629
+ full reset::
630
+
631
+ In [1]: %reset -f
632
+
633
+ Now, with a clean namespace we can make a few variables and use
634
+ ``%reset_selective`` to only delete names that match our regexp::
635
+
636
+ In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
637
+
638
+ In [3]: who_ls
639
+ Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
640
+
641
+ In [4]: %reset_selective -f b[2-3]m
642
+
643
+ In [5]: who_ls
644
+ Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
645
+
646
+ In [6]: %reset_selective -f d
647
+
648
+ In [7]: who_ls
649
+ Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
650
+
651
+ In [8]: %reset_selective -f c
652
+
653
+ In [9]: who_ls
654
+ Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
655
+
656
+ In [10]: %reset_selective -f b
657
+
658
+ In [11]: who_ls
659
+ Out[11]: ['a']
660
+
661
+ Notes
662
+ -----
663
+ Calling this magic from clients that do not implement standard input,
664
+ such as the ipython notebook interface, will reset the namespace
665
+ without confirmation.
666
+ """
667
+
668
+ opts, regex = self.parse_options(parameter_s,'f')
669
+
670
+ if 'f' in opts:
671
+ ans = True
672
+ else:
673
+ try:
674
+ ans = self.shell.ask_yes_no(
675
+ "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
676
+ default='n')
677
+ except StdinNotImplementedError:
678
+ ans = True
679
+ if not ans:
680
+ print('Nothing done.')
681
+ return
682
+ user_ns = self.shell.user_ns
683
+ if not regex:
684
+ print('No regex pattern specified. Nothing done.')
685
+ return
686
+ else:
687
+ try:
688
+ m = re.compile(regex)
689
+ except TypeError as e:
690
+ raise TypeError('regex must be a string or compiled pattern') from e
691
+ for i in self.who_ls():
692
+ if m.search(i):
693
+ del(user_ns[i])
694
+
695
+ @line_magic
696
+ def xdel(self, parameter_s=''):
697
+ """Delete a variable, trying to clear it from anywhere that
698
+ IPython's machinery has references to it. By default, this uses
699
+ the identity of the named object in the user namespace to remove
700
+ references held under other names. The object is also removed
701
+ from the output history.
702
+
703
+ Options
704
+ -n : Delete the specified name from all namespaces, without
705
+ checking their identity.
706
+ """
707
+ opts, varname = self.parse_options(parameter_s,'n')
708
+ try:
709
+ self.shell.del_var(varname, ('n' in opts))
710
+ except (NameError, ValueError) as e:
711
+ print(type(e).__name__ +": "+ str(e))
temp_venv/lib/python3.13/site-packages/IPython/core/magics/osm.py ADDED
@@ -0,0 +1,855 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions for interaction with the OS.
2
+
3
+ Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4
+ builtin.
5
+ """
6
+ # Copyright (c) IPython Development Team.
7
+ # Distributed under the terms of the Modified BSD License.
8
+
9
+ import io
10
+ import os
11
+ import pathlib
12
+ import re
13
+ import sys
14
+ from pprint import pformat
15
+
16
+ from IPython.core import magic_arguments
17
+ from IPython.core import oinspect
18
+ from IPython.core import page
19
+ from IPython.core.alias import AliasError, Alias
20
+ from IPython.core.error import UsageError
21
+ from IPython.core.magic import (
22
+ Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
23
+ )
24
+ from IPython.testing.skipdoctest import skip_doctest
25
+ from IPython.utils.openpy import source_to_unicode
26
+ from IPython.utils.process import abbrev_cwd
27
+ from IPython.utils.terminal import set_term_title
28
+ from traitlets import Bool
29
+ from warnings import warn
30
+
31
+
32
+ @magics_class
33
+ class OSMagics(Magics):
34
+ """Magics to interact with the underlying OS (shell-type functionality).
35
+ """
36
+
37
+ cd_force_quiet = Bool(False,
38
+ help="Force %cd magic to be quiet even if -q is not passed."
39
+ ).tag(config=True)
40
+
41
+ def __init__(self, shell=None, **kwargs):
42
+
43
+ # Now define isexec in a cross platform manner.
44
+ self.is_posix = False
45
+ self.execre = None
46
+ if os.name == 'posix':
47
+ self.is_posix = True
48
+ else:
49
+ try:
50
+ winext = os.environ['pathext'].replace(';','|').replace('.','')
51
+ except KeyError:
52
+ winext = 'exe|com|bat|py'
53
+ try:
54
+ self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
55
+ except re.error:
56
+ warn("Seems like your pathext environmental "
57
+ "variable is malformed. Please check it to "
58
+ "enable a proper handle of file extensions "
59
+ "managed for your system")
60
+ winext = 'exe|com|bat|py'
61
+ self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
62
+
63
+ # call up the chain
64
+ super().__init__(shell=shell, **kwargs)
65
+
66
+
67
+ def _isexec_POSIX(self, file):
68
+ """
69
+ Test for executable on a POSIX system
70
+ """
71
+ if os.access(file.path, os.X_OK):
72
+ # will fail on maxOS if access is not X_OK
73
+ return file.is_file()
74
+ return False
75
+
76
+
77
+
78
+ def _isexec_WIN(self, file):
79
+ """
80
+ Test for executable file on non POSIX system
81
+ """
82
+ return file.is_file() and self.execre.match(file.name) is not None
83
+
84
+ def isexec(self, file):
85
+ """
86
+ Test for executable file on non POSIX system
87
+ """
88
+ if self.is_posix:
89
+ return self._isexec_POSIX(file)
90
+ else:
91
+ return self._isexec_WIN(file)
92
+
93
+
94
+ @skip_doctest
95
+ @line_magic
96
+ def alias(self, parameter_s=''):
97
+ """Define an alias for a system command.
98
+
99
+ '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
100
+
101
+ Then, typing 'alias_name params' will execute the system command 'cmd
102
+ params' (from your underlying operating system).
103
+
104
+ Aliases have lower precedence than magic functions and Python normal
105
+ variables, so if 'foo' is both a Python variable and an alias, the
106
+ alias can not be executed until 'del foo' removes the Python variable.
107
+
108
+ You can use the %l specifier in an alias definition to represent the
109
+ whole line when the alias is called. For example::
110
+
111
+ In [2]: alias bracket echo "Input in brackets: <%l>"
112
+ In [3]: bracket hello world
113
+ Input in brackets: <hello world>
114
+
115
+ You can also define aliases with parameters using %s specifiers (one
116
+ per parameter)::
117
+
118
+ In [1]: alias parts echo first %s second %s
119
+ In [2]: %parts A B
120
+ first A second B
121
+ In [3]: %parts A
122
+ Incorrect number of arguments: 2 expected.
123
+ parts is an alias to: 'echo first %s second %s'
124
+
125
+ Note that %l and %s are mutually exclusive. You can only use one or
126
+ the other in your aliases.
127
+
128
+ Aliases expand Python variables just like system calls using ! or !!
129
+ do: all expressions prefixed with '$' get expanded. For details of
130
+ the semantic rules, see PEP-215:
131
+ https://peps.python.org/pep-0215/. This is the library used by
132
+ IPython for variable expansion. If you want to access a true shell
133
+ variable, an extra $ is necessary to prevent its expansion by
134
+ IPython::
135
+
136
+ In [6]: alias show echo
137
+ In [7]: PATH='A Python string'
138
+ In [8]: show $PATH
139
+ A Python string
140
+ In [9]: show $$PATH
141
+ /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
142
+
143
+ You can use the alias facility to access all of $PATH. See the %rehashx
144
+ function, which automatically creates aliases for the contents of your
145
+ $PATH.
146
+
147
+ If called with no parameters, %alias prints the current alias table
148
+ for your system. For posix systems, the default aliases are 'cat',
149
+ 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
150
+ aliases are added. For windows-based systems, the default aliases are
151
+ 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
152
+
153
+ You can see the definition of alias by adding a question mark in the
154
+ end::
155
+
156
+ In [1]: cat?
157
+ Repr: <alias cat for 'cat'>"""
158
+
159
+ par = parameter_s.strip()
160
+ if not par:
161
+ aliases = sorted(self.shell.alias_manager.aliases)
162
+ # stored = self.shell.db.get('stored_aliases', {} )
163
+ # for k, v in stored:
164
+ # atab.append(k, v[0])
165
+
166
+ print("Total number of aliases:", len(aliases))
167
+ sys.stdout.flush()
168
+ return aliases
169
+
170
+ # Now try to define a new one
171
+ try:
172
+ alias,cmd = par.split(None, 1)
173
+ except TypeError:
174
+ print(oinspect.getdoc(self.alias))
175
+ return
176
+
177
+ try:
178
+ self.shell.alias_manager.define_alias(alias, cmd)
179
+ except AliasError as e:
180
+ print(e)
181
+ # end magic_alias
182
+
183
+ @line_magic
184
+ def unalias(self, parameter_s=''):
185
+ """Remove an alias"""
186
+
187
+ aname = parameter_s.strip()
188
+ try:
189
+ self.shell.alias_manager.undefine_alias(aname)
190
+ except ValueError as e:
191
+ print(e)
192
+ return
193
+
194
+ stored = self.shell.db.get('stored_aliases', {} )
195
+ if aname in stored:
196
+ print("Removing %stored alias",aname)
197
+ del stored[aname]
198
+ self.shell.db['stored_aliases'] = stored
199
+
200
+ @line_magic
201
+ def rehashx(self, parameter_s=''):
202
+ """Update the alias table with all executable files in $PATH.
203
+
204
+ rehashx explicitly checks that every entry in $PATH is a file
205
+ with execute access (os.X_OK).
206
+
207
+ Under Windows, it checks executability as a match against a
208
+ '|'-separated string of extensions, stored in the IPython config
209
+ variable win_exec_ext. This defaults to 'exe|com|bat'.
210
+
211
+ This function also resets the root module cache of module completer,
212
+ used on slow filesystems.
213
+ """
214
+ from IPython.core.alias import InvalidAliasError
215
+
216
+ # for the benefit of module completer in ipy_completers.py
217
+ del self.shell.db['rootmodules_cache']
218
+
219
+ path = [os.path.abspath(os.path.expanduser(p)) for p in
220
+ os.environ.get('PATH','').split(os.pathsep)]
221
+
222
+ syscmdlist = []
223
+ savedir = os.getcwd()
224
+
225
+ # Now walk the paths looking for executables to alias.
226
+ try:
227
+ # write the whole loop for posix/Windows so we don't have an if in
228
+ # the innermost part
229
+ if self.is_posix:
230
+ for pdir in path:
231
+ try:
232
+ os.chdir(pdir)
233
+ except OSError:
234
+ continue
235
+
236
+ # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
237
+ dirlist = os.scandir(path=pdir)
238
+ for ff in dirlist:
239
+ if self.isexec(ff):
240
+ fname = ff.name
241
+ try:
242
+ # Removes dots from the name since ipython
243
+ # will assume names with dots to be python.
244
+ if not self.shell.alias_manager.is_alias(fname):
245
+ self.shell.alias_manager.define_alias(
246
+ fname.replace('.',''), fname)
247
+ except InvalidAliasError:
248
+ pass
249
+ else:
250
+ syscmdlist.append(fname)
251
+ else:
252
+ no_alias = Alias.blacklist
253
+ for pdir in path:
254
+ try:
255
+ os.chdir(pdir)
256
+ except OSError:
257
+ continue
258
+
259
+ # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
260
+ dirlist = os.scandir(pdir)
261
+ for ff in dirlist:
262
+ fname = ff.name
263
+ base, ext = os.path.splitext(fname)
264
+ if self.isexec(ff) and base.lower() not in no_alias:
265
+ if ext.lower() == '.exe':
266
+ fname = base
267
+ try:
268
+ # Removes dots from the name since ipython
269
+ # will assume names with dots to be python.
270
+ self.shell.alias_manager.define_alias(
271
+ base.lower().replace('.',''), fname)
272
+ except InvalidAliasError:
273
+ pass
274
+ syscmdlist.append(fname)
275
+
276
+ self.shell.db['syscmdlist'] = syscmdlist
277
+ finally:
278
+ os.chdir(savedir)
279
+
280
+ @skip_doctest
281
+ @line_magic
282
+ def pwd(self, parameter_s=''):
283
+ """Return the current working directory path.
284
+
285
+ Examples
286
+ --------
287
+ ::
288
+
289
+ In [9]: pwd
290
+ Out[9]: '/home/tsuser/sprint/ipython'
291
+ """
292
+ try:
293
+ return os.getcwd()
294
+ except FileNotFoundError as e:
295
+ raise UsageError("CWD no longer exists - please use %cd to change directory.") from e
296
+
297
+ @skip_doctest
298
+ @line_magic
299
+ def cd(self, parameter_s=''):
300
+ """Change the current working directory.
301
+
302
+ This command automatically maintains an internal list of directories
303
+ you visit during your IPython session, in the variable ``_dh``. The
304
+ command :magic:`%dhist` shows this history nicely formatted. You can
305
+ also do ``cd -<tab>`` to see directory history conveniently.
306
+ Usage:
307
+
308
+ - ``cd 'dir'``: changes to directory 'dir'.
309
+ - ``cd -``: changes to the last visited directory.
310
+ - ``cd -<n>``: changes to the n-th directory in the directory history.
311
+ - ``cd --foo``: change to directory that matches 'foo' in history
312
+ - ``cd -b <bookmark_name>``: jump to a bookmark set by %bookmark
313
+ - Hitting a tab key after ``cd -b`` allows you to tab-complete
314
+ bookmark names.
315
+
316
+ .. note::
317
+ ``cd <bookmark_name>`` is enough if there is no directory
318
+ ``<bookmark_name>``, but a bookmark with the name exists.
319
+
320
+ Options:
321
+
322
+ -q Be quiet. Do not print the working directory after the
323
+ cd command is executed. By default IPython's cd
324
+ command does print this directory, since the default
325
+ prompts do not display path information.
326
+
327
+ .. note::
328
+ Note that ``!cd`` doesn't work for this purpose because the shell
329
+ where ``!command`` runs is immediately discarded after executing
330
+ 'command'.
331
+
332
+ Examples
333
+ --------
334
+ ::
335
+
336
+ In [10]: cd parent/child
337
+ /home/tsuser/parent/child
338
+ """
339
+
340
+ try:
341
+ oldcwd = os.getcwd()
342
+ except FileNotFoundError:
343
+ # Happens if the CWD has been deleted.
344
+ oldcwd = None
345
+
346
+ numcd = re.match(r'(-)(\d+)$',parameter_s)
347
+ # jump in directory history by number
348
+ if numcd:
349
+ nn = int(numcd.group(2))
350
+ try:
351
+ ps = self.shell.user_ns['_dh'][nn]
352
+ except IndexError:
353
+ print('The requested directory does not exist in history.')
354
+ return
355
+ else:
356
+ opts = {}
357
+ elif parameter_s.startswith('--'):
358
+ ps = None
359
+ fallback = None
360
+ pat = parameter_s[2:]
361
+ dh = self.shell.user_ns['_dh']
362
+ # first search only by basename (last component)
363
+ for ent in reversed(dh):
364
+ if pat in os.path.basename(ent) and os.path.isdir(ent):
365
+ ps = ent
366
+ break
367
+
368
+ if fallback is None and pat in ent and os.path.isdir(ent):
369
+ fallback = ent
370
+
371
+ # if we have no last part match, pick the first full path match
372
+ if ps is None:
373
+ ps = fallback
374
+
375
+ if ps is None:
376
+ print("No matching entry in directory history")
377
+ return
378
+ else:
379
+ opts = {}
380
+
381
+
382
+ else:
383
+ opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
384
+ # jump to previous
385
+ if ps == '-':
386
+ try:
387
+ ps = self.shell.user_ns['_dh'][-2]
388
+ except IndexError as e:
389
+ raise UsageError('%cd -: No previous directory to change to.') from e
390
+ # jump to bookmark if needed
391
+ else:
392
+ if not os.path.isdir(ps) or 'b' in opts:
393
+ bkms = self.shell.db.get('bookmarks', {})
394
+
395
+ if ps in bkms:
396
+ target = bkms[ps]
397
+ print('(bookmark:%s) -> %s' % (ps, target))
398
+ ps = target
399
+ else:
400
+ if 'b' in opts:
401
+ raise UsageError("Bookmark '%s' not found. "
402
+ "Use '%%bookmark -l' to see your bookmarks." % ps)
403
+
404
+ # at this point ps should point to the target dir
405
+ if ps:
406
+ try:
407
+ os.chdir(os.path.expanduser(ps))
408
+ if hasattr(self.shell, 'term_title') and self.shell.term_title:
409
+ set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
410
+ except OSError:
411
+ print(sys.exc_info()[1])
412
+ else:
413
+ cwd = pathlib.Path.cwd()
414
+ dhist = self.shell.user_ns['_dh']
415
+ if oldcwd != cwd:
416
+ dhist.append(cwd)
417
+ self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
418
+
419
+ else:
420
+ os.chdir(self.shell.home_dir)
421
+ if hasattr(self.shell, 'term_title') and self.shell.term_title:
422
+ set_term_title(self.shell.term_title_format.format(cwd="~"))
423
+ cwd = pathlib.Path.cwd()
424
+ dhist = self.shell.user_ns['_dh']
425
+
426
+ if oldcwd != cwd:
427
+ dhist.append(cwd)
428
+ self.shell.db["dhist"] = compress_dhist(dhist)[-100:]
429
+ if "q" not in opts and not self.cd_force_quiet and self.shell.user_ns["_dh"]:
430
+ print(self.shell.user_ns["_dh"][-1])
431
+
432
+ @line_magic
433
+ def env(self, parameter_s=''):
434
+ """Get, set, or list environment variables.
435
+
436
+ Usage:\\
437
+
438
+ :``%env``: lists all environment variables/values
439
+ :``%env var``: get value for var
440
+ :``%env var val``: set value for var
441
+ :``%env var=val``: set value for var
442
+ :``%env var=$val``: set value for var, using python expansion if possible
443
+ """
444
+ if parameter_s.strip():
445
+ split = '=' if '=' in parameter_s else ' '
446
+ bits = parameter_s.split(split)
447
+ if len(bits) == 1:
448
+ key = parameter_s.strip()
449
+ if key in os.environ:
450
+ return os.environ[key]
451
+ else:
452
+ err = "Environment does not have key: {0}".format(key)
453
+ raise UsageError(err)
454
+ if len(bits) > 1:
455
+ return self.set_env(parameter_s)
456
+ env = dict(os.environ)
457
+ # hide likely secrets when printing the whole environment
458
+ for key in list(env):
459
+ if any(s in key.lower() for s in ('key', 'token', 'secret')):
460
+ env[key] = '<hidden>'
461
+
462
+ return env
463
+
464
+ @line_magic
465
+ def set_env(self, parameter_s):
466
+ """Set environment variables. Assumptions are that either "val" is a
467
+ name in the user namespace, or val is something that evaluates to a
468
+ string.
469
+
470
+ Usage:\\
471
+ :``%set_env var val``: set value for var
472
+ :``%set_env var=val``: set value for var
473
+ :``%set_env var=$val``: set value for var, using python expansion if possible
474
+ """
475
+ split = '=' if '=' in parameter_s else ' '
476
+ bits = parameter_s.split(split, 1)
477
+ if not parameter_s.strip() or len(bits)<2:
478
+ raise UsageError("usage is 'set_env var=val'")
479
+ var = bits[0].strip()
480
+ val = bits[1].strip()
481
+ if re.match(r'.*\s.*', var):
482
+ # an environment variable with whitespace is almost certainly
483
+ # not what the user intended. what's more likely is the wrong
484
+ # split was chosen, ie for "set_env cmd_args A=B", we chose
485
+ # '=' for the split and should have chosen ' '. to get around
486
+ # this, users should just assign directly to os.environ or use
487
+ # standard magic {var} expansion.
488
+ err = "refusing to set env var with whitespace: '{0}'"
489
+ err = err.format(val)
490
+ raise UsageError(err)
491
+ os.environ[var] = val
492
+ print('env: {0}={1}'.format(var,val))
493
+
494
+ @line_magic
495
+ def pushd(self, parameter_s=''):
496
+ """Place the current dir on stack and change directory.
497
+
498
+ Usage:\\
499
+ %pushd ['dirname']
500
+ """
501
+
502
+ dir_s = self.shell.dir_stack
503
+ tgt = os.path.expanduser(parameter_s)
504
+ cwd = os.getcwd().replace(self.shell.home_dir,'~')
505
+ if tgt:
506
+ self.cd(parameter_s)
507
+ dir_s.insert(0,cwd)
508
+ return self.shell.run_line_magic('dirs', '')
509
+
510
+ @line_magic
511
+ def popd(self, parameter_s=''):
512
+ """Change to directory popped off the top of the stack.
513
+ """
514
+ if not self.shell.dir_stack:
515
+ raise UsageError("%popd on empty stack")
516
+ top = self.shell.dir_stack.pop(0)
517
+ self.cd(top)
518
+ print("popd ->",top)
519
+
520
+ @line_magic
521
+ def dirs(self, parameter_s=''):
522
+ """Return the current directory stack."""
523
+
524
+ return self.shell.dir_stack
525
+
526
+ @line_magic
527
+ def dhist(self, parameter_s=''):
528
+ """Print your history of visited directories.
529
+
530
+ %dhist -> print full history\\
531
+ %dhist n -> print last n entries only\\
532
+ %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
533
+
534
+ This history is automatically maintained by the %cd command, and
535
+ always available as the global list variable _dh. You can use %cd -<n>
536
+ to go to directory number <n>.
537
+
538
+ Note that most of time, you should view directory history by entering
539
+ cd -<TAB>.
540
+
541
+ """
542
+
543
+ dh = self.shell.user_ns['_dh']
544
+ if parameter_s:
545
+ try:
546
+ args = map(int,parameter_s.split())
547
+ except:
548
+ self.arg_err(self.dhist)
549
+ return
550
+ if len(args) == 1:
551
+ ini,fin = max(len(dh)-(args[0]),0),len(dh)
552
+ elif len(args) == 2:
553
+ ini,fin = args
554
+ fin = min(fin, len(dh))
555
+ else:
556
+ self.arg_err(self.dhist)
557
+ return
558
+ else:
559
+ ini,fin = 0,len(dh)
560
+ print('Directory history (kept in _dh)')
561
+ for i in range(ini, fin):
562
+ print("%d: %s" % (i, dh[i]))
563
+
564
+ @skip_doctest
565
+ @line_magic
566
+ def sc(self, parameter_s=''):
567
+ """Shell capture - run shell command and capture output (DEPRECATED use !).
568
+
569
+ DEPRECATED. Suboptimal, retained for backwards compatibility.
570
+
571
+ You should use the form 'var = !command' instead. Example:
572
+
573
+ "%sc -l myfiles = ls ~" should now be written as
574
+
575
+ "myfiles = !ls ~"
576
+
577
+ myfiles.s, myfiles.l and myfiles.n still apply as documented
578
+ below.
579
+
580
+ --
581
+ %sc [options] varname=command
582
+
583
+ IPython will run the given command using commands.getoutput(), and
584
+ will then update the user's interactive namespace with a variable
585
+ called varname, containing the value of the call. Your command can
586
+ contain shell wildcards, pipes, etc.
587
+
588
+ The '=' sign in the syntax is mandatory, and the variable name you
589
+ supply must follow Python's standard conventions for valid names.
590
+
591
+ (A special format without variable name exists for internal use)
592
+
593
+ Options:
594
+
595
+ -l: list output. Split the output on newlines into a list before
596
+ assigning it to the given variable. By default the output is stored
597
+ as a single string.
598
+
599
+ -v: verbose. Print the contents of the variable.
600
+
601
+ In most cases you should not need to split as a list, because the
602
+ returned value is a special type of string which can automatically
603
+ provide its contents either as a list (split on newlines) or as a
604
+ space-separated string. These are convenient, respectively, either
605
+ for sequential processing or to be passed to a shell command.
606
+
607
+ For example::
608
+
609
+ # Capture into variable a
610
+ In [1]: sc a=ls *py
611
+
612
+ # a is a string with embedded newlines
613
+ In [2]: a
614
+ Out[2]: 'setup.py\\nwin32_manual_post_install.py'
615
+
616
+ # which can be seen as a list:
617
+ In [3]: a.l
618
+ Out[3]: ['setup.py', 'win32_manual_post_install.py']
619
+
620
+ # or as a whitespace-separated string:
621
+ In [4]: a.s
622
+ Out[4]: 'setup.py win32_manual_post_install.py'
623
+
624
+ # a.s is useful to pass as a single command line:
625
+ In [5]: !wc -l $a.s
626
+ 146 setup.py
627
+ 130 win32_manual_post_install.py
628
+ 276 total
629
+
630
+ # while the list form is useful to loop over:
631
+ In [6]: for f in a.l:
632
+ ...: !wc -l $f
633
+ ...:
634
+ 146 setup.py
635
+ 130 win32_manual_post_install.py
636
+
637
+ Similarly, the lists returned by the -l option are also special, in
638
+ the sense that you can equally invoke the .s attribute on them to
639
+ automatically get a whitespace-separated string from their contents::
640
+
641
+ In [7]: sc -l b=ls *py
642
+
643
+ In [8]: b
644
+ Out[8]: ['setup.py', 'win32_manual_post_install.py']
645
+
646
+ In [9]: b.s
647
+ Out[9]: 'setup.py win32_manual_post_install.py'
648
+
649
+ In summary, both the lists and strings used for output capture have
650
+ the following special attributes::
651
+
652
+ .l (or .list) : value as list.
653
+ .n (or .nlstr): value as newline-separated string.
654
+ .s (or .spstr): value as space-separated string.
655
+ """
656
+
657
+ opts,args = self.parse_options(parameter_s, 'lv')
658
+ # Try to get a variable name and command to run
659
+ try:
660
+ # the variable name must be obtained from the parse_options
661
+ # output, which uses shlex.split to strip options out.
662
+ var,_ = args.split('=', 1)
663
+ var = var.strip()
664
+ # But the command has to be extracted from the original input
665
+ # parameter_s, not on what parse_options returns, to avoid the
666
+ # quote stripping which shlex.split performs on it.
667
+ _,cmd = parameter_s.split('=', 1)
668
+ except ValueError:
669
+ var,cmd = '',''
670
+ # If all looks ok, proceed
671
+ split = 'l' in opts
672
+ out = self.shell.getoutput(cmd, split=split)
673
+ if 'v' in opts:
674
+ print('%s ==\n%s' % (var, pformat(out)))
675
+ if var:
676
+ self.shell.user_ns.update({var:out})
677
+ else:
678
+ return out
679
+
680
+ @line_cell_magic
681
+ def sx(self, line='', cell=None):
682
+ """Shell execute - run shell command and capture output (!! is short-hand).
683
+
684
+ %sx command
685
+
686
+ IPython will run the given command using commands.getoutput(), and
687
+ return the result formatted as a list (split on '\\n'). Since the
688
+ output is _returned_, it will be stored in ipython's regular output
689
+ cache Out[N] and in the '_N' automatic variables.
690
+
691
+ Notes:
692
+
693
+ 1) If an input line begins with '!!', then %sx is automatically
694
+ invoked. That is, while::
695
+
696
+ !ls
697
+
698
+ causes ipython to simply issue system('ls'), typing::
699
+
700
+ !!ls
701
+
702
+ is a shorthand equivalent to::
703
+
704
+ %sx ls
705
+
706
+ 2) %sx differs from %sc in that %sx automatically splits into a list,
707
+ like '%sc -l'. The reason for this is to make it as easy as possible
708
+ to process line-oriented shell output via further python commands.
709
+ %sc is meant to provide much finer control, but requires more
710
+ typing.
711
+
712
+ 3) Just like %sc -l, this is a list with special attributes:
713
+ ::
714
+
715
+ .l (or .list) : value as list.
716
+ .n (or .nlstr): value as newline-separated string.
717
+ .s (or .spstr): value as whitespace-separated string.
718
+
719
+ This is very useful when trying to use such lists as arguments to
720
+ system commands."""
721
+
722
+ if cell is None:
723
+ # line magic
724
+ return self.shell.getoutput(line)
725
+ else:
726
+ opts,args = self.parse_options(line, '', 'out=')
727
+ output = self.shell.getoutput(cell)
728
+ out_name = opts.get('out', opts.get('o'))
729
+ if out_name:
730
+ self.shell.user_ns[out_name] = output
731
+ else:
732
+ return output
733
+
734
+ system = line_cell_magic('system')(sx)
735
+ bang = cell_magic('!')(sx)
736
+
737
+ @line_magic
738
+ def bookmark(self, parameter_s=''):
739
+ """Manage IPython's bookmark system.
740
+
741
+ %bookmark <name> - set bookmark to current dir
742
+ %bookmark <name> <dir> - set bookmark to <dir>
743
+ %bookmark -l - list all bookmarks
744
+ %bookmark -d <name> - remove bookmark
745
+ %bookmark -r - remove all bookmarks
746
+
747
+ You can later on access a bookmarked folder with::
748
+
749
+ %cd -b <name>
750
+
751
+ or simply '%cd <name>' if there is no directory called <name> AND
752
+ there is such a bookmark defined.
753
+
754
+ Your bookmarks persist through IPython sessions, but they are
755
+ associated with each profile."""
756
+
757
+ opts,args = self.parse_options(parameter_s,'drl',mode='list')
758
+ if len(args) > 2:
759
+ raise UsageError("%bookmark: too many arguments")
760
+
761
+ bkms = self.shell.db.get('bookmarks',{})
762
+
763
+ if 'd' in opts:
764
+ try:
765
+ todel = args[0]
766
+ except IndexError as e:
767
+ raise UsageError(
768
+ "%bookmark -d: must provide a bookmark to delete") from e
769
+ else:
770
+ try:
771
+ del bkms[todel]
772
+ except KeyError as e:
773
+ raise UsageError(
774
+ "%%bookmark -d: Can't delete bookmark '%s'" % todel) from e
775
+
776
+ elif 'r' in opts:
777
+ bkms = {}
778
+ elif 'l' in opts:
779
+ bks = sorted(bkms)
780
+ if bks:
781
+ size = max(map(len, bks))
782
+ else:
783
+ size = 0
784
+ fmt = '%-'+str(size)+'s -> %s'
785
+ print('Current bookmarks:')
786
+ for bk in bks:
787
+ print(fmt % (bk, bkms[bk]))
788
+ else:
789
+ if not args:
790
+ raise UsageError("%bookmark: You must specify the bookmark name")
791
+ elif len(args)==1:
792
+ bkms[args[0]] = os.getcwd()
793
+ elif len(args)==2:
794
+ bkms[args[0]] = args[1]
795
+ self.shell.db['bookmarks'] = bkms
796
+
797
+ @line_magic
798
+ def pycat(self, parameter_s=''):
799
+ """Show a syntax-highlighted file through a pager.
800
+
801
+ This magic is similar to the cat utility, but it will assume the file
802
+ to be Python source and will show it with syntax highlighting.
803
+
804
+ This magic command can either take a local filename, an url,
805
+ an history range (see %history) or a macro as argument.
806
+
807
+ If no parameter is given, prints out history of current session up to
808
+ this point. ::
809
+
810
+ %pycat myscript.py
811
+ %pycat 7-27
812
+ %pycat myMacro
813
+ %pycat http://www.example.com/myscript.py
814
+ """
815
+ try:
816
+ cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
817
+ except (ValueError, IOError):
818
+ print("Error: no such file, variable, URL, history range or macro")
819
+ return
820
+
821
+ page.page(self.shell.pycolorize(source_to_unicode(cont)))
822
+
823
+ @magic_arguments.magic_arguments()
824
+ @magic_arguments.argument(
825
+ '-a', '--append', action='store_true', default=False,
826
+ help='Append contents of the cell to an existing file. '
827
+ 'The file will be created if it does not exist.'
828
+ )
829
+ @magic_arguments.argument(
830
+ 'filename', type=str,
831
+ help='file to write'
832
+ )
833
+ @cell_magic
834
+ def writefile(self, line, cell):
835
+ """Write the contents of the cell to a file.
836
+
837
+ The file will be overwritten unless the -a (--append) flag is specified.
838
+ """
839
+ args = magic_arguments.parse_argstring(self.writefile, line)
840
+ if re.match(r'^(\'.*\')|(".*")$', args.filename):
841
+ filename = os.path.expanduser(args.filename[1:-1])
842
+ else:
843
+ filename = os.path.expanduser(args.filename)
844
+
845
+ if os.path.exists(filename):
846
+ if args.append:
847
+ print("Appending to %s" % filename)
848
+ else:
849
+ print("Overwriting %s" % filename)
850
+ else:
851
+ print("Writing %s" % filename)
852
+
853
+ mode = 'a' if args.append else 'w'
854
+ with io.open(filename, mode, encoding='utf-8') as f:
855
+ f.write(cell)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/packaging.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of packaging-related magic functions.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2018 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ import functools
12
+ import os
13
+ import re
14
+ import shlex
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ from IPython.core.magic import Magics, magics_class, line_magic
19
+
20
+
21
+ def is_conda_environment(func):
22
+ @functools.wraps(func)
23
+ def wrapper(*args, **kwargs):
24
+ """Return True if the current Python executable is in a conda env"""
25
+ # TODO: does this need to change on windows?
26
+ if not Path(sys.prefix, "conda-meta", "history").exists():
27
+ raise ValueError(
28
+ "The python kernel does not appear to be a conda environment. "
29
+ "Please use ``%pip install`` instead."
30
+ )
31
+ return func(*args, **kwargs)
32
+
33
+ return wrapper
34
+
35
+
36
+ def _get_conda_like_executable(command):
37
+ """Find the path to the given executable
38
+
39
+ Parameters
40
+ ----------
41
+
42
+ executable: string
43
+ Value should be: conda, mamba or micromamba
44
+ """
45
+ # Check for a environment variable bound to the base executable, both conda and mamba
46
+ # set these when activating an environment.
47
+ base_executable = "CONDA_EXE"
48
+ if "mamba" in command.lower():
49
+ base_executable = "MAMBA_EXE"
50
+ if base_executable in os.environ:
51
+ executable = Path(os.environ[base_executable])
52
+ if executable.is_file():
53
+ return str(executable.resolve())
54
+
55
+ # Check if there is a conda executable in the same directory as the Python executable.
56
+ # This is the case within conda's root environment.
57
+ executable = Path(sys.executable).parent / command
58
+ if executable.is_file():
59
+ return str(executable)
60
+
61
+ # Otherwise, attempt to extract the executable from conda history.
62
+ # This applies in any conda environment. Parsing this way is error prone because
63
+ # different versions of conda and mamba include differing cmd values such as
64
+ # `conda`, `conda-script.py`, or `path/to/conda`, here use the raw command provided.
65
+ history = Path(sys.prefix, "conda-meta", "history").read_text(encoding="utf-8")
66
+ match = re.search(
67
+ rf"^#\s*cmd:\s*(?P<command>.*{command})\s[create|install]",
68
+ history,
69
+ flags=re.MULTILINE,
70
+ )
71
+ if match:
72
+ return match.groupdict()["command"]
73
+
74
+ # Fallback: assume the executable is available on the system path.
75
+ return command
76
+
77
+
78
+ CONDA_COMMANDS_REQUIRING_PREFIX = {
79
+ 'install', 'list', 'remove', 'uninstall', 'update', 'upgrade',
80
+ }
81
+ CONDA_COMMANDS_REQUIRING_YES = {
82
+ 'install', 'remove', 'uninstall', 'update', 'upgrade',
83
+ }
84
+ CONDA_ENV_FLAGS = {'-p', '--prefix', '-n', '--name'}
85
+ CONDA_YES_FLAGS = {'-y', '--y'}
86
+
87
+
88
+ @magics_class
89
+ class PackagingMagics(Magics):
90
+ """Magics related to packaging & installation"""
91
+
92
+ @line_magic
93
+ def pip(self, line):
94
+ """Run the pip package manager within the current kernel.
95
+
96
+ Usage:
97
+ %pip install [pkgs]
98
+ """
99
+ python = sys.executable
100
+ if sys.platform == "win32":
101
+ python = '"' + python + '"'
102
+ else:
103
+ python = shlex.quote(python)
104
+
105
+ self.shell.system(" ".join([python, "-m", "pip", line]))
106
+
107
+ print("Note: you may need to restart the kernel to use updated packages.")
108
+
109
+ def _run_command(self, cmd, line):
110
+ args = shlex.split(line)
111
+ command = args[0] if len(args) > 0 else ""
112
+ args = args[1:] if len(args) > 1 else [""]
113
+
114
+ extra_args = []
115
+
116
+ # When the subprocess does not allow us to respond "yes" during the installation,
117
+ # we need to insert --yes in the argument list for some commands
118
+ stdin_disabled = getattr(self.shell, 'kernel', None) is not None
119
+ needs_yes = command in CONDA_COMMANDS_REQUIRING_YES
120
+ has_yes = set(args).intersection(CONDA_YES_FLAGS)
121
+ if stdin_disabled and needs_yes and not has_yes:
122
+ extra_args.append("--yes")
123
+
124
+ # Add --prefix to point conda installation to the current environment
125
+ needs_prefix = command in CONDA_COMMANDS_REQUIRING_PREFIX
126
+ has_prefix = set(args).intersection(CONDA_ENV_FLAGS)
127
+ if needs_prefix and not has_prefix:
128
+ extra_args.extend(["--prefix", sys.prefix])
129
+
130
+ self.shell.system(" ".join([cmd, command] + extra_args + args))
131
+ print("\nNote: you may need to restart the kernel to use updated packages.")
132
+
133
+ @line_magic
134
+ @is_conda_environment
135
+ def conda(self, line):
136
+ """Run the conda package manager within the current kernel.
137
+
138
+ Usage:
139
+ %conda install [pkgs]
140
+ """
141
+ conda = _get_conda_like_executable("conda")
142
+ self._run_command(conda, line)
143
+
144
+ @line_magic
145
+ @is_conda_environment
146
+ def mamba(self, line):
147
+ """Run the mamba package manager within the current kernel.
148
+
149
+ Usage:
150
+ %mamba install [pkgs]
151
+ """
152
+ mamba = _get_conda_like_executable("mamba")
153
+ self._run_command(mamba, line)
154
+
155
+ @line_magic
156
+ @is_conda_environment
157
+ def micromamba(self, line):
158
+ """Run the conda package manager within the current kernel.
159
+
160
+ Usage:
161
+ %micromamba install [pkgs]
162
+ """
163
+ micromamba = _get_conda_like_executable("micromamba")
164
+ self._run_command(micromamba, line)
165
+
166
+ @line_magic
167
+ def uv(self, line):
168
+ """Run the uv package manager within the current kernel.
169
+
170
+ Usage:
171
+ %uv pip install [pkgs]
172
+ """
173
+ python = sys.executable
174
+ if sys.platform == "win32":
175
+ python = '"' + python + '"'
176
+ else:
177
+ python = shlex.quote(python)
178
+
179
+ self.shell.system(" ".join([python, "-m", "uv", line]))
180
+
181
+ print("Note: you may need to restart the kernel to use updated packages.")
temp_venv/lib/python3.13/site-packages/IPython/core/magics/pylab.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of magic functions for matplotlib/pylab support.
2
+ """
3
+ #-----------------------------------------------------------------------------
4
+ # Copyright (c) 2012 The IPython Development Team.
5
+ #
6
+ # Distributed under the terms of the Modified BSD License.
7
+ #
8
+ # The full license is in the file COPYING.txt, distributed with this software.
9
+ #-----------------------------------------------------------------------------
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Imports
13
+ #-----------------------------------------------------------------------------
14
+
15
+ # Our own packages
16
+ from traitlets.config.application import Application
17
+ from IPython.core import magic_arguments
18
+ from IPython.core.magic import Magics, magics_class, line_magic
19
+ from IPython.testing.skipdoctest import skip_doctest
20
+ from warnings import warn
21
+
22
+ #-----------------------------------------------------------------------------
23
+ # Magic implementation classes
24
+ #-----------------------------------------------------------------------------
25
+
26
+ magic_gui_arg = magic_arguments.argument(
27
+ "gui",
28
+ nargs="?",
29
+ help="""Name of the matplotlib backend to use such as 'qt' or 'widget'.
30
+ If given, the corresponding matplotlib backend is used,
31
+ otherwise it will be matplotlib's default
32
+ (which you can set in your matplotlib config file).
33
+ """,
34
+ )
35
+
36
+
37
+ @magics_class
38
+ class PylabMagics(Magics):
39
+ """Magics related to matplotlib's pylab support"""
40
+
41
+ @skip_doctest
42
+ @line_magic
43
+ @magic_arguments.magic_arguments()
44
+ @magic_arguments.argument('-l', '--list', action='store_true',
45
+ help='Show available matplotlib backends')
46
+ @magic_gui_arg
47
+ def matplotlib(self, line=''):
48
+ """Set up matplotlib to work interactively.
49
+
50
+ This function lets you activate matplotlib interactive support
51
+ at any point during an IPython session. It does not import anything
52
+ into the interactive namespace.
53
+
54
+ If you are using the inline matplotlib backend in the IPython Notebook
55
+ you can set which figure formats are enabled using the following::
56
+
57
+ In [1]: from matplotlib_inline.backend_inline import set_matplotlib_formats
58
+
59
+ In [2]: set_matplotlib_formats('pdf', 'svg')
60
+
61
+ The default for inline figures sets `bbox_inches` to 'tight'. This can
62
+ cause discrepancies between the displayed image and the identical
63
+ image created using `savefig`. This behavior can be disabled using the
64
+ `%config` magic::
65
+
66
+ In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None}
67
+
68
+ In addition, see the docstrings of
69
+ `matplotlib_inline.backend_inline.set_matplotlib_formats` and
70
+ `matplotlib_inline.backend_inline.set_matplotlib_close` for more information on
71
+ changing additional behaviors of the inline backend.
72
+
73
+ Examples
74
+ --------
75
+ To enable the inline backend for usage with the IPython Notebook::
76
+
77
+ In [1]: %matplotlib inline
78
+
79
+ In this case, where the matplotlib default is TkAgg::
80
+
81
+ In [2]: %matplotlib
82
+ Using matplotlib backend: TkAgg
83
+
84
+ But you can explicitly request a different GUI backend::
85
+
86
+ In [3]: %matplotlib qt
87
+
88
+ You can list the available backends using the -l/--list option::
89
+
90
+ In [4]: %matplotlib --list
91
+ Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'gtk4', 'notebook', 'wx', 'qt', 'nbagg',
92
+ 'gtk', 'tk', 'inline']
93
+ """
94
+ args = magic_arguments.parse_argstring(self.matplotlib, line)
95
+ if args.list:
96
+ from IPython.core.pylabtools import _list_matplotlib_backends_and_gui_loops
97
+
98
+ print(
99
+ "Available matplotlib backends: %s"
100
+ % _list_matplotlib_backends_and_gui_loops()
101
+ )
102
+ else:
103
+ gui, backend = self.shell.enable_matplotlib(args.gui)
104
+ self._show_matplotlib_backend(args.gui, backend)
105
+
106
+ @skip_doctest
107
+ @line_magic
108
+ @magic_arguments.magic_arguments()
109
+ @magic_arguments.argument(
110
+ '--no-import-all', action='store_true', default=None,
111
+ help="""Prevent IPython from performing ``import *`` into the interactive namespace.
112
+
113
+ You can govern the default behavior of this flag with the
114
+ InteractiveShellApp.pylab_import_all configurable.
115
+ """
116
+ )
117
+ @magic_gui_arg
118
+ def pylab(self, line=''):
119
+ """Load numpy and matplotlib to work interactively.
120
+
121
+ This function lets you activate pylab (matplotlib, numpy and
122
+ interactive support) at any point during an IPython session.
123
+
124
+ %pylab makes the following imports::
125
+
126
+ import numpy
127
+ import matplotlib
128
+ from matplotlib import pylab, mlab, pyplot
129
+ np = numpy
130
+ plt = pyplot
131
+
132
+ from IPython.display import display
133
+ from IPython.core.pylabtools import figsize, getfigs
134
+
135
+ from pylab import *
136
+ from numpy import *
137
+
138
+ If you pass `--no-import-all`, the last two `*` imports will be excluded.
139
+
140
+ See the %matplotlib magic for more details about activating matplotlib
141
+ without affecting the interactive namespace.
142
+ """
143
+ args = magic_arguments.parse_argstring(self.pylab, line)
144
+ if args.no_import_all is None:
145
+ # get default from Application
146
+ if Application.initialized():
147
+ app = Application.instance()
148
+ try:
149
+ import_all = app.pylab_import_all
150
+ except AttributeError:
151
+ import_all = True
152
+ else:
153
+ # nothing specified, no app - default True
154
+ import_all = True
155
+ else:
156
+ # invert no-import flag
157
+ import_all = not args.no_import_all
158
+
159
+ gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
160
+ self._show_matplotlib_backend(args.gui, backend)
161
+ print(
162
+ "%pylab is deprecated, use %matplotlib inline and import the required libraries."
163
+ )
164
+ print("Populating the interactive namespace from numpy and matplotlib")
165
+ if clobbered:
166
+ warn("pylab import has clobbered these variables: %s" % clobbered +
167
+ "\n`%matplotlib` prevents importing * from pylab and numpy"
168
+ )
169
+
170
+ def _show_matplotlib_backend(self, gui, backend):
171
+ """show matplotlib message backend message"""
172
+ if not gui or gui == 'auto':
173
+ print("Using matplotlib backend: %s" % backend)
temp_venv/lib/python3.13/site-packages/IPython/core/magics/script.py ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Magic functions for running cells in various scripts."""
2
+
3
+ # Copyright (c) IPython Development Team.
4
+ # Distributed under the terms of the Modified BSD License.
5
+
6
+ import asyncio
7
+ import asyncio.exceptions
8
+ import atexit
9
+ import errno
10
+ import os
11
+ import signal
12
+ import sys
13
+ import time
14
+ from subprocess import CalledProcessError
15
+ from threading import Thread
16
+
17
+ from traitlets import Any, Dict, List, default
18
+
19
+ from IPython.core import magic_arguments
20
+ from IPython.core.async_helpers import _AsyncIOProxy
21
+ from IPython.core.magic import Magics, cell_magic, line_magic, magics_class
22
+ from IPython.utils.process import arg_split
23
+
24
+ #-----------------------------------------------------------------------------
25
+ # Magic implementation classes
26
+ #-----------------------------------------------------------------------------
27
+
28
+ def script_args(f):
29
+ """single decorator for adding script args"""
30
+ args = [
31
+ magic_arguments.argument(
32
+ '--out', type=str,
33
+ help="""The variable in which to store stdout from the script.
34
+ If the script is backgrounded, this will be the stdout *pipe*,
35
+ instead of the stderr text itself and will not be auto closed.
36
+ """
37
+ ),
38
+ magic_arguments.argument(
39
+ '--err', type=str,
40
+ help="""The variable in which to store stderr from the script.
41
+ If the script is backgrounded, this will be the stderr *pipe*,
42
+ instead of the stderr text itself and will not be autoclosed.
43
+ """
44
+ ),
45
+ magic_arguments.argument(
46
+ '--bg', action="store_true",
47
+ help="""Whether to run the script in the background.
48
+ If given, the only way to see the output of the command is
49
+ with --out/err.
50
+ """
51
+ ),
52
+ magic_arguments.argument(
53
+ '--proc', type=str,
54
+ help="""The variable in which to store Popen instance.
55
+ This is used only when --bg option is given.
56
+ """
57
+ ),
58
+ magic_arguments.argument(
59
+ '--no-raise-error', action="store_false", dest='raise_error',
60
+ help="""Whether you should raise an error message in addition to
61
+ a stream on stderr if you get a nonzero exit code.
62
+ """,
63
+ ),
64
+ ]
65
+ for arg in args:
66
+ f = arg(f)
67
+ return f
68
+
69
+
70
+ class RaiseAfterInterrupt(Exception):
71
+ pass
72
+
73
+
74
+ @magics_class
75
+ class ScriptMagics(Magics):
76
+ """Magics for talking to scripts
77
+
78
+ This defines a base `%%script` cell magic for running a cell
79
+ with a program in a subprocess, and registers a few top-level
80
+ magics that call %%script with common interpreters.
81
+ """
82
+
83
+ event_loop = Any(
84
+ help="""
85
+ The event loop on which to run subprocesses
86
+
87
+ Not the main event loop,
88
+ because we want to be able to make blocking calls
89
+ and have certain requirements we don't want to impose on the main loop.
90
+ """
91
+ )
92
+
93
+ script_magics: List = List(
94
+ help="""Extra script cell magics to define
95
+
96
+ This generates simple wrappers of `%%script foo` as `%%foo`.
97
+
98
+ If you want to add script magics that aren't on your path,
99
+ specify them in script_paths
100
+ """,
101
+ ).tag(config=True)
102
+
103
+ @default('script_magics')
104
+ def _script_magics_default(self):
105
+ """default to a common list of programs"""
106
+
107
+ defaults = [
108
+ 'sh',
109
+ 'bash',
110
+ 'perl',
111
+ 'ruby',
112
+ 'python',
113
+ 'python2',
114
+ 'python3',
115
+ 'pypy',
116
+ ]
117
+ if os.name == 'nt':
118
+ defaults.extend([
119
+ 'cmd',
120
+ ])
121
+
122
+ return defaults
123
+
124
+ script_paths = Dict(
125
+ help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
126
+
127
+ Only necessary for items in script_magics where the default path will not
128
+ find the right interpreter.
129
+ """
130
+ ).tag(config=True)
131
+
132
+ def __init__(self, shell=None):
133
+ super(ScriptMagics, self).__init__(shell=shell)
134
+ self._generate_script_magics()
135
+ self.bg_processes = []
136
+ atexit.register(self.kill_bg_processes)
137
+
138
+ def __del__(self):
139
+ self.kill_bg_processes()
140
+
141
+ def _generate_script_magics(self):
142
+ cell_magics = self.magics['cell']
143
+ for name in self.script_magics:
144
+ cell_magics[name] = self._make_script_magic(name)
145
+
146
+ def _make_script_magic(self, name):
147
+ """make a named magic, that calls %%script with a particular program"""
148
+ # expand to explicit path if necessary:
149
+ script = self.script_paths.get(name, name)
150
+
151
+ @magic_arguments.magic_arguments()
152
+ @script_args
153
+ def named_script_magic(line, cell):
154
+ # if line, add it as cl-flags
155
+ if line:
156
+ line = "%s %s" % (script, line)
157
+ else:
158
+ line = script
159
+ return self.shebang(line, cell)
160
+
161
+ # write a basic docstring:
162
+ named_script_magic.__doc__ = \
163
+ """%%{name} script magic
164
+
165
+ Run cells with {script} in a subprocess.
166
+
167
+ This is a shortcut for `%%script {script}`
168
+ """.format(**locals())
169
+
170
+ return named_script_magic
171
+
172
+ @magic_arguments.magic_arguments()
173
+ @script_args
174
+ @cell_magic("script")
175
+ def shebang(self, line, cell):
176
+ """Run a cell via a shell command
177
+
178
+ The `%%script` line is like the #! line of script,
179
+ specifying a program (bash, perl, ruby, etc.) with which to run.
180
+
181
+ The rest of the cell is run by that program.
182
+
183
+ .. versionchanged:: 9.0
184
+ Interrupting the script executed without `--bg` will end in
185
+ raising an exception (unless `--no-raise-error` is passed).
186
+
187
+ Examples
188
+ --------
189
+ ::
190
+
191
+ In [1]: %%script bash
192
+ ...: for i in 1 2 3; do
193
+ ...: echo $i
194
+ ...: done
195
+ 1
196
+ 2
197
+ 3
198
+ """
199
+
200
+ # Create the event loop in which to run script magics
201
+ # this operates on a background thread
202
+ if self.event_loop is None:
203
+ if sys.platform == "win32":
204
+ # don't override the current policy,
205
+ # just create an event loop
206
+ event_loop = asyncio.WindowsProactorEventLoopPolicy().new_event_loop()
207
+ else:
208
+ event_loop = asyncio.new_event_loop()
209
+ self.event_loop = event_loop
210
+
211
+ # start the loop in a background thread
212
+ asyncio_thread = Thread(target=event_loop.run_forever, daemon=True)
213
+ asyncio_thread.start()
214
+ else:
215
+ event_loop = self.event_loop
216
+
217
+ def in_thread(coro):
218
+ """Call a coroutine on the asyncio thread"""
219
+ return asyncio.run_coroutine_threadsafe(coro, event_loop).result()
220
+
221
+ async def _readchunk(stream):
222
+ try:
223
+ return await stream.read(100)
224
+ except asyncio.exceptions.IncompleteReadError as e:
225
+ return e.partial
226
+ except asyncio.exceptions.LimitOverrunError as e:
227
+ return await stream.read(e.consumed)
228
+
229
+ async def _handle_stream(stream, stream_arg, file_object):
230
+ while True:
231
+ chunk = (await _readchunk(stream)).decode("utf8", errors="replace")
232
+ if not chunk:
233
+ break
234
+ if stream_arg:
235
+ self.shell.user_ns[stream_arg] = chunk
236
+ else:
237
+ file_object.write(chunk)
238
+ file_object.flush()
239
+
240
+ async def _stream_communicate(process, cell):
241
+ process.stdin.write(cell)
242
+ process.stdin.close()
243
+ stdout_task = asyncio.create_task(
244
+ _handle_stream(process.stdout, args.out, sys.stdout)
245
+ )
246
+ stderr_task = asyncio.create_task(
247
+ _handle_stream(process.stderr, args.err, sys.stderr)
248
+ )
249
+ await asyncio.wait([stdout_task, stderr_task])
250
+ await process.wait()
251
+
252
+ argv = arg_split(line, posix=not sys.platform.startswith("win"))
253
+ args, cmd = self.shebang.parser.parse_known_args(argv)
254
+
255
+ try:
256
+ p = in_thread(
257
+ asyncio.create_subprocess_exec(
258
+ *cmd,
259
+ stdout=asyncio.subprocess.PIPE,
260
+ stderr=asyncio.subprocess.PIPE,
261
+ stdin=asyncio.subprocess.PIPE,
262
+ )
263
+ )
264
+ except OSError as e:
265
+ if e.errno == errno.ENOENT:
266
+ print("Couldn't find program: %r" % cmd[0])
267
+ return
268
+ else:
269
+ raise
270
+
271
+ if not cell.endswith('\n'):
272
+ cell += '\n'
273
+ cell = cell.encode('utf8', 'replace')
274
+ if args.bg:
275
+ self.bg_processes.append(p)
276
+ self._gc_bg_processes()
277
+ to_close = []
278
+ if args.out:
279
+ self.shell.user_ns[args.out] = _AsyncIOProxy(p.stdout, event_loop)
280
+ else:
281
+ to_close.append(p.stdout)
282
+ if args.err:
283
+ self.shell.user_ns[args.err] = _AsyncIOProxy(p.stderr, event_loop)
284
+ else:
285
+ to_close.append(p.stderr)
286
+ event_loop.call_soon_threadsafe(
287
+ lambda: asyncio.Task(self._run_script(p, cell, to_close))
288
+ )
289
+ if args.proc:
290
+ proc_proxy = _AsyncIOProxy(p, event_loop)
291
+ proc_proxy.stdout = _AsyncIOProxy(p.stdout, event_loop)
292
+ proc_proxy.stderr = _AsyncIOProxy(p.stderr, event_loop)
293
+ self.shell.user_ns[args.proc] = proc_proxy
294
+ return
295
+
296
+ try:
297
+ in_thread(_stream_communicate(p, cell))
298
+ except KeyboardInterrupt:
299
+ try:
300
+ p.send_signal(signal.SIGINT)
301
+ in_thread(asyncio.wait_for(p.wait(), timeout=0.1))
302
+ if p.returncode is not None:
303
+ print("Process was interrupted.")
304
+ if args.raise_error:
305
+ raise RaiseAfterInterrupt()
306
+ else:
307
+ return
308
+ p.terminate()
309
+ in_thread(asyncio.wait_for(p.wait(), timeout=0.1))
310
+ if p.returncode is not None:
311
+ print("Process was terminated.")
312
+ if args.raise_error:
313
+ raise RaiseAfterInterrupt()
314
+ else:
315
+ return
316
+ p.kill()
317
+ print("Process was killed.")
318
+ if args.raise_error:
319
+ raise RaiseAfterInterrupt()
320
+ except RaiseAfterInterrupt:
321
+ pass
322
+ except OSError:
323
+ pass
324
+ except Exception as e:
325
+ print("Error while terminating subprocess (pid=%i): %s" % (p.pid, e))
326
+ if args.raise_error:
327
+ raise CalledProcessError(p.returncode, cell) from None
328
+ else:
329
+ return
330
+
331
+ if args.raise_error and p.returncode != 0:
332
+ # If we get here and p.returncode is still None, we must have
333
+ # killed it but not yet seen its return code. We don't wait for it,
334
+ # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
335
+ rc = p.returncode or -9
336
+ raise CalledProcessError(rc, cell)
337
+
338
+ shebang.__skip_doctest__ = os.name != "posix"
339
+
340
+ async def _run_script(self, p, cell, to_close):
341
+ """callback for running the script in the background"""
342
+
343
+ p.stdin.write(cell)
344
+ await p.stdin.drain()
345
+ p.stdin.close()
346
+ await p.stdin.wait_closed()
347
+ await p.wait()
348
+ # asyncio read pipes have no close
349
+ # but we should drain the data anyway
350
+ for s in to_close:
351
+ await s.read()
352
+ self._gc_bg_processes()
353
+
354
+ @line_magic("killbgscripts")
355
+ def killbgscripts(self, _nouse_=''):
356
+ """Kill all BG processes started by %%script and its family."""
357
+ self.kill_bg_processes()
358
+ print("All background processes were killed.")
359
+
360
+ def kill_bg_processes(self):
361
+ """Kill all BG processes which are still running."""
362
+ if not self.bg_processes:
363
+ return
364
+ for p in self.bg_processes:
365
+ if p.returncode is None:
366
+ try:
367
+ p.send_signal(signal.SIGINT)
368
+ except:
369
+ pass
370
+ time.sleep(0.1)
371
+ self._gc_bg_processes()
372
+ if not self.bg_processes:
373
+ return
374
+ for p in self.bg_processes:
375
+ if p.returncode is None:
376
+ try:
377
+ p.terminate()
378
+ except:
379
+ pass
380
+ time.sleep(0.1)
381
+ self._gc_bg_processes()
382
+ if not self.bg_processes:
383
+ return
384
+ for p in self.bg_processes:
385
+ if p.returncode is None:
386
+ try:
387
+ p.kill()
388
+ except:
389
+ pass
390
+ self._gc_bg_processes()
391
+
392
+ def _gc_bg_processes(self):
393
+ self.bg_processes = [p for p in self.bg_processes if p.returncode is None]
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (204 Bytes). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/debugger.cpython-313.pyc ADDED
Binary file (9.18 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/embed.cpython-313.pyc ADDED
Binary file (17.5 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/interactiveshell.cpython-313.pyc ADDED
Binary file (47.2 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/ipapp.cpython-313.pyc ADDED
Binary file (14.5 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/magics.cpython-313.pyc ADDED
Binary file (9.81 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/prompts.cpython-313.pyc ADDED
Binary file (8.35 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/__pycache__/ptutils.cpython-313.pyc ADDED
Binary file (9.89 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/__init__.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib
2
+ import os
3
+ from typing import Tuple, Callable
4
+
5
+ aliases = {
6
+ 'qt4': 'qt',
7
+ 'gtk2': 'gtk',
8
+ }
9
+
10
+ backends = [
11
+ "qt",
12
+ "qt5",
13
+ "qt6",
14
+ "gtk",
15
+ "gtk2",
16
+ "gtk3",
17
+ "gtk4",
18
+ "tk",
19
+ "wx",
20
+ "pyglet",
21
+ "glut",
22
+ "osx",
23
+ "asyncio",
24
+ ]
25
+
26
+ registered = {}
27
+
28
+ def register(name, inputhook):
29
+ """Register the function *inputhook* as an event loop integration."""
30
+ registered[name] = inputhook
31
+
32
+
33
+ class UnknownBackend(KeyError):
34
+ def __init__(self, name):
35
+ self.name = name
36
+
37
+ def __str__(self):
38
+ return ("No event loop integration for {!r}. "
39
+ "Supported event loops are: {}").format(self.name,
40
+ ', '.join(backends + sorted(registered)))
41
+
42
+
43
+ def set_qt_api(gui):
44
+ """Sets the `QT_API` environment variable if it isn't already set."""
45
+
46
+ qt_api = os.environ.get("QT_API", None)
47
+
48
+ from IPython.external.qt_loaders import (
49
+ QT_API_PYQT,
50
+ QT_API_PYQT5,
51
+ QT_API_PYQT6,
52
+ QT_API_PYSIDE,
53
+ QT_API_PYSIDE2,
54
+ QT_API_PYSIDE6,
55
+ QT_API_PYQTv1,
56
+ loaded_api,
57
+ )
58
+
59
+ loaded = loaded_api()
60
+
61
+ qt_env2gui = {
62
+ QT_API_PYSIDE: "qt4",
63
+ QT_API_PYQTv1: "qt4",
64
+ QT_API_PYQT: "qt4",
65
+ QT_API_PYSIDE2: "qt5",
66
+ QT_API_PYQT5: "qt5",
67
+ QT_API_PYSIDE6: "qt6",
68
+ QT_API_PYQT6: "qt6",
69
+ }
70
+ if loaded is not None and gui != "qt":
71
+ if qt_env2gui[loaded] != gui:
72
+ print(
73
+ f"Cannot switch Qt versions for this session; will use {qt_env2gui[loaded]}."
74
+ )
75
+ return qt_env2gui[loaded]
76
+
77
+ if qt_api is not None and gui != "qt":
78
+ if qt_env2gui[qt_api] != gui:
79
+ print(
80
+ f'Request for "{gui}" will be ignored because `QT_API` '
81
+ f'environment variable is set to "{qt_api}"'
82
+ )
83
+ return qt_env2gui[qt_api]
84
+ else:
85
+ if gui == "qt5":
86
+ try:
87
+ import PyQt5 # noqa
88
+
89
+ os.environ["QT_API"] = "pyqt5"
90
+ except ImportError:
91
+ try:
92
+ import PySide2 # noqa
93
+
94
+ os.environ["QT_API"] = "pyside2"
95
+ except ImportError:
96
+ os.environ["QT_API"] = "pyqt5"
97
+ elif gui == "qt6":
98
+ try:
99
+ import PyQt6 # noqa
100
+
101
+ os.environ["QT_API"] = "pyqt6"
102
+ except ImportError:
103
+ try:
104
+ import PySide6 # noqa
105
+
106
+ os.environ["QT_API"] = "pyside6"
107
+ except ImportError:
108
+ os.environ["QT_API"] = "pyqt6"
109
+ elif gui == "qt":
110
+ # Don't set QT_API; let IPython logic choose the version.
111
+ if "QT_API" in os.environ.keys():
112
+ del os.environ["QT_API"]
113
+ else:
114
+ print(f'Unrecognized Qt version: {gui}. Should be "qt5", "qt6", or "qt".')
115
+ return
116
+
117
+ # Import it now so we can figure out which version it is.
118
+ from IPython.external.qt_for_kernel import QT_API
119
+
120
+ return qt_env2gui[QT_API]
121
+
122
+
123
+ def get_inputhook_name_and_func(gui: str) -> Tuple[str, Callable]:
124
+ if gui in registered:
125
+ return gui, registered[gui]
126
+
127
+ if gui not in backends:
128
+ raise UnknownBackend(gui)
129
+
130
+ if gui in aliases:
131
+ return get_inputhook_name_and_func(aliases[gui])
132
+
133
+ gui_mod = gui
134
+ if gui.startswith("qt"):
135
+ gui = set_qt_api(gui)
136
+ gui_mod = "qt"
137
+
138
+ mod = importlib.import_module("IPython.terminal.pt_inputhooks." + gui_mod)
139
+ return gui, mod.inputhook
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (4.57 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/asyncio.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Inputhook for running the original asyncio event loop while we're waiting for
3
+ input.
4
+
5
+ By default, in IPython, we run the prompt with a different asyncio event loop,
6
+ because otherwise we risk that people are freezing the prompt by scheduling bad
7
+ coroutines. E.g., a coroutine that does a while/true and never yield back
8
+ control to the loop. We can't cancel that.
9
+
10
+ However, sometimes we want the asyncio loop to keep running while waiting for
11
+ a prompt.
12
+
13
+ The following example will print the numbers from 1 to 10 above the prompt,
14
+ while we are waiting for input. (This works also because we use
15
+ prompt_toolkit`s `patch_stdout`)::
16
+
17
+ In [1]: import asyncio
18
+
19
+ In [2]: %gui asyncio
20
+
21
+ In [3]: async def f():
22
+ ...: for i in range(10):
23
+ ...: await asyncio.sleep(1)
24
+ ...: print(i)
25
+
26
+
27
+ In [4]: asyncio.ensure_future(f())
28
+
29
+ """
30
+
31
+
32
+ def inputhook(context):
33
+ """
34
+ Inputhook for asyncio event loop integration.
35
+ """
36
+ # For prompt_toolkit 3.0, this input hook literally doesn't do anything.
37
+ # The event loop integration here is implemented in `interactiveshell.py`
38
+ # by running the prompt itself in the current asyncio loop. The main reason
39
+ # for this is that nesting asyncio event loops is unreliable.
40
+ return
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/glut.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """GLUT Input hook for interactive use with prompt_toolkit
2
+ """
3
+
4
+
5
+ # GLUT is quite an old library and it is difficult to ensure proper
6
+ # integration within IPython since original GLUT does not allow to handle
7
+ # events one by one. Instead, it requires for the mainloop to be entered
8
+ # and never returned (there is not even a function to exit he
9
+ # mainloop). Fortunately, there are alternatives such as freeglut
10
+ # (available for linux and windows) and the OSX implementation gives
11
+ # access to a glutCheckLoop() function that blocks itself until a new
12
+ # event is received. This means we have to setup the idle callback to
13
+ # ensure we got at least one event that will unblock the function.
14
+ #
15
+ # Furthermore, it is not possible to install these handlers without a window
16
+ # being first created. We choose to make this window invisible. This means that
17
+ # display mode options are set at this level and user won't be able to change
18
+ # them later without modifying the code. This should probably be made available
19
+ # via IPython options system.
20
+
21
+ import sys
22
+ import time
23
+ import signal
24
+ import OpenGL.GLUT as glut
25
+ import OpenGL.platform as platform
26
+ from timeit import default_timer as clock
27
+
28
+ # Frame per second : 60
29
+ # Should probably be an IPython option
30
+ glut_fps = 60
31
+
32
+ # Display mode : double buffeed + rgba + depth
33
+ # Should probably be an IPython option
34
+ glut_display_mode = (glut.GLUT_DOUBLE |
35
+ glut.GLUT_RGBA |
36
+ glut.GLUT_DEPTH)
37
+
38
+ glutMainLoopEvent = None
39
+ if sys.platform == 'darwin':
40
+ try:
41
+ glutCheckLoop = platform.createBaseFunction(
42
+ 'glutCheckLoop', dll=platform.GLUT, resultType=None,
43
+ argTypes=[],
44
+ doc='glutCheckLoop( ) -> None',
45
+ argNames=(),
46
+ )
47
+ except AttributeError as e:
48
+ raise RuntimeError(
49
+ '''Your glut implementation does not allow interactive sessions. '''
50
+ '''Consider installing freeglut.''') from e
51
+ glutMainLoopEvent = glutCheckLoop
52
+ elif glut.HAVE_FREEGLUT:
53
+ glutMainLoopEvent = glut.glutMainLoopEvent
54
+ else:
55
+ raise RuntimeError(
56
+ '''Your glut implementation does not allow interactive sessions. '''
57
+ '''Consider installing freeglut.''')
58
+
59
+
60
+ def glut_display():
61
+ # Dummy display function
62
+ pass
63
+
64
+ def glut_idle():
65
+ # Dummy idle function
66
+ pass
67
+
68
+ def glut_close():
69
+ # Close function only hides the current window
70
+ glut.glutHideWindow()
71
+ glutMainLoopEvent()
72
+
73
+ def glut_int_handler(signum, frame):
74
+ # Catch sigint and print the defaultipyt message
75
+ signal.signal(signal.SIGINT, signal.default_int_handler)
76
+ print('\nKeyboardInterrupt')
77
+ # Need to reprint the prompt at this stage
78
+
79
+ # Initialisation code
80
+ glut.glutInit( sys.argv )
81
+ glut.glutInitDisplayMode( glut_display_mode )
82
+ # This is specific to freeglut
83
+ if bool(glut.glutSetOption):
84
+ glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
85
+ glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
86
+ glut.glutCreateWindow( b'ipython' )
87
+ glut.glutReshapeWindow( 1, 1 )
88
+ glut.glutHideWindow( )
89
+ glut.glutWMCloseFunc( glut_close )
90
+ glut.glutDisplayFunc( glut_display )
91
+ glut.glutIdleFunc( glut_idle )
92
+
93
+
94
+ def inputhook(context):
95
+ """Run the pyglet event loop by processing pending events only.
96
+
97
+ This keeps processing pending events until stdin is ready. After
98
+ processing all pending events, a call to time.sleep is inserted. This is
99
+ needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
100
+ though for best performance.
101
+ """
102
+ # We need to protect against a user pressing Control-C when IPython is
103
+ # idle and this is running. We trap KeyboardInterrupt and pass.
104
+
105
+ signal.signal(signal.SIGINT, glut_int_handler)
106
+
107
+ try:
108
+ t = clock()
109
+
110
+ # Make sure the default window is set after a window has been closed
111
+ if glut.glutGetWindow() == 0:
112
+ glut.glutSetWindow( 1 )
113
+ glutMainLoopEvent()
114
+ return 0
115
+
116
+ while not context.input_is_ready():
117
+ glutMainLoopEvent()
118
+ # We need to sleep at this point to keep the idle CPU load
119
+ # low. However, if sleep to long, GUI response is poor. As
120
+ # a compromise, we watch how often GUI events are being processed
121
+ # and switch between a short and long sleep time. Here are some
122
+ # stats useful in helping to tune this.
123
+ # time CPU load
124
+ # 0.001 13%
125
+ # 0.005 3%
126
+ # 0.01 1.5%
127
+ # 0.05 0.5%
128
+ used_time = clock() - t
129
+ if used_time > 10.0:
130
+ # print('Sleep for 1 s') # dbg
131
+ time.sleep(1.0)
132
+ elif used_time > 0.1:
133
+ # Few GUI events coming in, so we can sleep longer
134
+ # print('Sleep for 0.05 s') # dbg
135
+ time.sleep(0.05)
136
+ else:
137
+ # Many GUI events coming in, so sleep only very little
138
+ time.sleep(0.001)
139
+ except KeyboardInterrupt:
140
+ pass
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code borrowed from python-prompt-toolkit examples
2
+ # https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py
3
+
4
+ # Copyright (c) 2014, Jonathan Slenders
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice, this
11
+ # list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright notice, this
14
+ # list of conditions and the following disclaimer in the documentation and/or
15
+ # other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the {organization} nor the names of its
18
+ # contributors may be used to endorse or promote products derived from
19
+ # this software without specific prior written permission.
20
+ #
21
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ """
33
+ PyGTK input hook for prompt_toolkit.
34
+
35
+ Listens on the pipe prompt_toolkit sets up for a notification that it should
36
+ return control to the terminal event loop.
37
+ """
38
+
39
+ import gtk, gobject
40
+
41
+ # Enable threading in GTK. (Otherwise, GTK will keep the GIL.)
42
+ gtk.gdk.threads_init()
43
+
44
+
45
+ def inputhook(context):
46
+ """
47
+ When the eventloop of prompt-toolkit is idle, call this inputhook.
48
+
49
+ This will run the GTK main loop until the file descriptor
50
+ `context.fileno()` becomes ready.
51
+
52
+ :param context: An `InputHookContext` instance.
53
+ """
54
+
55
+ def _main_quit(*a, **kw):
56
+ gtk.main_quit()
57
+ return False
58
+
59
+ gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit)
60
+ gtk.main()
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk3.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """prompt_toolkit input hook for GTK 3"""
2
+
3
+ from gi.repository import Gtk, GLib
4
+
5
+
6
+ def _main_quit(*args, **kwargs):
7
+ Gtk.main_quit()
8
+ return False
9
+
10
+
11
+ def inputhook(context):
12
+ GLib.io_add_watch(context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, _main_quit)
13
+ Gtk.main()
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/gtk4.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ prompt_toolkit input hook for GTK 4.
3
+ """
4
+
5
+ from gi.repository import GLib
6
+
7
+
8
+ class _InputHook:
9
+ def __init__(self, context):
10
+ self._quit = False
11
+ GLib.io_add_watch(
12
+ context.fileno(), GLib.PRIORITY_DEFAULT, GLib.IO_IN, self.quit
13
+ )
14
+
15
+ def quit(self, *args, **kwargs):
16
+ self._quit = True
17
+ return False
18
+
19
+ def run(self):
20
+ context = GLib.MainContext.default()
21
+ while not self._quit:
22
+ context.iteration(True)
23
+
24
+
25
+ def inputhook(context):
26
+ hook = _InputHook(context)
27
+ hook.run()
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/osx.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Inputhook for OS X
2
+
3
+ Calls NSApp / CoreFoundation APIs via ctypes.
4
+ """
5
+
6
+ # obj-c boilerplate from appnope, used under BSD 2-clause
7
+
8
+ import ctypes
9
+ import ctypes.util
10
+ from threading import Event
11
+
12
+ objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc")) # type: ignore
13
+
14
+ void_p = ctypes.c_void_p
15
+
16
+ objc.objc_getClass.restype = void_p
17
+ objc.sel_registerName.restype = void_p
18
+ objc.objc_msgSend.restype = void_p
19
+ objc.objc_msgSend.argtypes = [void_p, void_p]
20
+
21
+ msg = objc.objc_msgSend
22
+
23
+ def _utf8(s):
24
+ """ensure utf8 bytes"""
25
+ if not isinstance(s, bytes):
26
+ s = s.encode('utf8')
27
+ return s
28
+
29
+ def n(name):
30
+ """create a selector name (for ObjC methods)"""
31
+ return objc.sel_registerName(_utf8(name))
32
+
33
+ def C(classname):
34
+ """get an ObjC Class by name"""
35
+ return objc.objc_getClass(_utf8(classname))
36
+
37
+ # end obj-c boilerplate from appnope
38
+
39
+ # CoreFoundation C-API calls we will use:
40
+ CoreFoundation = ctypes.cdll.LoadLibrary(ctypes.util.find_library("CoreFoundation")) # type: ignore
41
+
42
+ CFFileDescriptorCreate = CoreFoundation.CFFileDescriptorCreate
43
+ CFFileDescriptorCreate.restype = void_p
44
+ CFFileDescriptorCreate.argtypes = [void_p, ctypes.c_int, ctypes.c_bool, void_p, void_p]
45
+
46
+ CFFileDescriptorGetNativeDescriptor = CoreFoundation.CFFileDescriptorGetNativeDescriptor
47
+ CFFileDescriptorGetNativeDescriptor.restype = ctypes.c_int
48
+ CFFileDescriptorGetNativeDescriptor.argtypes = [void_p]
49
+
50
+ CFFileDescriptorEnableCallBacks = CoreFoundation.CFFileDescriptorEnableCallBacks
51
+ CFFileDescriptorEnableCallBacks.restype = None
52
+ CFFileDescriptorEnableCallBacks.argtypes = [void_p, ctypes.c_ulong]
53
+
54
+ CFFileDescriptorCreateRunLoopSource = CoreFoundation.CFFileDescriptorCreateRunLoopSource
55
+ CFFileDescriptorCreateRunLoopSource.restype = void_p
56
+ CFFileDescriptorCreateRunLoopSource.argtypes = [void_p, void_p, void_p]
57
+
58
+ CFRunLoopGetCurrent = CoreFoundation.CFRunLoopGetCurrent
59
+ CFRunLoopGetCurrent.restype = void_p
60
+
61
+ CFRunLoopAddSource = CoreFoundation.CFRunLoopAddSource
62
+ CFRunLoopAddSource.restype = None
63
+ CFRunLoopAddSource.argtypes = [void_p, void_p, void_p]
64
+
65
+ CFRelease = CoreFoundation.CFRelease
66
+ CFRelease.restype = None
67
+ CFRelease.argtypes = [void_p]
68
+
69
+ CFFileDescriptorInvalidate = CoreFoundation.CFFileDescriptorInvalidate
70
+ CFFileDescriptorInvalidate.restype = None
71
+ CFFileDescriptorInvalidate.argtypes = [void_p]
72
+
73
+ # From CFFileDescriptor.h
74
+ kCFFileDescriptorReadCallBack = 1
75
+ kCFRunLoopCommonModes = void_p.in_dll(CoreFoundation, 'kCFRunLoopCommonModes')
76
+
77
+
78
+ def _NSApp():
79
+ """Return the global NSApplication instance (NSApp)"""
80
+ objc.objc_msgSend.argtypes = [void_p, void_p]
81
+ return msg(C('NSApplication'), n('sharedApplication'))
82
+
83
+
84
+ def _wake(NSApp):
85
+ """Wake the Application"""
86
+ objc.objc_msgSend.argtypes = [
87
+ void_p,
88
+ void_p,
89
+ void_p,
90
+ void_p,
91
+ void_p,
92
+ void_p,
93
+ void_p,
94
+ void_p,
95
+ void_p,
96
+ void_p,
97
+ void_p,
98
+ ]
99
+ event = msg(
100
+ C("NSEvent"),
101
+ n(
102
+ "otherEventWithType:location:modifierFlags:"
103
+ "timestamp:windowNumber:context:subtype:data1:data2:"
104
+ ),
105
+ 15, # Type
106
+ 0, # location
107
+ 0, # flags
108
+ 0, # timestamp
109
+ 0, # window
110
+ None, # context
111
+ 0, # subtype
112
+ 0, # data1
113
+ 0, # data2
114
+ )
115
+ objc.objc_msgSend.argtypes = [void_p, void_p, void_p, void_p]
116
+ msg(NSApp, n('postEvent:atStart:'), void_p(event), True)
117
+
118
+
119
+ def _input_callback(fdref, flags, info):
120
+ """Callback to fire when there's input to be read"""
121
+ CFFileDescriptorInvalidate(fdref)
122
+ CFRelease(fdref)
123
+ NSApp = _NSApp()
124
+ objc.objc_msgSend.argtypes = [void_p, void_p, void_p]
125
+ msg(NSApp, n('stop:'), NSApp)
126
+ _wake(NSApp)
127
+
128
+ _c_callback_func_type = ctypes.CFUNCTYPE(None, void_p, void_p, void_p)
129
+ _c_input_callback = _c_callback_func_type(_input_callback)
130
+
131
+
132
+ def _stop_on_read(fd):
133
+ """Register callback to stop eventloop when there's data on fd"""
134
+ fdref = CFFileDescriptorCreate(None, fd, False, _c_input_callback, None)
135
+ CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack)
136
+ source = CFFileDescriptorCreateRunLoopSource(None, fdref, 0)
137
+ loop = CFRunLoopGetCurrent()
138
+ CFRunLoopAddSource(loop, source, kCFRunLoopCommonModes)
139
+ CFRelease(source)
140
+
141
+
142
+ def inputhook(context):
143
+ """Inputhook for Cocoa (NSApp)"""
144
+ NSApp = _NSApp()
145
+ _stop_on_read(context.fileno())
146
+ objc.objc_msgSend.argtypes = [void_p, void_p]
147
+ msg(NSApp, n('run'))
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/pyglet.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Enable pyglet to be used interactively with prompt_toolkit"""
2
+
3
+ import sys
4
+ import time
5
+ from timeit import default_timer as clock
6
+ import pyglet
7
+
8
+ # On linux only, window.flip() has a bug that causes an AttributeError on
9
+ # window close. For details, see:
10
+ # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
11
+
12
+ if sys.platform.startswith("linux"):
13
+
14
+ def flip(window):
15
+ try:
16
+ window.flip()
17
+ except AttributeError:
18
+ pass
19
+ else:
20
+
21
+ def flip(window):
22
+ window.flip()
23
+
24
+
25
+ def inputhook(context):
26
+ """Run the pyglet event loop by processing pending events only.
27
+
28
+ This keeps processing pending events until stdin is ready. After
29
+ processing all pending events, a call to time.sleep is inserted. This is
30
+ needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
31
+ though for best performance.
32
+ """
33
+ # We need to protect against a user pressing Control-C when IPython is
34
+ # idle and this is running. We trap KeyboardInterrupt and pass.
35
+ try:
36
+ t = clock()
37
+ while not context.input_is_ready():
38
+ pyglet.clock.tick()
39
+ for window in pyglet.app.windows:
40
+ window.switch_to()
41
+ window.dispatch_events()
42
+ window.dispatch_event("on_draw")
43
+ flip(window)
44
+
45
+ # We need to sleep at this point to keep the idle CPU load
46
+ # low. However, if sleep to long, GUI response is poor. As
47
+ # a compromise, we watch how often GUI events are being processed
48
+ # and switch between a short and long sleep time. Here are some
49
+ # stats useful in helping to tune this.
50
+ # time CPU load
51
+ # 0.001 13%
52
+ # 0.005 3%
53
+ # 0.01 1.5%
54
+ # 0.05 0.5%
55
+ used_time = clock() - t
56
+ if used_time > 10.0:
57
+ # print('Sleep for 1 s') # dbg
58
+ time.sleep(1.0)
59
+ elif used_time > 0.1:
60
+ # Few GUI events coming in, so we can sleep longer
61
+ # print('Sleep for 0.05 s') # dbg
62
+ time.sleep(0.05)
63
+ else:
64
+ # Many GUI events coming in, so sleep only very little
65
+ time.sleep(0.001)
66
+ except KeyboardInterrupt:
67
+ pass
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/qt.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import os
3
+ from IPython.external.qt_for_kernel import QtCore, QtGui, enum_helper
4
+ from IPython import get_ipython
5
+
6
+ # If we create a QApplication, QEventLoop, or a QTimer, keep a reference to them
7
+ # so that they don't get garbage collected or leak memory when created multiple times.
8
+ _appref = None
9
+ _eventloop = None
10
+ _timer = None
11
+ _already_warned = False
12
+
13
+
14
+ def _exec(obj):
15
+ # exec on PyQt6, exec_ elsewhere.
16
+ obj.exec() if hasattr(obj, "exec") else obj.exec_()
17
+
18
+
19
+ def _reclaim_excepthook():
20
+ shell = get_ipython()
21
+ if shell is not None:
22
+ sys.excepthook = shell.excepthook
23
+
24
+
25
+ def inputhook(context):
26
+ global _appref, _eventloop, _timer
27
+ app = QtCore.QCoreApplication.instance()
28
+ if not app:
29
+ if sys.platform == 'linux':
30
+ if not os.environ.get('DISPLAY') \
31
+ and not os.environ.get('WAYLAND_DISPLAY'):
32
+ import warnings
33
+ global _already_warned
34
+ if not _already_warned:
35
+ _already_warned = True
36
+ warnings.warn(
37
+ 'The DISPLAY or WAYLAND_DISPLAY environment variable is '
38
+ 'not set or empty and Qt5 requires this environment '
39
+ 'variable. Deactivate Qt5 code.'
40
+ )
41
+ return
42
+ try:
43
+ QtCore.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
44
+ except AttributeError: # Only for Qt>=5.6, <6.
45
+ pass
46
+ try:
47
+ QtCore.QApplication.setHighDpiScaleFactorRoundingPolicy(
48
+ QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
49
+ )
50
+ except AttributeError: # Only for Qt>=5.14.
51
+ pass
52
+ _appref = app = QtGui.QApplication([" "])
53
+
54
+ # "reclaim" IPython sys.excepthook after event loop starts
55
+ # without this, it defaults back to BaseIPythonApplication.excepthook
56
+ # and exceptions in the Qt event loop are rendered without traceback
57
+ # formatting and look like "bug in IPython".
58
+ QtCore.QTimer.singleShot(0, _reclaim_excepthook)
59
+
60
+ if _eventloop is None:
61
+ _eventloop = QtCore.QEventLoop(app)
62
+
63
+ if sys.platform == 'win32':
64
+ # The QSocketNotifier method doesn't appear to work on Windows.
65
+ # Use polling instead.
66
+ if _timer is None:
67
+ _timer = QtCore.QTimer()
68
+ _timer.timeout.connect(_eventloop.quit)
69
+ while not context.input_is_ready():
70
+ # NOTE: run the event loop, and after 10 ms, call `quit` to exit it.
71
+ _timer.start(10) # 10 ms
72
+ _exec(_eventloop)
73
+ _timer.stop()
74
+ else:
75
+ # On POSIX platforms, we can use a file descriptor to quit the event
76
+ # loop when there is input ready to read.
77
+ notifier = QtCore.QSocketNotifier(
78
+ context.fileno(), enum_helper("QtCore.QSocketNotifier.Type").Read
79
+ )
80
+ try:
81
+ # connect the callback we care about before we turn it on
82
+ # lambda is necessary as PyQT inspect the function signature to know
83
+ # what arguments to pass to. See https://github.com/ipython/ipython/pull/12355
84
+ notifier.activated.connect(lambda: _eventloop.exit())
85
+ notifier.setEnabled(True)
86
+ # only start the event loop we are not already flipped
87
+ if not context.input_is_ready():
88
+ _exec(_eventloop)
89
+ finally:
90
+ notifier.setEnabled(False)
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/tk.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code borrowed from ptpython
2
+ # https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py
3
+
4
+ # Copyright (c) 2015, Jonathan Slenders
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without modification,
8
+ # are permitted provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice, this
11
+ # list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright notice, this
14
+ # list of conditions and the following disclaimer in the documentation and/or
15
+ # other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the {organization} nor the names of its
18
+ # contributors may be used to endorse or promote products derived from
19
+ # this software without specific prior written permission.
20
+ #
21
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ """
33
+ Wrapper around the eventloop that gives some time to the Tkinter GUI to process
34
+ events when it's loaded and while we are waiting for input at the REPL. This
35
+ way we don't block the UI of for instance ``turtle`` and other Tk libraries.
36
+
37
+ (Normally Tkinter registers it's callbacks in ``PyOS_InputHook`` to integrate
38
+ in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
39
+ will fix it for Tk.)
40
+ """
41
+
42
+ import time
43
+
44
+ import _tkinter
45
+ import tkinter
46
+
47
+
48
+ def inputhook(inputhook_context):
49
+ """
50
+ Inputhook for Tk.
51
+ Run the Tk eventloop until prompt-toolkit needs to process the next input.
52
+ """
53
+ # Get the current TK application.
54
+ root = tkinter._default_root
55
+
56
+ def wait_using_filehandler():
57
+ """
58
+ Run the TK eventloop until the file handler that we got from the
59
+ inputhook becomes readable.
60
+ """
61
+ # Add a handler that sets the stop flag when `prompt-toolkit` has input
62
+ # to process.
63
+ stop = [False]
64
+
65
+ def done(*a):
66
+ stop[0] = True
67
+
68
+ root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done)
69
+
70
+ # Run the TK event loop as long as we don't receive input.
71
+ while root.dooneevent(_tkinter.ALL_EVENTS):
72
+ if stop[0]:
73
+ break
74
+
75
+ root.deletefilehandler(inputhook_context.fileno())
76
+
77
+ def wait_using_polling():
78
+ """
79
+ Windows TK doesn't support 'createfilehandler'.
80
+ So, run the TK eventloop and poll until input is ready.
81
+ """
82
+ while not inputhook_context.input_is_ready():
83
+ while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT):
84
+ pass
85
+ # Sleep to make the CPU idle, but not too long, so that the UI
86
+ # stays responsive.
87
+ time.sleep(0.01)
88
+
89
+ if root is not None:
90
+ if hasattr(root, "createfilehandler"):
91
+ wait_using_filehandler()
92
+ else:
93
+ wait_using_polling()
temp_venv/lib/python3.13/site-packages/IPython/terminal/pt_inputhooks/wx.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Enable wxPython to be used interactively in prompt_toolkit
2
+ """
3
+
4
+ import sys
5
+ import signal
6
+ import time
7
+ from timeit import default_timer as clock
8
+ import wx
9
+
10
+
11
+ def ignore_keyboardinterrupts(func):
12
+ """Decorator which causes KeyboardInterrupt exceptions to be ignored during
13
+ execution of the decorated function.
14
+
15
+ This is used by the inputhook functions to handle the event where the user
16
+ presses CTRL+C while IPython is idle, and the inputhook loop is running. In
17
+ this case, we want to ignore interrupts.
18
+ """
19
+ def wrapper(*args, **kwargs):
20
+ try:
21
+ func(*args, **kwargs)
22
+ except KeyboardInterrupt:
23
+ pass
24
+ return wrapper
25
+
26
+
27
+ @ignore_keyboardinterrupts
28
+ def inputhook_wx1(context):
29
+ """Run the wx event loop by processing pending events only.
30
+
31
+ This approach seems to work, but its performance is not great as it
32
+ relies on having PyOS_InputHook called regularly.
33
+ """
34
+ app = wx.GetApp()
35
+ if app is not None:
36
+ assert wx.Thread_IsMain()
37
+
38
+ # Make a temporary event loop and process system events until
39
+ # there are no more waiting, then allow idle events (which
40
+ # will also deal with pending or posted wx events.)
41
+ evtloop = wx.EventLoop()
42
+ ea = wx.EventLoopActivator(evtloop)
43
+ while evtloop.Pending():
44
+ evtloop.Dispatch()
45
+ app.ProcessIdle()
46
+ del ea
47
+ return 0
48
+
49
+
50
+ class EventLoopTimer(wx.Timer):
51
+
52
+ def __init__(self, func):
53
+ self.func = func
54
+ wx.Timer.__init__(self)
55
+
56
+ def Notify(self):
57
+ self.func()
58
+
59
+
60
+ class EventLoopRunner:
61
+
62
+ def Run(self, time, input_is_ready):
63
+ self.input_is_ready = input_is_ready
64
+ self.evtloop = wx.EventLoop()
65
+ self.timer = EventLoopTimer(self.check_stdin)
66
+ self.timer.Start(time)
67
+ self.evtloop.Run()
68
+
69
+ def check_stdin(self):
70
+ if self.input_is_ready():
71
+ self.timer.Stop()
72
+ self.evtloop.Exit()
73
+
74
+
75
+ @ignore_keyboardinterrupts
76
+ def inputhook_wx2(context):
77
+ """Run the wx event loop, polling for stdin.
78
+
79
+ This version runs the wx eventloop for an undetermined amount of time,
80
+ during which it periodically checks to see if anything is ready on
81
+ stdin. If anything is ready on stdin, the event loop exits.
82
+
83
+ The argument to elr.Run controls how often the event loop looks at stdin.
84
+ This determines the responsiveness at the keyboard. A setting of 1000
85
+ enables a user to type at most 1 char per second. I have found that a
86
+ setting of 10 gives good keyboard response. We can shorten it further,
87
+ but eventually performance would suffer from calling select/kbhit too
88
+ often.
89
+ """
90
+ app = wx.GetApp()
91
+ if app is not None:
92
+ assert wx.Thread_IsMain()
93
+ elr = EventLoopRunner()
94
+ # As this time is made shorter, keyboard response improves, but idle
95
+ # CPU load goes up. 10 ms seems like a good compromise.
96
+ elr.Run(time=10, # CHANGE time here to control polling interval
97
+ input_is_ready=context.input_is_ready)
98
+ return 0
99
+
100
+
101
+ @ignore_keyboardinterrupts
102
+ def inputhook_wx3(context):
103
+ """Run the wx event loop by processing pending events only.
104
+
105
+ This is like inputhook_wx1, but it keeps processing pending events
106
+ until stdin is ready. After processing all pending events, a call to
107
+ time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%.
108
+ This sleep time should be tuned though for best performance.
109
+ """
110
+ app = wx.GetApp()
111
+ if app is not None:
112
+ assert wx.Thread_IsMain()
113
+
114
+ # The import of wx on Linux sets the handler for signal.SIGINT
115
+ # to 0. This is a bug in wx or gtk. We fix by just setting it
116
+ # back to the Python default.
117
+ if not callable(signal.getsignal(signal.SIGINT)):
118
+ signal.signal(signal.SIGINT, signal.default_int_handler)
119
+
120
+ evtloop = wx.EventLoop()
121
+ ea = wx.EventLoopActivator(evtloop)
122
+ t = clock()
123
+ while not context.input_is_ready():
124
+ while evtloop.Pending():
125
+ t = clock()
126
+ evtloop.Dispatch()
127
+ app.ProcessIdle()
128
+ # We need to sleep at this point to keep the idle CPU load
129
+ # low. However, if sleep to long, GUI response is poor. As
130
+ # a compromise, we watch how often GUI events are being processed
131
+ # and switch between a short and long sleep time. Here are some
132
+ # stats useful in helping to tune this.
133
+ # time CPU load
134
+ # 0.001 13%
135
+ # 0.005 3%
136
+ # 0.01 1.5%
137
+ # 0.05 0.5%
138
+ used_time = clock() - t
139
+ if used_time > 10.0:
140
+ # print('Sleep for 1 s') # dbg
141
+ time.sleep(1.0)
142
+ elif used_time > 0.1:
143
+ # Few GUI events coming in, so we can sleep longer
144
+ # print('Sleep for 0.05 s') # dbg
145
+ time.sleep(0.05)
146
+ else:
147
+ # Many GUI events coming in, so sleep only very little
148
+ time.sleep(0.001)
149
+ del ea
150
+ return 0
151
+
152
+
153
+ @ignore_keyboardinterrupts
154
+ def inputhook_wxphoenix(context):
155
+ """Run the wx event loop until the user provides more input.
156
+
157
+ This input hook is suitable for use with wxPython >= 4 (a.k.a. Phoenix).
158
+
159
+ It uses the same approach to that used in
160
+ ipykernel.eventloops.loop_wx. The wx.MainLoop is executed, and a wx.Timer
161
+ is used to periodically poll the context for input. As soon as input is
162
+ ready, the wx.MainLoop is stopped.
163
+ """
164
+
165
+ app = wx.GetApp()
166
+
167
+ if app is None:
168
+ return
169
+
170
+ if context.input_is_ready():
171
+ return
172
+
173
+ assert wx.IsMainThread()
174
+
175
+ # Wx uses milliseconds
176
+ poll_interval = 100
177
+
178
+ # Use a wx.Timer to periodically check whether input is ready - as soon as
179
+ # it is, we exit the main loop
180
+ timer = wx.Timer()
181
+
182
+ def poll(ev):
183
+ if context.input_is_ready():
184
+ timer.Stop()
185
+ app.ExitMainLoop()
186
+
187
+ timer.Start(poll_interval)
188
+ timer.Bind(wx.EVT_TIMER, poll)
189
+
190
+ # The import of wx on Linux sets the handler for signal.SIGINT to 0. This
191
+ # is a bug in wx or gtk. We fix by just setting it back to the Python
192
+ # default.
193
+ if not callable(signal.getsignal(signal.SIGINT)):
194
+ signal.signal(signal.SIGINT, signal.default_int_handler)
195
+
196
+ # The SetExitOnFrameDelete call allows us to run the wx mainloop without
197
+ # having a frame open.
198
+ app.SetExitOnFrameDelete(False)
199
+ app.MainLoop()
200
+
201
+
202
+ # Get the major wx version number to figure out what input hook we should use.
203
+ major_version = 3
204
+
205
+ try:
206
+ major_version = int(wx.__version__[0])
207
+ except Exception:
208
+ pass
209
+
210
+ # Use the phoenix hook on all platforms for wxpython >= 4
211
+ if major_version >= 4:
212
+ inputhook = inputhook_wxphoenix
213
+ # On OSX, evtloop.Pending() always returns True, regardless of there being
214
+ # any events pending. As such we can't use implementations 1 or 3 of the
215
+ # inputhook as those depend on a pending/dispatch loop.
216
+ elif sys.platform == 'darwin':
217
+ inputhook = inputhook_wx2
218
+ else:
219
+ inputhook = inputhook_wx3
temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__init__.py ADDED
@@ -0,0 +1,636 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module to define and register Terminal IPython shortcuts with
3
+ :mod:`prompt_toolkit`
4
+ """
5
+
6
+ # Copyright (c) IPython Development Team.
7
+ # Distributed under the terms of the Modified BSD License.
8
+
9
+ import os
10
+ import signal
11
+ import sys
12
+ import warnings
13
+ from dataclasses import dataclass
14
+ from typing import Callable, Any, Optional, List
15
+
16
+ from prompt_toolkit.application.current import get_app
17
+ from prompt_toolkit.key_binding import KeyBindings
18
+ from prompt_toolkit.key_binding.key_processor import KeyPressEvent
19
+ from prompt_toolkit.key_binding.bindings import named_commands as nc
20
+ from prompt_toolkit.key_binding.bindings.completion import (
21
+ display_completions_like_readline,
22
+ )
23
+ from prompt_toolkit.key_binding.vi_state import InputMode, ViState
24
+ from prompt_toolkit.filters import Condition
25
+
26
+ from IPython.core.getipython import get_ipython
27
+ from . import auto_match as match
28
+ from . import auto_suggest
29
+ from .filters import filter_from_string
30
+ from IPython.utils.decorators import undoc
31
+
32
+ from prompt_toolkit.enums import DEFAULT_BUFFER
33
+
34
+ __all__ = ["create_ipython_shortcuts"]
35
+
36
+
37
+ @dataclass
38
+ class BaseBinding:
39
+ command: Callable[[KeyPressEvent], Any]
40
+ keys: List[str]
41
+
42
+
43
+ @dataclass
44
+ class RuntimeBinding(BaseBinding):
45
+ filter: Condition
46
+
47
+
48
+ @dataclass
49
+ class Binding(BaseBinding):
50
+ # while filter could be created by referencing variables directly (rather
51
+ # than created from strings), by using strings we ensure that users will
52
+ # be able to create filters in configuration (e.g. JSON) files too, which
53
+ # also benefits the documentation by enforcing human-readable filter names.
54
+ condition: Optional[str] = None
55
+
56
+ def __post_init__(self):
57
+ if self.condition:
58
+ self.filter = filter_from_string(self.condition)
59
+ else:
60
+ self.filter = None
61
+
62
+
63
+ def create_identifier(handler: Callable):
64
+ parts = handler.__module__.split(".")
65
+ name = handler.__name__
66
+ package = parts[0]
67
+ if len(parts) > 1:
68
+ final_module = parts[-1]
69
+ return f"{package}:{final_module}.{name}"
70
+ else:
71
+ return f"{package}:{name}"
72
+
73
+
74
+ AUTO_MATCH_BINDINGS = [
75
+ *[
76
+ Binding(
77
+ cmd, [key], "focused_insert & auto_match & followed_by_closing_paren_or_end"
78
+ )
79
+ for key, cmd in match.auto_match_parens.items()
80
+ ],
81
+ *[
82
+ # raw string
83
+ Binding(cmd, [key], "focused_insert & auto_match & preceded_by_raw_str_prefix")
84
+ for key, cmd in match.auto_match_parens_raw_string.items()
85
+ ],
86
+ Binding(
87
+ match.double_quote,
88
+ ['"'],
89
+ "focused_insert"
90
+ " & auto_match"
91
+ " & not_inside_unclosed_string"
92
+ " & preceded_by_paired_double_quotes"
93
+ " & followed_by_closing_paren_or_end",
94
+ ),
95
+ Binding(
96
+ match.single_quote,
97
+ ["'"],
98
+ "focused_insert"
99
+ " & auto_match"
100
+ " & not_inside_unclosed_string"
101
+ " & preceded_by_paired_single_quotes"
102
+ " & followed_by_closing_paren_or_end",
103
+ ),
104
+ Binding(
105
+ match.docstring_double_quotes,
106
+ ['"'],
107
+ "focused_insert"
108
+ " & auto_match"
109
+ " & not_inside_unclosed_string"
110
+ " & preceded_by_two_double_quotes",
111
+ ),
112
+ Binding(
113
+ match.docstring_single_quotes,
114
+ ["'"],
115
+ "focused_insert"
116
+ " & auto_match"
117
+ " & not_inside_unclosed_string"
118
+ " & preceded_by_two_single_quotes",
119
+ ),
120
+ Binding(
121
+ match.skip_over,
122
+ [")"],
123
+ "focused_insert & auto_match & followed_by_closing_round_paren",
124
+ ),
125
+ Binding(
126
+ match.skip_over,
127
+ ["]"],
128
+ "focused_insert & auto_match & followed_by_closing_bracket",
129
+ ),
130
+ Binding(
131
+ match.skip_over,
132
+ ["}"],
133
+ "focused_insert & auto_match & followed_by_closing_brace",
134
+ ),
135
+ Binding(
136
+ match.skip_over, ['"'], "focused_insert & auto_match & followed_by_double_quote"
137
+ ),
138
+ Binding(
139
+ match.skip_over, ["'"], "focused_insert & auto_match & followed_by_single_quote"
140
+ ),
141
+ Binding(
142
+ match.delete_pair,
143
+ ["backspace"],
144
+ "focused_insert"
145
+ " & preceded_by_opening_round_paren"
146
+ " & auto_match"
147
+ " & followed_by_closing_round_paren",
148
+ ),
149
+ Binding(
150
+ match.delete_pair,
151
+ ["backspace"],
152
+ "focused_insert"
153
+ " & preceded_by_opening_bracket"
154
+ " & auto_match"
155
+ " & followed_by_closing_bracket",
156
+ ),
157
+ Binding(
158
+ match.delete_pair,
159
+ ["backspace"],
160
+ "focused_insert"
161
+ " & preceded_by_opening_brace"
162
+ " & auto_match"
163
+ " & followed_by_closing_brace",
164
+ ),
165
+ Binding(
166
+ match.delete_pair,
167
+ ["backspace"],
168
+ "focused_insert"
169
+ " & preceded_by_double_quote"
170
+ " & auto_match"
171
+ " & followed_by_double_quote",
172
+ ),
173
+ Binding(
174
+ match.delete_pair,
175
+ ["backspace"],
176
+ "focused_insert"
177
+ " & preceded_by_single_quote"
178
+ " & auto_match"
179
+ " & followed_by_single_quote",
180
+ ),
181
+ ]
182
+
183
+ AUTO_SUGGEST_BINDINGS = [
184
+ # there are two reasons for re-defining bindings defined upstream:
185
+ # 1) prompt-toolkit does not execute autosuggestion bindings in vi mode,
186
+ # 2) prompt-toolkit checks if we are at the end of text, not end of line
187
+ # hence it does not work in multi-line mode of navigable provider
188
+ Binding(
189
+ auto_suggest.accept_or_jump_to_end,
190
+ ["end"],
191
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
192
+ ),
193
+ Binding(
194
+ auto_suggest.accept_or_jump_to_end,
195
+ ["c-e"],
196
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
197
+ ),
198
+ Binding(
199
+ auto_suggest.accept,
200
+ ["c-f"],
201
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
202
+ ),
203
+ Binding(
204
+ auto_suggest.accept,
205
+ ["right"],
206
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode & is_cursor_at_the_end_of_line",
207
+ ),
208
+ Binding(
209
+ auto_suggest.accept_word,
210
+ ["escape", "f"],
211
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
212
+ ),
213
+ Binding(
214
+ auto_suggest.accept_token,
215
+ ["c-right"],
216
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
217
+ ),
218
+ Binding(
219
+ auto_suggest.discard,
220
+ ["escape"],
221
+ # note this one is using `emacs_insert_mode`, not `emacs_like_insert_mode`
222
+ # as in `vi_insert_mode` we do not want `escape` to be shadowed (ever).
223
+ "has_suggestion & default_buffer_focused & emacs_insert_mode",
224
+ ),
225
+ Binding(
226
+ auto_suggest.discard,
227
+ ["delete"],
228
+ "has_suggestion & default_buffer_focused & emacs_insert_mode",
229
+ ),
230
+ Binding(
231
+ auto_suggest.swap_autosuggestion_up,
232
+ ["c-up"],
233
+ "navigable_suggestions"
234
+ " & ~has_line_above"
235
+ " & has_suggestion"
236
+ " & default_buffer_focused",
237
+ ),
238
+ Binding(
239
+ auto_suggest.swap_autosuggestion_down,
240
+ ["c-down"],
241
+ "navigable_suggestions"
242
+ " & ~has_line_below"
243
+ " & has_suggestion"
244
+ " & default_buffer_focused",
245
+ ),
246
+ Binding(
247
+ auto_suggest.up_and_update_hint,
248
+ ["c-up"],
249
+ "has_line_above & navigable_suggestions & default_buffer_focused",
250
+ ),
251
+ Binding(
252
+ auto_suggest.down_and_update_hint,
253
+ ["c-down"],
254
+ "has_line_below & navigable_suggestions & default_buffer_focused",
255
+ ),
256
+ Binding(
257
+ auto_suggest.accept_character,
258
+ ["escape", "right"],
259
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
260
+ ),
261
+ Binding(
262
+ auto_suggest.accept_and_move_cursor_left,
263
+ ["c-left"],
264
+ "has_suggestion & default_buffer_focused & emacs_like_insert_mode",
265
+ ),
266
+ Binding(
267
+ auto_suggest.accept_and_keep_cursor,
268
+ ["escape", "down"],
269
+ "has_suggestion & default_buffer_focused & emacs_insert_mode",
270
+ ),
271
+ Binding(
272
+ auto_suggest.backspace_and_resume_hint,
273
+ ["backspace"],
274
+ # no `has_suggestion` here to allow resuming if no suggestion
275
+ "default_buffer_focused & emacs_like_insert_mode",
276
+ ),
277
+ Binding(
278
+ auto_suggest.resume_hinting,
279
+ ["right"],
280
+ "is_cursor_at_the_end_of_line"
281
+ " & default_buffer_focused"
282
+ " & emacs_like_insert_mode"
283
+ " & pass_through",
284
+ ),
285
+ ]
286
+
287
+
288
+ SIMPLE_CONTROL_BINDINGS = [
289
+ Binding(cmd, [key], "vi_insert_mode & default_buffer_focused & ebivim")
290
+ for key, cmd in {
291
+ "c-a": nc.beginning_of_line,
292
+ "c-b": nc.backward_char,
293
+ "c-k": nc.kill_line,
294
+ "c-w": nc.backward_kill_word,
295
+ "c-y": nc.yank,
296
+ "c-_": nc.undo,
297
+ }.items()
298
+ ]
299
+
300
+
301
+ ALT_AND_COMOBO_CONTROL_BINDINGS = [
302
+ Binding(cmd, list(keys), "vi_insert_mode & default_buffer_focused & ebivim")
303
+ for keys, cmd in {
304
+ # Control Combos
305
+ ("c-x", "c-e"): nc.edit_and_execute,
306
+ ("c-x", "e"): nc.edit_and_execute,
307
+ # Alt
308
+ ("escape", "b"): nc.backward_word,
309
+ ("escape", "c"): nc.capitalize_word,
310
+ ("escape", "d"): nc.kill_word,
311
+ ("escape", "h"): nc.backward_kill_word,
312
+ ("escape", "l"): nc.downcase_word,
313
+ ("escape", "u"): nc.uppercase_word,
314
+ ("escape", "y"): nc.yank_pop,
315
+ ("escape", "."): nc.yank_last_arg,
316
+ }.items()
317
+ ]
318
+
319
+
320
+ def add_binding(bindings: KeyBindings, binding: Binding):
321
+ bindings.add(
322
+ *binding.keys,
323
+ **({"filter": binding.filter} if binding.filter is not None else {}),
324
+ )(binding.command)
325
+
326
+
327
+ def create_ipython_shortcuts(shell, skip=None) -> KeyBindings:
328
+ """Set up the prompt_toolkit keyboard shortcuts for IPython.
329
+
330
+ Parameters
331
+ ----------
332
+ shell: InteractiveShell
333
+ The current IPython shell Instance
334
+ skip: List[Binding]
335
+ Bindings to skip.
336
+
337
+ Returns
338
+ -------
339
+ KeyBindings
340
+ the keybinding instance for prompt toolkit.
341
+
342
+ """
343
+ kb = KeyBindings()
344
+ skip = skip or []
345
+ for binding in KEY_BINDINGS:
346
+ skip_this_one = False
347
+ for to_skip in skip:
348
+ if (
349
+ to_skip.command == binding.command
350
+ and to_skip.filter == binding.filter
351
+ and to_skip.keys == binding.keys
352
+ ):
353
+ skip_this_one = True
354
+ break
355
+ if skip_this_one:
356
+ continue
357
+ add_binding(kb, binding)
358
+
359
+ def get_input_mode(self):
360
+ app = get_app()
361
+ app.ttimeoutlen = shell.ttimeoutlen
362
+ app.timeoutlen = shell.timeoutlen
363
+
364
+ return self._input_mode
365
+
366
+ def set_input_mode(self, mode):
367
+ shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6)
368
+ cursor = "\x1b[{} q".format(shape)
369
+
370
+ sys.stdout.write(cursor)
371
+ sys.stdout.flush()
372
+
373
+ self._input_mode = mode
374
+
375
+ if shell.editing_mode == "vi" and shell.modal_cursor:
376
+ ViState._input_mode = InputMode.INSERT # type: ignore
377
+ ViState.input_mode = property(get_input_mode, set_input_mode) # type: ignore
378
+
379
+ return kb
380
+
381
+
382
+ def reformat_and_execute(event):
383
+ """Reformat code and execute it"""
384
+ shell = get_ipython()
385
+ reformat_text_before_cursor(
386
+ event.current_buffer, event.current_buffer.document, shell
387
+ )
388
+ event.current_buffer.validate_and_handle()
389
+
390
+
391
+ def reformat_text_before_cursor(buffer, document, shell):
392
+ text = buffer.delete_before_cursor(len(document.text[: document.cursor_position]))
393
+ try:
394
+ formatted_text = shell.reformat_handler(text)
395
+ buffer.insert_text(formatted_text)
396
+ except Exception as e:
397
+ buffer.insert_text(text)
398
+
399
+
400
+ def handle_return_or_newline_or_execute(event):
401
+ shell = get_ipython()
402
+ if getattr(shell, "handle_return", None):
403
+ return shell.handle_return(shell)(event)
404
+ else:
405
+ return newline_or_execute_outer(shell)(event)
406
+
407
+
408
+ def newline_or_execute_outer(shell):
409
+ def newline_or_execute(event):
410
+ """When the user presses return, insert a newline or execute the code."""
411
+ b = event.current_buffer
412
+ d = b.document
413
+
414
+ if b.complete_state:
415
+ cc = b.complete_state.current_completion
416
+ if cc:
417
+ b.apply_completion(cc)
418
+ else:
419
+ b.cancel_completion()
420
+ return
421
+
422
+ # If there's only one line, treat it as if the cursor is at the end.
423
+ # See https://github.com/ipython/ipython/issues/10425
424
+ if d.line_count == 1:
425
+ check_text = d.text
426
+ else:
427
+ check_text = d.text[: d.cursor_position]
428
+ status, indent = shell.check_complete(check_text)
429
+
430
+ # if all we have after the cursor is whitespace: reformat current text
431
+ # before cursor
432
+ after_cursor = d.text[d.cursor_position :]
433
+ reformatted = False
434
+ if not after_cursor.strip():
435
+ reformat_text_before_cursor(b, d, shell)
436
+ reformatted = True
437
+ if not (
438
+ d.on_last_line
439
+ or d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
440
+ ):
441
+ if shell.autoindent:
442
+ b.insert_text("\n" + indent)
443
+ else:
444
+ b.insert_text("\n")
445
+ return
446
+
447
+ if (status != "incomplete") and b.accept_handler:
448
+ if not reformatted:
449
+ reformat_text_before_cursor(b, d, shell)
450
+ b.validate_and_handle()
451
+ else:
452
+ if shell.autoindent:
453
+ b.insert_text("\n" + indent)
454
+ else:
455
+ b.insert_text("\n")
456
+
457
+ return newline_or_execute
458
+
459
+
460
+ def previous_history_or_previous_completion(event):
461
+ """
462
+ Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
463
+
464
+ If completer is open this still select previous completion.
465
+ """
466
+ event.current_buffer.auto_up()
467
+
468
+
469
+ def next_history_or_next_completion(event):
470
+ """
471
+ Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
472
+
473
+ If completer is open this still select next completion.
474
+ """
475
+ event.current_buffer.auto_down()
476
+
477
+
478
+ def dismiss_completion(event):
479
+ """Dismiss completion"""
480
+ b = event.current_buffer
481
+ if b.complete_state:
482
+ b.cancel_completion()
483
+
484
+
485
+ def reset_buffer(event):
486
+ """Reset buffer"""
487
+ b = event.current_buffer
488
+ if b.complete_state:
489
+ b.cancel_completion()
490
+ else:
491
+ b.reset()
492
+
493
+
494
+ def reset_search_buffer(event):
495
+ """Reset search buffer"""
496
+ if event.current_buffer.document.text:
497
+ event.current_buffer.reset()
498
+ else:
499
+ event.app.layout.focus(DEFAULT_BUFFER)
500
+
501
+
502
+ def suspend_to_bg(event):
503
+ """Suspend to background"""
504
+ event.app.suspend_to_background()
505
+
506
+
507
+ def quit(event):
508
+ """
509
+ Quit application with ``SIGQUIT`` if supported or ``sys.exit`` otherwise.
510
+
511
+ On platforms that support SIGQUIT, send SIGQUIT to the current process.
512
+ On other platforms, just exit the process with a message.
513
+ """
514
+ sigquit = getattr(signal, "SIGQUIT", None)
515
+ if sigquit is not None:
516
+ os.kill(0, signal.SIGQUIT)
517
+ else:
518
+ sys.exit("Quit")
519
+
520
+
521
+ def indent_buffer(event):
522
+ """Indent buffer"""
523
+ event.current_buffer.insert_text(" " * 4)
524
+
525
+
526
+ def newline_autoindent(event):
527
+ """Insert a newline after the cursor indented appropriately.
528
+
529
+ Fancier version of former ``newline_with_copy_margin`` which should
530
+ compute the correct indentation of the inserted line. That is to say, indent
531
+ by 4 extra space after a function definition, class definition, context
532
+ manager... And dedent by 4 space after ``pass``, ``return``, ``raise ...``.
533
+ """
534
+ shell = get_ipython()
535
+ inputsplitter = shell.input_transformer_manager
536
+ b = event.current_buffer
537
+ d = b.document
538
+
539
+ if b.complete_state:
540
+ b.cancel_completion()
541
+ text = d.text[: d.cursor_position] + "\n"
542
+ _, indent = inputsplitter.check_complete(text)
543
+ b.insert_text("\n" + (" " * (indent or 0)), move_cursor=False)
544
+
545
+
546
+ def open_input_in_editor(event):
547
+ """Open code from input in external editor"""
548
+ event.app.current_buffer.open_in_editor()
549
+
550
+
551
+ if sys.platform == "win32":
552
+ from IPython.core.error import TryNext
553
+ from IPython.lib.clipboard import (
554
+ ClipboardEmpty,
555
+ tkinter_clipboard_get,
556
+ win32_clipboard_get,
557
+ )
558
+
559
+ @undoc
560
+ def win_paste(event):
561
+ try:
562
+ text = win32_clipboard_get()
563
+ except TryNext:
564
+ try:
565
+ text = tkinter_clipboard_get()
566
+ except (TryNext, ClipboardEmpty):
567
+ return
568
+ except ClipboardEmpty:
569
+ return
570
+ event.current_buffer.insert_text(text.replace("\t", " " * 4))
571
+
572
+ else:
573
+
574
+ @undoc
575
+ def win_paste(event):
576
+ """Stub used on other platforms"""
577
+ pass
578
+
579
+
580
+ KEY_BINDINGS = [
581
+ Binding(
582
+ handle_return_or_newline_or_execute,
583
+ ["enter"],
584
+ "default_buffer_focused & ~has_selection & insert_mode",
585
+ ),
586
+ Binding(
587
+ reformat_and_execute,
588
+ ["escape", "enter"],
589
+ "default_buffer_focused & ~has_selection & insert_mode & ebivim",
590
+ ),
591
+ Binding(quit, ["c-\\"]),
592
+ Binding(
593
+ previous_history_or_previous_completion,
594
+ ["c-p"],
595
+ "vi_insert_mode & default_buffer_focused",
596
+ ),
597
+ Binding(
598
+ next_history_or_next_completion,
599
+ ["c-n"],
600
+ "vi_insert_mode & default_buffer_focused",
601
+ ),
602
+ Binding(dismiss_completion, ["c-g"], "default_buffer_focused & has_completions"),
603
+ Binding(reset_buffer, ["c-c"], "default_buffer_focused"),
604
+ Binding(reset_search_buffer, ["c-c"], "search_buffer_focused"),
605
+ Binding(suspend_to_bg, ["c-z"], "supports_suspend"),
606
+ Binding(
607
+ indent_buffer,
608
+ ["tab"], # Ctrl+I == Tab
609
+ "default_buffer_focused & ~has_selection & insert_mode & cursor_in_leading_ws",
610
+ ),
611
+ Binding(newline_autoindent, ["c-o"], "default_buffer_focused & emacs_insert_mode"),
612
+ Binding(open_input_in_editor, ["f2"], "default_buffer_focused"),
613
+ *AUTO_MATCH_BINDINGS,
614
+ *AUTO_SUGGEST_BINDINGS,
615
+ Binding(
616
+ display_completions_like_readline,
617
+ ["c-i"],
618
+ "readline_like_completions"
619
+ " & default_buffer_focused"
620
+ " & ~has_selection"
621
+ " & insert_mode"
622
+ " & ~cursor_in_leading_ws",
623
+ ),
624
+ Binding(win_paste, ["c-v"], "default_buffer_focused & ~vi_mode & is_windows_os"),
625
+ *SIMPLE_CONTROL_BINDINGS,
626
+ *ALT_AND_COMOBO_CONTROL_BINDINGS,
627
+ ]
628
+
629
+ UNASSIGNED_ALLOWED_COMMANDS = [
630
+ auto_suggest.llm_autosuggestion,
631
+ nc.beginning_of_buffer,
632
+ nc.end_of_buffer,
633
+ nc.end_of_line,
634
+ nc.forward_word,
635
+ nc.unix_line_discard,
636
+ ]
temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (22.3 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/auto_match.cpython-313.pyc ADDED
Binary file (4.86 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/auto_suggest.cpython-313.pyc ADDED
Binary file (29.5 kB). View file
 
temp_venv/lib/python3.13/site-packages/IPython/terminal/shortcuts/__pycache__/filters.cpython-313.pyc ADDED
Binary file (13.9 kB). View file