ipython 9.3.0__py3-none-any.whl → 9.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- IPython/core/debugger.py +11 -1
- IPython/core/debugger_backport.py +206 -0
- IPython/core/interactiveshell.py +32 -5
- IPython/core/magics/execution.py +64 -11
- IPython/core/magics/namespace.py +19 -5
- IPython/core/magics/script.py +8 -1
- IPython/core/release.py +1 -1
- IPython/extensions/autoreload.py +165 -6
- IPython/extensions/deduperreload/deduperreload.py +1 -10
- IPython/utils/_sysinfo.py +1 -1
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/METADATA +1 -1
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/RECORD +18 -17
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/WHEEL +1 -1
- {ipython-9.3.0.data → ipython-9.4.0.data}/data/share/man/man1/ipython.1 +0 -0
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/entry_points.txt +0 -0
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/licenses/COPYING.rst +0 -0
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/licenses/LICENSE +0 -0
- {ipython-9.3.0.dist-info → ipython-9.4.0.dist-info}/top_level.txt +0 -0
IPython/core/debugger.py
CHANGED
|
@@ -133,6 +133,7 @@ from contextlib import contextmanager
|
|
|
133
133
|
from functools import lru_cache
|
|
134
134
|
|
|
135
135
|
from IPython import get_ipython
|
|
136
|
+
from IPython.core.debugger_backport import PdbClosureBackport
|
|
136
137
|
from IPython.utils import PyColorize
|
|
137
138
|
from IPython.utils.PyColorize import TokenStream
|
|
138
139
|
|
|
@@ -140,9 +141,18 @@ from typing import TYPE_CHECKING
|
|
|
140
141
|
from types import FrameType
|
|
141
142
|
|
|
142
143
|
# We have to check this directly from sys.argv, config struct not yet available
|
|
143
|
-
from pdb import Pdb as
|
|
144
|
+
from pdb import Pdb as _OldPdb
|
|
144
145
|
from pygments.token import Token
|
|
145
146
|
|
|
147
|
+
|
|
148
|
+
if sys.version_info < (3, 13):
|
|
149
|
+
|
|
150
|
+
class OldPdb(PdbClosureBackport, _OldPdb):
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
else:
|
|
154
|
+
OldPdb = _OldPdb
|
|
155
|
+
|
|
146
156
|
if TYPE_CHECKING:
|
|
147
157
|
# otherwise circular import
|
|
148
158
|
from IPython.core.interactiveshell import InteractiveShell
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The code in this module is a backport of cPython changes in Pdb
|
|
3
|
+
that were introduced in Python 3.13 by gh-83151: Make closure work on pdb
|
|
4
|
+
https://github.com/python/cpython/pull/111094.
|
|
5
|
+
This file should be removed once IPython drops supports for Python 3.12.
|
|
6
|
+
|
|
7
|
+
The only changes are:
|
|
8
|
+
- reformatting by darker (black) formatter
|
|
9
|
+
- addition of type-ignore comments to satisfy mypy
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2001 Python Software Foundation; All Rights Reserved
|
|
12
|
+
|
|
13
|
+
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
|
14
|
+
--------------------------------------------
|
|
15
|
+
|
|
16
|
+
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
|
17
|
+
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
|
18
|
+
otherwise using this software ("Python") in source or binary form and
|
|
19
|
+
its associated documentation.
|
|
20
|
+
|
|
21
|
+
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
|
22
|
+
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
|
23
|
+
analyze, test, perform and/or display publicly, prepare derivative works,
|
|
24
|
+
distribute, and otherwise use Python alone or in any derivative version,
|
|
25
|
+
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
|
26
|
+
i.e., "Copyright (c) 2001 Python Software Foundation; All Rights Reserved"
|
|
27
|
+
are retained in Python alone or in any derivative version prepared by Licensee.
|
|
28
|
+
|
|
29
|
+
3. In the event Licensee prepares a derivative work that is based on
|
|
30
|
+
or incorporates Python or any part thereof, and wants to make
|
|
31
|
+
the derivative work available to others as provided herein, then
|
|
32
|
+
Licensee hereby agrees to include in any such work a brief summary of
|
|
33
|
+
the changes made to Python.
|
|
34
|
+
|
|
35
|
+
4. PSF is making Python available to Licensee on an "AS IS"
|
|
36
|
+
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
|
37
|
+
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
|
38
|
+
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
|
39
|
+
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
|
40
|
+
INFRINGE ANY THIRD PARTY RIGHTS.
|
|
41
|
+
|
|
42
|
+
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
|
43
|
+
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
|
44
|
+
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
|
45
|
+
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
|
46
|
+
|
|
47
|
+
6. This License Agreement will automatically terminate upon a material
|
|
48
|
+
breach of its terms and conditions.
|
|
49
|
+
|
|
50
|
+
7. Nothing in this License Agreement shall be deemed to create any
|
|
51
|
+
relationship of agency, partnership, or joint venture between PSF and
|
|
52
|
+
Licensee. This License Agreement does not grant permission to use PSF
|
|
53
|
+
trademarks or trade name in a trademark sense to endorse or promote
|
|
54
|
+
products or services of Licensee, or any third party.
|
|
55
|
+
|
|
56
|
+
8. By copying, installing or otherwise using Python, Licensee
|
|
57
|
+
agrees to be bound by the terms and conditions of this License
|
|
58
|
+
Agreement.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
import sys
|
|
62
|
+
import types
|
|
63
|
+
import codeop
|
|
64
|
+
import textwrap
|
|
65
|
+
from types import CodeType
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class PdbClosureBackport:
|
|
69
|
+
def _exec_in_closure(self, source, globals, locals): # type: ignore[no-untyped-def]
|
|
70
|
+
"""Run source code in closure so code object created within source
|
|
71
|
+
can find variables in locals correctly
|
|
72
|
+
returns True if the source is executed, False otherwise
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
# Determine if the source should be executed in closure. Only when the
|
|
76
|
+
# source compiled to multiple code objects, we should use this feature.
|
|
77
|
+
# Otherwise, we can just raise an exception and normal exec will be used.
|
|
78
|
+
|
|
79
|
+
code = compile(source, "<string>", "exec")
|
|
80
|
+
if not any(isinstance(const, CodeType) for const in code.co_consts):
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
# locals could be a proxy which does not support pop
|
|
84
|
+
# copy it first to avoid modifying the original locals
|
|
85
|
+
locals_copy = dict(locals)
|
|
86
|
+
|
|
87
|
+
locals_copy["__pdb_eval__"] = {"result": None, "write_back": {}}
|
|
88
|
+
|
|
89
|
+
# If the source is an expression, we need to print its value
|
|
90
|
+
try:
|
|
91
|
+
compile(source, "<string>", "eval")
|
|
92
|
+
except SyntaxError:
|
|
93
|
+
pass
|
|
94
|
+
else:
|
|
95
|
+
source = "__pdb_eval__['result'] = " + source
|
|
96
|
+
|
|
97
|
+
# Add write-back to update the locals
|
|
98
|
+
source = (
|
|
99
|
+
"try:\n"
|
|
100
|
+
+ textwrap.indent(source, " ")
|
|
101
|
+
+ "\n"
|
|
102
|
+
+ "finally:\n"
|
|
103
|
+
+ " __pdb_eval__['write_back'] = locals()"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Build a closure source code with freevars from locals like:
|
|
107
|
+
# def __pdb_outer():
|
|
108
|
+
# var = None
|
|
109
|
+
# def __pdb_scope(): # This is the code object we want to execute
|
|
110
|
+
# nonlocal var
|
|
111
|
+
# <source>
|
|
112
|
+
# return __pdb_scope.__code__
|
|
113
|
+
source_with_closure = (
|
|
114
|
+
"def __pdb_outer():\n"
|
|
115
|
+
+ "\n".join(f" {var} = None" for var in locals_copy)
|
|
116
|
+
+ "\n"
|
|
117
|
+
+ " def __pdb_scope():\n"
|
|
118
|
+
+ "\n".join(f" nonlocal {var}" for var in locals_copy)
|
|
119
|
+
+ "\n"
|
|
120
|
+
+ textwrap.indent(source, " ")
|
|
121
|
+
+ "\n"
|
|
122
|
+
+ " return __pdb_scope.__code__"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Get the code object of __pdb_scope()
|
|
126
|
+
# The exec fills locals_copy with the __pdb_outer() function and we can call
|
|
127
|
+
# that to get the code object of __pdb_scope()
|
|
128
|
+
ns = {}
|
|
129
|
+
try:
|
|
130
|
+
exec(source_with_closure, {}, ns)
|
|
131
|
+
except Exception:
|
|
132
|
+
return False
|
|
133
|
+
code = ns["__pdb_outer"]()
|
|
134
|
+
|
|
135
|
+
cells = tuple(types.CellType(locals_copy.get(var)) for var in code.co_freevars)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
exec(code, globals, locals_copy, closure=cells)
|
|
139
|
+
except Exception:
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
# get the data we need from the statement
|
|
143
|
+
pdb_eval = locals_copy["__pdb_eval__"]
|
|
144
|
+
|
|
145
|
+
# __pdb_eval__ should not be updated back to locals
|
|
146
|
+
pdb_eval["write_back"].pop("__pdb_eval__")
|
|
147
|
+
|
|
148
|
+
# Write all local variables back to locals
|
|
149
|
+
locals.update(pdb_eval["write_back"])
|
|
150
|
+
eval_result = pdb_eval["result"]
|
|
151
|
+
if eval_result is not None:
|
|
152
|
+
print(repr(eval_result))
|
|
153
|
+
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
def default(self, line): # type: ignore[no-untyped-def]
|
|
157
|
+
if line[:1] == "!":
|
|
158
|
+
line = line[1:].strip()
|
|
159
|
+
locals = self.curframe_locals
|
|
160
|
+
globals = self.curframe.f_globals
|
|
161
|
+
try:
|
|
162
|
+
buffer = line
|
|
163
|
+
if (
|
|
164
|
+
code := codeop.compile_command(line + "\n", "<stdin>", "single")
|
|
165
|
+
) is None:
|
|
166
|
+
# Multi-line mode
|
|
167
|
+
with self._disable_command_completion():
|
|
168
|
+
buffer = line
|
|
169
|
+
continue_prompt = "... "
|
|
170
|
+
while (
|
|
171
|
+
code := codeop.compile_command(buffer, "<stdin>", "single")
|
|
172
|
+
) is None:
|
|
173
|
+
if self.use_rawinput:
|
|
174
|
+
try:
|
|
175
|
+
line = input(continue_prompt)
|
|
176
|
+
except (EOFError, KeyboardInterrupt):
|
|
177
|
+
self.lastcmd = ""
|
|
178
|
+
print("\n")
|
|
179
|
+
return
|
|
180
|
+
else:
|
|
181
|
+
self.stdout.write(continue_prompt)
|
|
182
|
+
self.stdout.flush()
|
|
183
|
+
line = self.stdin.readline()
|
|
184
|
+
if not len(line):
|
|
185
|
+
self.lastcmd = ""
|
|
186
|
+
self.stdout.write("\n")
|
|
187
|
+
self.stdout.flush()
|
|
188
|
+
return
|
|
189
|
+
else:
|
|
190
|
+
line = line.rstrip("\r\n")
|
|
191
|
+
buffer += "\n" + line
|
|
192
|
+
save_stdout = sys.stdout
|
|
193
|
+
save_stdin = sys.stdin
|
|
194
|
+
save_displayhook = sys.displayhook
|
|
195
|
+
try:
|
|
196
|
+
sys.stdin = self.stdin
|
|
197
|
+
sys.stdout = self.stdout
|
|
198
|
+
sys.displayhook = self.displayhook
|
|
199
|
+
if not self._exec_in_closure(buffer, globals, locals):
|
|
200
|
+
exec(code, globals, locals)
|
|
201
|
+
finally:
|
|
202
|
+
sys.stdout = save_stdout
|
|
203
|
+
sys.stdin = save_stdin
|
|
204
|
+
sys.displayhook = save_displayhook
|
|
205
|
+
except:
|
|
206
|
+
self._error_exc()
|
IPython/core/interactiveshell.py
CHANGED
|
@@ -252,13 +252,23 @@ class ExecutionInfo:
|
|
|
252
252
|
Stores information about what is going to happen.
|
|
253
253
|
"""
|
|
254
254
|
raw_cell = None
|
|
255
|
+
transformed_cell = None
|
|
255
256
|
store_history = False
|
|
256
257
|
silent = False
|
|
257
258
|
shell_futures = True
|
|
258
259
|
cell_id = None
|
|
259
260
|
|
|
260
|
-
def __init__(
|
|
261
|
+
def __init__(
|
|
262
|
+
self,
|
|
263
|
+
raw_cell,
|
|
264
|
+
store_history,
|
|
265
|
+
silent,
|
|
266
|
+
shell_futures,
|
|
267
|
+
cell_id,
|
|
268
|
+
transformed_cell=None,
|
|
269
|
+
):
|
|
261
270
|
self.raw_cell = raw_cell
|
|
271
|
+
self.transformed_cell = transformed_cell
|
|
262
272
|
self.store_history = store_history
|
|
263
273
|
self.silent = silent
|
|
264
274
|
self.shell_futures = shell_futures
|
|
@@ -269,12 +279,18 @@ class ExecutionInfo:
|
|
|
269
279
|
raw_cell = (
|
|
270
280
|
(self.raw_cell[:50] + "..") if len(self.raw_cell) > 50 else self.raw_cell
|
|
271
281
|
)
|
|
282
|
+
transformed_cell = (
|
|
283
|
+
(self.transformed_cell[:50] + "..")
|
|
284
|
+
if self.transformed_cell and len(self.transformed_cell) > 50
|
|
285
|
+
else self.transformed_cell
|
|
286
|
+
)
|
|
272
287
|
return (
|
|
273
|
-
'<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
|
|
288
|
+
'<%s object at %x, raw_cell="%s" transformed_cell="%s" store_history=%s silent=%s shell_futures=%s cell_id=%s>'
|
|
274
289
|
% (
|
|
275
290
|
name,
|
|
276
291
|
id(self),
|
|
277
292
|
raw_cell,
|
|
293
|
+
transformed_cell,
|
|
278
294
|
self.store_history,
|
|
279
295
|
self.silent,
|
|
280
296
|
self.shell_futures,
|
|
@@ -3156,14 +3172,18 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3156
3172
|
except BaseException as e:
|
|
3157
3173
|
try:
|
|
3158
3174
|
info = ExecutionInfo(
|
|
3159
|
-
raw_cell,
|
|
3175
|
+
raw_cell,
|
|
3176
|
+
store_history,
|
|
3177
|
+
silent,
|
|
3178
|
+
shell_futures,
|
|
3179
|
+
cell_id,
|
|
3180
|
+
transformed_cell=transformed_cell,
|
|
3160
3181
|
)
|
|
3161
3182
|
result = ExecutionResult(info)
|
|
3162
3183
|
result.error_in_exec = e
|
|
3163
3184
|
self.showtraceback(running_compiled_code=True)
|
|
3164
3185
|
except:
|
|
3165
3186
|
pass
|
|
3166
|
-
|
|
3167
3187
|
return result
|
|
3168
3188
|
|
|
3169
3189
|
def should_run_async(
|
|
@@ -3248,7 +3268,14 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3248
3268
|
|
|
3249
3269
|
.. versionadded:: 7.0
|
|
3250
3270
|
"""
|
|
3251
|
-
info = ExecutionInfo(
|
|
3271
|
+
info = ExecutionInfo(
|
|
3272
|
+
raw_cell,
|
|
3273
|
+
store_history,
|
|
3274
|
+
silent,
|
|
3275
|
+
shell_futures,
|
|
3276
|
+
cell_id,
|
|
3277
|
+
transformed_cell=transformed_cell,
|
|
3278
|
+
)
|
|
3252
3279
|
result = ExecutionResult(info)
|
|
3253
3280
|
|
|
3254
3281
|
if (not raw_cell) or raw_cell.isspace():
|
IPython/core/magics/execution.py
CHANGED
|
@@ -20,6 +20,7 @@ import shlex
|
|
|
20
20
|
import sys
|
|
21
21
|
import time
|
|
22
22
|
import timeit
|
|
23
|
+
import signal
|
|
23
24
|
from typing import Dict, Any
|
|
24
25
|
from ast import (
|
|
25
26
|
Assign,
|
|
@@ -1257,8 +1258,15 @@ class ExecutionMagics(Magics):
|
|
|
1257
1258
|
if return_result:
|
|
1258
1259
|
return timeit_result
|
|
1259
1260
|
|
|
1260
|
-
@skip_doctest
|
|
1261
1261
|
@no_var_expand
|
|
1262
|
+
@magic_arguments.magic_arguments()
|
|
1263
|
+
@magic_arguments.argument(
|
|
1264
|
+
"--no-raise-error",
|
|
1265
|
+
action="store_true",
|
|
1266
|
+
dest="no_raise_error",
|
|
1267
|
+
help="If given, don't re-raise exceptions",
|
|
1268
|
+
)
|
|
1269
|
+
@skip_doctest
|
|
1262
1270
|
@needs_local_scope
|
|
1263
1271
|
@line_cell_magic
|
|
1264
1272
|
@output_can_be_silenced
|
|
@@ -1329,9 +1337,34 @@ class ExecutionMagics(Magics):
|
|
|
1329
1337
|
Wall time: 0.00 s
|
|
1330
1338
|
Compiler : 0.78 s
|
|
1331
1339
|
"""
|
|
1332
|
-
|
|
1340
|
+
line_present = False
|
|
1341
|
+
# Try to parse --no-raise-error if present, else ignore unrecognized args
|
|
1342
|
+
try:
|
|
1343
|
+
args = magic_arguments.parse_argstring(self.time, line)
|
|
1344
|
+
except UsageError as e:
|
|
1345
|
+
# Only ignore UsageError if caused by unrecognized arguments
|
|
1346
|
+
# We'll manually check for --no-raise-error and remove it from line
|
|
1347
|
+
line_present = True
|
|
1348
|
+
|
|
1349
|
+
# Check if --no-raise-error is present
|
|
1350
|
+
no_raise_error = "--no-raise-error" in line
|
|
1351
|
+
|
|
1352
|
+
if no_raise_error:
|
|
1353
|
+
# Remove --no-raise-error while preserving the rest of the line structure
|
|
1354
|
+
line = re.sub(r"\s*--no-raise-error\s*", " ", line).strip()
|
|
1355
|
+
# Clean up any double spaces
|
|
1356
|
+
line = re.sub(r"\s+", " ", line)
|
|
1357
|
+
|
|
1358
|
+
class Args:
|
|
1359
|
+
def __init__(self, no_raise_error):
|
|
1360
|
+
self.no_raise_error = no_raise_error
|
|
1361
|
+
|
|
1362
|
+
args = Args(no_raise_error)
|
|
1363
|
+
else:
|
|
1364
|
+
if not hasattr(args, "no_raise_error"):
|
|
1365
|
+
args.no_raise_error = False
|
|
1333
1366
|
|
|
1334
|
-
if
|
|
1367
|
+
if line_present and cell:
|
|
1335
1368
|
raise UsageError("Can't use statement directly after '%%time'!")
|
|
1336
1369
|
|
|
1337
1370
|
if cell:
|
|
@@ -1376,13 +1409,24 @@ class ExecutionMagics(Magics):
|
|
|
1376
1409
|
wtime = time.time
|
|
1377
1410
|
# time execution
|
|
1378
1411
|
wall_st = wtime()
|
|
1412
|
+
# Track whether to propagate exceptions or exit
|
|
1413
|
+
exit_on_interrupt = False
|
|
1414
|
+
interrupt_occured = False
|
|
1415
|
+
captured_exception = None
|
|
1416
|
+
|
|
1379
1417
|
if mode == "eval":
|
|
1380
1418
|
st = clock2()
|
|
1381
1419
|
try:
|
|
1382
1420
|
out = eval(code, glob, local_ns)
|
|
1383
|
-
except
|
|
1384
|
-
|
|
1385
|
-
|
|
1421
|
+
except KeyboardInterrupt as e:
|
|
1422
|
+
captured_exception = e
|
|
1423
|
+
interrupt_occured = True
|
|
1424
|
+
exit_on_interrupt = True
|
|
1425
|
+
except Exception as e:
|
|
1426
|
+
captured_exception = e
|
|
1427
|
+
interrupt_occured = True
|
|
1428
|
+
if not args.no_raise_error:
|
|
1429
|
+
exit_on_interrupt = True
|
|
1386
1430
|
end = clock2()
|
|
1387
1431
|
else:
|
|
1388
1432
|
st = clock2()
|
|
@@ -1393,11 +1437,16 @@ class ExecutionMagics(Magics):
|
|
|
1393
1437
|
if expr_val is not None:
|
|
1394
1438
|
code_2 = self.shell.compile(expr_val, source, 'eval')
|
|
1395
1439
|
out = eval(code_2, glob, local_ns)
|
|
1396
|
-
except
|
|
1397
|
-
|
|
1398
|
-
|
|
1440
|
+
except KeyboardInterrupt as e:
|
|
1441
|
+
captured_exception = e
|
|
1442
|
+
interrupt_occured = True
|
|
1443
|
+
exit_on_interrupt = True
|
|
1444
|
+
except Exception as e:
|
|
1445
|
+
captured_exception = e
|
|
1446
|
+
interrupt_occured = True
|
|
1447
|
+
if not args.no_raise_error:
|
|
1448
|
+
exit_on_interrupt = True
|
|
1399
1449
|
end = clock2()
|
|
1400
|
-
|
|
1401
1450
|
wall_end = wtime()
|
|
1402
1451
|
# Compute actual times and report
|
|
1403
1452
|
wall_time = wall_end - wall_st
|
|
@@ -1416,6 +1465,10 @@ class ExecutionMagics(Magics):
|
|
|
1416
1465
|
print(f"Compiler : {_format_time(tc)}")
|
|
1417
1466
|
if tp > tp_min:
|
|
1418
1467
|
print(f"Parser : {_format_time(tp)}")
|
|
1468
|
+
if interrupt_occured:
|
|
1469
|
+
if exit_on_interrupt and captured_exception:
|
|
1470
|
+
raise captured_exception
|
|
1471
|
+
return
|
|
1419
1472
|
return out
|
|
1420
1473
|
|
|
1421
1474
|
@skip_doctest
|
|
@@ -1514,7 +1567,7 @@ class ExecutionMagics(Magics):
|
|
|
1514
1567
|
default="",
|
|
1515
1568
|
nargs="?",
|
|
1516
1569
|
help="""
|
|
1517
|
-
|
|
1570
|
+
|
|
1518
1571
|
The name of the variable in which to store output.
|
|
1519
1572
|
This is a ``utils.io.CapturedIO`` object with stdout/err attributes
|
|
1520
1573
|
for the text of the captured output.
|
IPython/core/magics/namespace.py
CHANGED
|
@@ -361,6 +361,9 @@ class NamespaceMagics(Magics):
|
|
|
361
361
|
- For numpy arrays, a summary with shape, number of
|
|
362
362
|
elements, typecode and size in memory.
|
|
363
363
|
|
|
364
|
+
- For objects that have shape attribute, primarily dataframe and series like
|
|
365
|
+
objects, will print the shape.
|
|
366
|
+
|
|
364
367
|
- Everything else: a string representation, snipping their middle if
|
|
365
368
|
too long.
|
|
366
369
|
|
|
@@ -372,11 +375,17 @@ class NamespaceMagics(Magics):
|
|
|
372
375
|
|
|
373
376
|
In [2]: beta = 'test'
|
|
374
377
|
|
|
375
|
-
In [3]:
|
|
378
|
+
In [3]: df = pd.DataFrame({"a": range(10), "b": range(10,20)})
|
|
379
|
+
|
|
380
|
+
In [4]: s = df["a"]
|
|
381
|
+
|
|
382
|
+
In [5]: %whos
|
|
376
383
|
Variable Type Data/Info
|
|
377
384
|
--------------------------------
|
|
378
385
|
alpha int 123
|
|
379
386
|
beta str test
|
|
387
|
+
df DataFrame Shape: (10, 2)
|
|
388
|
+
s Series Shape: (10, )
|
|
380
389
|
"""
|
|
381
390
|
|
|
382
391
|
varnames = self.who_ls(parameter_s)
|
|
@@ -441,9 +450,7 @@ class NamespaceMagics(Magics):
|
|
|
441
450
|
Mb = 1048576 # kb**2
|
|
442
451
|
for vname,var,vtype in zip(varnames,varlist,typelist):
|
|
443
452
|
print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
|
|
444
|
-
if vtype
|
|
445
|
-
print("n="+str(len(var)))
|
|
446
|
-
elif vtype == ndarray_type:
|
|
453
|
+
if vtype == ndarray_type:
|
|
447
454
|
vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
|
|
448
455
|
if vtype==ndarray_type:
|
|
449
456
|
# numpy
|
|
@@ -458,7 +465,14 @@ class NamespaceMagics(Magics):
|
|
|
458
465
|
if vbytes < Mb:
|
|
459
466
|
print('(%s kb)' % (vbytes/kb,))
|
|
460
467
|
else:
|
|
461
|
-
print(
|
|
468
|
+
print("(%s Mb)" % (vbytes / Mb,))
|
|
469
|
+
elif hasattr(var, "shape"):
|
|
470
|
+
# Useful for DataFrames and Series
|
|
471
|
+
# Ought to work for both pandas and polars
|
|
472
|
+
print(f"Shape: {var.shape}")
|
|
473
|
+
elif hasattr(var, "__len__"):
|
|
474
|
+
## types that can be used in len function
|
|
475
|
+
print(var if isinstance(var, str) else f"n={len(var)}")
|
|
462
476
|
else:
|
|
463
477
|
try:
|
|
464
478
|
vstr = str(var)
|
IPython/core/magics/script.py
CHANGED
|
@@ -11,6 +11,7 @@ import os
|
|
|
11
11
|
import signal
|
|
12
12
|
import sys
|
|
13
13
|
import time
|
|
14
|
+
from codecs import getincrementaldecoder
|
|
14
15
|
from subprocess import CalledProcessError
|
|
15
16
|
from threading import Thread
|
|
16
17
|
|
|
@@ -227,15 +228,21 @@ class ScriptMagics(Magics):
|
|
|
227
228
|
return await stream.read(e.consumed)
|
|
228
229
|
|
|
229
230
|
async def _handle_stream(stream, stream_arg, file_object):
|
|
231
|
+
should_break = False
|
|
232
|
+
decoder = getincrementaldecoder("utf-8")(errors="replace")
|
|
230
233
|
while True:
|
|
231
|
-
chunk = (await _readchunk(stream))
|
|
234
|
+
chunk = decoder.decode(await _readchunk(stream))
|
|
232
235
|
if not chunk:
|
|
233
236
|
break
|
|
237
|
+
chunk = decoder.decode("", final=True)
|
|
238
|
+
should_break = True
|
|
234
239
|
if stream_arg:
|
|
235
240
|
self.shell.user_ns[stream_arg] = chunk
|
|
236
241
|
else:
|
|
237
242
|
file_object.write(chunk)
|
|
238
243
|
file_object.flush()
|
|
244
|
+
if should_break:
|
|
245
|
+
break
|
|
239
246
|
|
|
240
247
|
async def _stream_communicate(process, cell):
|
|
241
248
|
process.stdin.write(cell)
|
IPython/core/release.py
CHANGED
IPython/extensions/autoreload.py
CHANGED
|
@@ -73,6 +73,30 @@ The following magic commands are provided:
|
|
|
73
73
|
|
|
74
74
|
Mark module 'foo' to not be autoreloaded.
|
|
75
75
|
|
|
76
|
+
Import Conflict Resolution
|
|
77
|
+
==========================
|
|
78
|
+
|
|
79
|
+
In ``%autoreload 3`` mode, the extension tracks ``from X import Y`` style imports
|
|
80
|
+
and intelligently resolves conflicts when the same name is imported multiple ways.
|
|
81
|
+
|
|
82
|
+
Import tracking occurs after successful code execution, ensuring that only valid
|
|
83
|
+
imports are tracked. This approach handles edge cases such as:
|
|
84
|
+
|
|
85
|
+
- Importing a name that doesn't initially exist in a module, then adding that name
|
|
86
|
+
to the module and importing it again
|
|
87
|
+
- Conflicts between aliased imports (``from X import Y as Z``) and direct imports
|
|
88
|
+
(``from X import Z``)
|
|
89
|
+
|
|
90
|
+
When conflicts occur:
|
|
91
|
+
|
|
92
|
+
- If you first do ``from X import Y as Z`` then later ``from X import Z``,
|
|
93
|
+
the extension will switch to reloading ``Z`` instead of ``Y`` under the name ``Z``.
|
|
94
|
+
|
|
95
|
+
- Similarly, if you first do ``from X import Z`` then later ``from X import Y as Z``,
|
|
96
|
+
the extension will switch to reloading ``Y`` as ``Z`` instead of the original ``Z``.
|
|
97
|
+
|
|
98
|
+
- The most recent successful import always takes precedence in conflict resolution.
|
|
99
|
+
|
|
76
100
|
Caveats
|
|
77
101
|
=======
|
|
78
102
|
|
|
@@ -127,6 +151,7 @@ __skip_doctest__ = True
|
|
|
127
151
|
# Imports
|
|
128
152
|
# -----------------------------------------------------------------------------
|
|
129
153
|
|
|
154
|
+
import ast
|
|
130
155
|
import os
|
|
131
156
|
import sys
|
|
132
157
|
import traceback
|
|
@@ -171,6 +196,9 @@ class ModuleReloader:
|
|
|
171
196
|
# Deduper reloader
|
|
172
197
|
self.deduper_reloader = DeduperReloader()
|
|
173
198
|
|
|
199
|
+
# Persistent import tracker for from-imports
|
|
200
|
+
self.import_from_tracker = ImportFromTracker({}, {})
|
|
201
|
+
|
|
174
202
|
# Cache module modification times
|
|
175
203
|
self.check(check_all=True, do_reload=False)
|
|
176
204
|
|
|
@@ -193,6 +221,10 @@ class ModuleReloader:
|
|
|
193
221
|
pass
|
|
194
222
|
self.modules[module_name] = True
|
|
195
223
|
|
|
224
|
+
def clear_import_tracker(self):
|
|
225
|
+
"""Clear the persistent import tracker state"""
|
|
226
|
+
self.import_from_tracker = ImportFromTracker({}, {})
|
|
227
|
+
|
|
196
228
|
def aimport_module(self, module_name):
|
|
197
229
|
"""Import a module, and mark it reloadable
|
|
198
230
|
|
|
@@ -237,7 +269,7 @@ class ModuleReloader:
|
|
|
237
269
|
|
|
238
270
|
return py_filename, pymtime
|
|
239
271
|
|
|
240
|
-
def check(self, check_all=False, do_reload=True):
|
|
272
|
+
def check(self, check_all=False, do_reload=True, execution_info=None):
|
|
241
273
|
"""Check whether some modules need to be reloaded."""
|
|
242
274
|
|
|
243
275
|
if not self.enabled and not check_all:
|
|
@@ -248,6 +280,10 @@ class ModuleReloader:
|
|
|
248
280
|
else:
|
|
249
281
|
modules = list(self.modules.keys())
|
|
250
282
|
|
|
283
|
+
# Use the persistent import_from_tracker
|
|
284
|
+
import_from_tracker = (
|
|
285
|
+
self.import_from_tracker if self.import_from_tracker.imports_froms else None
|
|
286
|
+
)
|
|
251
287
|
for modname in modules:
|
|
252
288
|
m = sys.modules.get(modname, None)
|
|
253
289
|
|
|
@@ -275,7 +311,13 @@ class ModuleReloader:
|
|
|
275
311
|
self._report(f"Reloading '{modname}'.")
|
|
276
312
|
try:
|
|
277
313
|
if self.autoload_obj:
|
|
278
|
-
superreload(
|
|
314
|
+
superreload(
|
|
315
|
+
m,
|
|
316
|
+
reload,
|
|
317
|
+
self.old_objects,
|
|
318
|
+
self.shell,
|
|
319
|
+
import_from_tracker=import_from_tracker,
|
|
320
|
+
)
|
|
279
321
|
# if not using autoload, check if deduperreload is viable for this module
|
|
280
322
|
elif self.deduper_reloader.maybe_reload_module(m):
|
|
281
323
|
pass
|
|
@@ -427,6 +469,59 @@ mod_attrs = [
|
|
|
427
469
|
]
|
|
428
470
|
|
|
429
471
|
|
|
472
|
+
class ImportFromTracker:
|
|
473
|
+
def __init__(self, imports_froms: dict, symbol_map: dict):
|
|
474
|
+
self.imports_froms = imports_froms
|
|
475
|
+
# symbol_map maps original_name -> list of resolved_names
|
|
476
|
+
self.symbol_map = {}
|
|
477
|
+
if symbol_map:
|
|
478
|
+
for module_name, mappings in symbol_map.items():
|
|
479
|
+
self.symbol_map[module_name] = {}
|
|
480
|
+
for original_name, resolved_names in mappings.items():
|
|
481
|
+
if isinstance(resolved_names, list):
|
|
482
|
+
self.symbol_map[module_name][original_name] = resolved_names[:]
|
|
483
|
+
else:
|
|
484
|
+
self.symbol_map[module_name][original_name] = [resolved_names]
|
|
485
|
+
else:
|
|
486
|
+
self.symbol_map = symbol_map or {}
|
|
487
|
+
|
|
488
|
+
def add_import(
|
|
489
|
+
self, module_name: str, original_name: str, resolved_name: str
|
|
490
|
+
) -> None:
|
|
491
|
+
"""Add an import, handling conflicts with existing imports.
|
|
492
|
+
|
|
493
|
+
This method is called after successful code execution, so we know the import is valid.
|
|
494
|
+
"""
|
|
495
|
+
if module_name not in self.imports_froms:
|
|
496
|
+
self.imports_froms[module_name] = []
|
|
497
|
+
if module_name not in self.symbol_map:
|
|
498
|
+
self.symbol_map[module_name] = {}
|
|
499
|
+
|
|
500
|
+
# Check if there's already a different mapping for the same resolved_name from a different original_name
|
|
501
|
+
# We need to remove any conflicting mappings
|
|
502
|
+
for orig_name, res_names in list(self.symbol_map[module_name].items()):
|
|
503
|
+
if resolved_name in res_names and orig_name != original_name:
|
|
504
|
+
# Remove the conflicting resolved_name from the other original_name's list
|
|
505
|
+
res_names.remove(resolved_name)
|
|
506
|
+
if (
|
|
507
|
+
not res_names
|
|
508
|
+
): # If the list is now empty, remove the original_name entirely
|
|
509
|
+
if orig_name in self.imports_froms[module_name]:
|
|
510
|
+
self.imports_froms[module_name].remove(orig_name)
|
|
511
|
+
del self.symbol_map[module_name][orig_name]
|
|
512
|
+
|
|
513
|
+
# Add the new mapping
|
|
514
|
+
if original_name not in self.imports_froms[module_name]:
|
|
515
|
+
self.imports_froms[module_name].append(original_name)
|
|
516
|
+
|
|
517
|
+
if original_name not in self.symbol_map[module_name]:
|
|
518
|
+
self.symbol_map[module_name][original_name] = []
|
|
519
|
+
|
|
520
|
+
# Add the resolved_name if it's not already in the list
|
|
521
|
+
if resolved_name not in self.symbol_map[module_name][original_name]:
|
|
522
|
+
self.symbol_map[module_name][original_name].append(resolved_name)
|
|
523
|
+
|
|
524
|
+
|
|
430
525
|
def append_obj(module, d, name, obj, autoload=False):
|
|
431
526
|
in_module = hasattr(obj, "__module__") and obj.__module__ == module.__name__
|
|
432
527
|
if autoload:
|
|
@@ -445,7 +540,9 @@ def append_obj(module, d, name, obj, autoload=False):
|
|
|
445
540
|
return True
|
|
446
541
|
|
|
447
542
|
|
|
448
|
-
def superreload(
|
|
543
|
+
def superreload(
|
|
544
|
+
module, reload=reload, old_objects=None, shell=None, import_from_tracker=None
|
|
545
|
+
):
|
|
449
546
|
"""Enhanced version of the builtin reload function.
|
|
450
547
|
|
|
451
548
|
superreload remembers objects previously in the module, and
|
|
@@ -486,18 +583,34 @@ def superreload(module, reload=reload, old_objects=None, shell=None):
|
|
|
486
583
|
module.__dict__.update(old_dict)
|
|
487
584
|
raise
|
|
488
585
|
|
|
489
|
-
# iterate over all objects and update functions & classes
|
|
490
586
|
for name, new_obj in list(module.__dict__.items()):
|
|
491
587
|
key = (module.__name__, name)
|
|
492
588
|
if key not in old_objects:
|
|
493
589
|
# here 'shell' acts both as a flag and as an output var
|
|
590
|
+
imports_froms = (
|
|
591
|
+
import_from_tracker.imports_froms if import_from_tracker else None
|
|
592
|
+
)
|
|
593
|
+
symbol_map = import_from_tracker.symbol_map if import_from_tracker else None
|
|
494
594
|
if (
|
|
495
595
|
shell is None
|
|
496
596
|
or name == "Enum"
|
|
497
597
|
or not append_obj(module, old_objects, name, new_obj, True)
|
|
598
|
+
or (
|
|
599
|
+
imports_froms
|
|
600
|
+
and module.__name__ in imports_froms
|
|
601
|
+
and "*" not in imports_froms[module.__name__]
|
|
602
|
+
and name not in imports_froms[module.__name__]
|
|
603
|
+
)
|
|
498
604
|
):
|
|
499
605
|
continue
|
|
500
|
-
|
|
606
|
+
|
|
607
|
+
# Handle symbol mapping - now supporting multiple resolved names per original name
|
|
608
|
+
if symbol_map and name in symbol_map.get(module.__name__, {}):
|
|
609
|
+
resolved_names = symbol_map.get(module.__name__, {})[name]
|
|
610
|
+
for resolved_name in resolved_names:
|
|
611
|
+
shell.user_ns[resolved_name] = new_obj
|
|
612
|
+
else:
|
|
613
|
+
shell.user_ns[name] = new_obj
|
|
501
614
|
|
|
502
615
|
new_refs = []
|
|
503
616
|
for old_ref in old_objects[key]:
|
|
@@ -727,6 +840,9 @@ class AutoreloadMagics(Magics):
|
|
|
727
840
|
self.shell.push({top_name: top_module})
|
|
728
841
|
|
|
729
842
|
def pre_run_cell(self, info):
|
|
843
|
+
# Store the execution info for later use in post_execute_hook
|
|
844
|
+
self._last_execution_info = info
|
|
845
|
+
|
|
730
846
|
if self._reloader.enabled:
|
|
731
847
|
try:
|
|
732
848
|
self._reloader.check()
|
|
@@ -734,7 +850,20 @@ class AutoreloadMagics(Magics):
|
|
|
734
850
|
pass
|
|
735
851
|
|
|
736
852
|
def post_execute_hook(self):
|
|
737
|
-
"""Cache the modification times of any modules imported in this execution"""
|
|
853
|
+
"""Cache the modification times of any modules imported in this execution and track imports"""
|
|
854
|
+
|
|
855
|
+
# Track imports from the recently executed code if autoreload 3 is enabled
|
|
856
|
+
if self._reloader.enabled and self._reloader.autoload_obj:
|
|
857
|
+
# Use the stored execution info
|
|
858
|
+
if (
|
|
859
|
+
hasattr(self, "_last_execution_info")
|
|
860
|
+
and self._last_execution_info
|
|
861
|
+
and self._last_execution_info.transformed_cell
|
|
862
|
+
):
|
|
863
|
+
self._track_imports_from_code(
|
|
864
|
+
self._last_execution_info.transformed_cell
|
|
865
|
+
)
|
|
866
|
+
|
|
738
867
|
newly_loaded_modules = set(sys.modules) - self.loaded_modules
|
|
739
868
|
for modname in newly_loaded_modules:
|
|
740
869
|
_, pymtime = self._reloader.filename_and_mtime(sys.modules[modname])
|
|
@@ -743,6 +872,36 @@ class AutoreloadMagics(Magics):
|
|
|
743
872
|
|
|
744
873
|
self.loaded_modules.update(newly_loaded_modules)
|
|
745
874
|
|
|
875
|
+
def _track_imports_from_code(self, code: str) -> None:
|
|
876
|
+
"""Track import statements from executed code"""
|
|
877
|
+
try:
|
|
878
|
+
tree = ast.parse(code)
|
|
879
|
+
|
|
880
|
+
for node in ast.walk(tree):
|
|
881
|
+
# Handle "from X import Y" style imports
|
|
882
|
+
if isinstance(node, ast.ImportFrom):
|
|
883
|
+
mod = node.module
|
|
884
|
+
|
|
885
|
+
# Skip relative imports that don't have a module name
|
|
886
|
+
if mod is None:
|
|
887
|
+
continue
|
|
888
|
+
|
|
889
|
+
for name in node.names:
|
|
890
|
+
# name.name is going to be actual name that we want to import from module
|
|
891
|
+
# name.asname is Z in the case of from X import Y as Z
|
|
892
|
+
# we should update Z in the shell in this situation, so track it too.
|
|
893
|
+
original_name = name.name
|
|
894
|
+
resolved_name = name.asname if name.asname else name.name
|
|
895
|
+
|
|
896
|
+
# Since the code executed successfully, we know this import is valid
|
|
897
|
+
self._reloader.import_from_tracker.add_import(
|
|
898
|
+
mod, original_name, resolved_name
|
|
899
|
+
)
|
|
900
|
+
except (SyntaxError, ValueError):
|
|
901
|
+
# If there's a syntax error, skip import tracking
|
|
902
|
+
# (though this shouldn't happen since the code already executed successfully)
|
|
903
|
+
pass
|
|
904
|
+
|
|
746
905
|
|
|
747
906
|
def load_ipython_extension(ip):
|
|
748
907
|
"""Load the extension in IPython."""
|
|
@@ -432,16 +432,7 @@ class DeduperReloader(DeduperReloaderPatchingMixin):
|
|
|
432
432
|
func_code = "class __autoreload_class__:\n" + textwrap.indent(
|
|
433
433
|
func_code, " "
|
|
434
434
|
)
|
|
435
|
-
global_env =
|
|
436
|
-
if hasattr(to_patch_to, "__globals__"):
|
|
437
|
-
global_env = to_patch_to.__globals__
|
|
438
|
-
elif isinstance(to_patch_to, property):
|
|
439
|
-
if to_patch_to.fget is not None:
|
|
440
|
-
global_env = to_patch_to.fget.__globals__
|
|
441
|
-
elif to_patch_to.fset is not None:
|
|
442
|
-
global_env = to_patch_to.fset.__globals__
|
|
443
|
-
elif to_patch_to.fdel is not None:
|
|
444
|
-
global_env = to_patch_to.fdel.__globals__
|
|
435
|
+
global_env = ns.__dict__
|
|
445
436
|
if not isinstance(global_env, dict):
|
|
446
437
|
global_env = dict(global_env)
|
|
447
438
|
exec(func_code, global_env, local_env) # type: ignore[arg-type]
|
IPython/utils/_sysinfo.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# GENERATED BY setup.py
|
|
2
|
-
commit = "
|
|
2
|
+
commit = "67f7d8b8b"
|
|
@@ -13,7 +13,8 @@ IPython/core/compilerop.py,sha256=tA8xHh10gp85brI2OYmvl7kW0TgDghdKbzmZE7nS4sw,69
|
|
|
13
13
|
IPython/core/completer.py,sha256=xczIOWv2i6fKjt2neeSLCeMvBMPIV-OQbE7ggBQB_PU,129815
|
|
14
14
|
IPython/core/completerlib.py,sha256=C_1uFwR4eiqIsemMRbluMQV1WJ3qSfnGxO01PsGSpr8,12641
|
|
15
15
|
IPython/core/crashhandler.py,sha256=8-kyI6aNkqbaB_lBlbNKAOFv34HDBCpLggMfiu4oIDg,8747
|
|
16
|
-
IPython/core/debugger.py,sha256=
|
|
16
|
+
IPython/core/debugger.py,sha256=ZVvFEIby6pBAd1Cv5MfZ8EX3lY3il-v2eT2Z4JwubD8,41991
|
|
17
|
+
IPython/core/debugger_backport.py,sha256=qP96tVbfH7wpOFIjhuFyFVVM1zIgCGbP1AyQzOBfw28,8216
|
|
17
18
|
IPython/core/display.py,sha256=wQgVFY_U1O-a-jJSLb00nJ9m2w9-NsBhEBGnQUcWUd0,41129
|
|
18
19
|
IPython/core/display_functions.py,sha256=hlj1gXXrcIQU_ita03dHFesltOCViP1N3RcoLtLuyFI,12407
|
|
19
20
|
IPython/core/display_trap.py,sha256=r9AeMqllLicJvY8JfrGTQMkyxz37QT7X_RwwXxNk7R0,2185
|
|
@@ -30,7 +31,7 @@ IPython/core/history.py,sha256=5hmGOe1H93tCtWj_d8HdFixDCr0kdEqahGJ-zUo03RQ,41183
|
|
|
30
31
|
IPython/core/historyapp.py,sha256=5H38INsWXRacscKz_5PQHYrEnHEayDtc1D1qcSyHRBU,5847
|
|
31
32
|
IPython/core/hooks.py,sha256=xBWTZqycxZi97yj01IFc-SoJBzV5B73IoDHbAAlKUpQ,5193
|
|
32
33
|
IPython/core/inputtransformer2.py,sha256=7sRleytrcAbp5PZMOrDw59MjUAGXg5BbaRbPkSW83-I,28909
|
|
33
|
-
IPython/core/interactiveshell.py,sha256=
|
|
34
|
+
IPython/core/interactiveshell.py,sha256=LYa9QAz74ljvILU-UIymV-VsXZBczrDegSftUZ24-pM,159746
|
|
34
35
|
IPython/core/latex_symbols.py,sha256=DzFecvqWVSsdN7vWAsp0mlYAHRDQKfZGAmvuDUh0M-s,30127
|
|
35
36
|
IPython/core/logger.py,sha256=Iwe4xKMmxEdvSwHYPMfsTWkmdaqVCgvZT3R3I3qTmrU,8436
|
|
36
37
|
IPython/core/macro.py,sha256=OhvXWNhLe393rI2wTpMgbUVHWSnmC_ycHiYqzqSHXZU,1726
|
|
@@ -44,7 +45,7 @@ IPython/core/prefilter.py,sha256=JHQ3feaD4bhoBDqZcEgmlDjQ2sfRXC1DNjgJhpaMU7E,257
|
|
|
44
45
|
IPython/core/profileapp.py,sha256=bFMFIyehxeF9pDUtxw_6D3b0nxeqsupKTe7XhH7GMkc,10711
|
|
45
46
|
IPython/core/profiledir.py,sha256=-vjOa1I_UajMZJblJRYXh16Y0RaAUn5a2swQBsw2qEU,8459
|
|
46
47
|
IPython/core/pylabtools.py,sha256=LfNV9xCJ3flCfJXmv1NaCRYj9jZDtHAQ5oSEHWo3Gmg,17376
|
|
47
|
-
IPython/core/release.py,sha256=
|
|
48
|
+
IPython/core/release.py,sha256=ecwU1SOd6rB87PaUvxEoHsxQCLFEAtebo2_pvVgvA0A,1505
|
|
48
49
|
IPython/core/shellapp.py,sha256=oZIzj_sqIXrN3qyyhinZ1gLXvFviKYHkmS4H3wVEb74,19307
|
|
49
50
|
IPython/core/splitinput.py,sha256=bAX1puQjvYB-otJyqiqeOhWj6dooWuQeNVx2YdaKQs8,5006
|
|
50
51
|
IPython/core/tbtools.py,sha256=X4iB5zKAT2y4TK1R9l3d3kiW5htrzKn3qxalFFe2xzI,16880
|
|
@@ -58,21 +59,21 @@ IPython/core/magics/basic.py,sha256=uFkd-gTzlSVkNDSu8Rg4fbS_IK2raEhx1SYA6kWZ4hg,
|
|
|
58
59
|
IPython/core/magics/code.py,sha256=h_dho9niPvtf_IpoOZf5GAD6CYbT0EQGsfLfutyX-7I,28144
|
|
59
60
|
IPython/core/magics/config.py,sha256=QBL5uY7m-Q7C46mO3q1Yio9s73w1TnI9y__j5E-j44Y,4881
|
|
60
61
|
IPython/core/magics/display.py,sha256=STRq66GlZwcvFyBxbkqslclpP_s9LnqD0ew9Z3S4-Jo,3130
|
|
61
|
-
IPython/core/magics/execution.py,sha256=
|
|
62
|
+
IPython/core/magics/execution.py,sha256=YKsyU9cUxAyAquyWVzw5iNH7h-OY-UYHRm4eJoz5XKI,64512
|
|
62
63
|
IPython/core/magics/extension.py,sha256=Jj6OlkM71PS0j1HfEMDc-jU2Exwo9Ff_K0nD7e_W4N0,2477
|
|
63
64
|
IPython/core/magics/history.py,sha256=Aw9gBzK4AJbe-gvRdMW7n-_zxxHuMyHvHJtRDuCwwug,12629
|
|
64
65
|
IPython/core/magics/logging.py,sha256=VuDiF5QZrgzTT7Lr1NkkMCtUM1EHoGCw2pYlKsSQc4Q,6867
|
|
65
|
-
IPython/core/magics/namespace.py,sha256=
|
|
66
|
+
IPython/core/magics/namespace.py,sha256=uqWM77PbbpOYvQOYMqCwJJrnJwXVIw4abju9Q7cxas0,25446
|
|
66
67
|
IPython/core/magics/osm.py,sha256=mNlHBS8ZEMf687nDpLGYKj6aC-i_r7d9iUTFKw6WtY4,30695
|
|
67
68
|
IPython/core/magics/packaging.py,sha256=5m2pt1bkosMdiQxB46hDdD4KisfPJpNnebCqMnygodE,6030
|
|
68
69
|
IPython/core/magics/pylab.py,sha256=BBRczZ0khoZB5NPipgvVtOWYpdkLatB9mQFYzyg-vpg,6624
|
|
69
|
-
IPython/core/magics/script.py,sha256=
|
|
70
|
+
IPython/core/magics/script.py,sha256=zv-BwLsqAeVsgwCEnO3mr4HoSM6aFz6eaH_KPmM2uJM,13570
|
|
70
71
|
IPython/core/profile/README_STARTUP,sha256=Y47GtYQkWy6pdzkqylUNL6eBSZMUIRGwTxXPUF_BBBc,371
|
|
71
72
|
IPython/extensions/__init__.py,sha256=V4vSllFd18CVUvDTbXLYqfwTFmPXUiQZGCs5LX2IliE,78
|
|
72
|
-
IPython/extensions/autoreload.py,sha256=
|
|
73
|
+
IPython/extensions/autoreload.py,sha256=XnNxSE8d4cxvBGyvz2YJwySRsIOZe6WXRT9TUPWBd88,31724
|
|
73
74
|
IPython/extensions/storemagic.py,sha256=ths8PLtGmYZAYaibRuS1QetLm1Xu1soyGwehBjayByg,8168
|
|
74
75
|
IPython/extensions/deduperreload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
IPython/extensions/deduperreload/deduperreload.py,sha256=
|
|
76
|
+
IPython/extensions/deduperreload/deduperreload.py,sha256=5BWnzqfoScQ3a1RTN3wZpxKGXVU_Oxo7P4rQoJfRrI0,24134
|
|
76
77
|
IPython/extensions/deduperreload/deduperreload_patching.py,sha256=xOaws3UV5KmaAK8yZ3qtQO45w_5Ntkt_qZTcZ1psszY,4934
|
|
77
78
|
IPython/external/__init__.py,sha256=-EQHbuUnBe1RS1_CwaLGzNSZQsCJsrxHW_r15smvVW0,126
|
|
78
79
|
IPython/external/pickleshare.py,sha256=Zs0Hq8IXbf51RNFCr1AFxZKtlhfPJMM3b1WD4sNB670,9974
|
|
@@ -142,7 +143,7 @@ IPython/utils/_process_emscripten.py,sha256=lGLQb2IgmanNtb502KflfuKIhgOF119Ji3cw
|
|
|
142
143
|
IPython/utils/_process_posix.py,sha256=aOEtguhS3vdWngBpws1XQURO8Ozqd5gRiCk9VLky6tA,7502
|
|
143
144
|
IPython/utils/_process_win32.py,sha256=Pcf6ZiqMbqDT79edzegE_AX3D367UtE8bbhT41no54A,6775
|
|
144
145
|
IPython/utils/_process_win32_controller.py,sha256=hi2eR7mLbl3TTMCVbgps85GppxdtYbhOYK_l13WvYaM,21343
|
|
145
|
-
IPython/utils/_sysinfo.py,sha256=
|
|
146
|
+
IPython/utils/_sysinfo.py,sha256=dBl2xAoPkJnjAen7HGklkADaXbyQjQc9sk00mQOwoCA,45
|
|
146
147
|
IPython/utils/capture.py,sha256=h5yL5Lxq8bgO1SFpoNDYjEi6mh1IW_2X9CE7vOsUxE4,5137
|
|
147
148
|
IPython/utils/coloransi.py,sha256=CML-SkzLa7oaIK1qypb3uwcfPXDeKHxZQiMJ0IWvUY0,293
|
|
148
149
|
IPython/utils/contexts.py,sha256=w5_uXc0WTU3KKV1kcCW9A0_Mz5mGRoeGWMq_P_eo-Dg,1610
|
|
@@ -174,11 +175,11 @@ IPython/utils/text.py,sha256=6s-y4KvDmnJxLs0urf5D-1auZGSnj2xmXgQ-9jVu0N8,18788
|
|
|
174
175
|
IPython/utils/timing.py,sha256=nND-ZUBkHWfYevvbRG-YfOSIFczz_epzMqWK5PH6nqA,4275
|
|
175
176
|
IPython/utils/tokenutil.py,sha256=x6KQ6ZCGOY7j5GQcr7byJRZSBFgyBcfkTiLtjxkl9f8,6552
|
|
176
177
|
IPython/utils/wildcard.py,sha256=6EEc3OEYp-IuSoidL6nwpaHg--GxnzbAJTmFiz77CNE,4612
|
|
177
|
-
ipython-9.
|
|
178
|
-
ipython-9.
|
|
179
|
-
ipython-9.
|
|
180
|
-
ipython-9.
|
|
181
|
-
ipython-9.
|
|
182
|
-
ipython-9.
|
|
183
|
-
ipython-9.
|
|
184
|
-
ipython-9.
|
|
178
|
+
ipython-9.4.0.data/data/share/man/man1/ipython.1,sha256=PVdQP2hHmHyUEwzLOPcgavnCe9jTDVrM1jKZt4cnF_Q,2058
|
|
179
|
+
ipython-9.4.0.dist-info/licenses/COPYING.rst,sha256=NBr8vXKYh7cEb-e5j8T07f867Y048G7v2bMGcPBD3xc,1639
|
|
180
|
+
ipython-9.4.0.dist-info/licenses/LICENSE,sha256=4OOQdI7UQKuJPKHxNaiKkgqvVAnbuQpbQnx1xeUSaPs,1720
|
|
181
|
+
ipython-9.4.0.dist-info/METADATA,sha256=d4dTcreyYD_4S0OE3JSqst9kT1pRCroTCNNwdInBiZY,4431
|
|
182
|
+
ipython-9.4.0.dist-info/WHEEL,sha256=_2vT4RZnosDS5yjNeAMuEbJY3SAaKsQTuZHmdWSC-aI,90
|
|
183
|
+
ipython-9.4.0.dist-info/entry_points.txt,sha256=z5BEEohWgg0SHdgdeNABf4T3fu-lr9W6F_bWOQHLdVs,83
|
|
184
|
+
ipython-9.4.0.dist-info/top_level.txt,sha256=PKjvHtNCBZ9EHTmd2mwJ1J_k3j0F6D1lTFzIcJFFPEU,8
|
|
185
|
+
ipython-9.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|