ipython 9.0.2__py3-none-any.whl → 9.1.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/completer.py +155 -3
- IPython/core/display_trap.py +4 -0
- IPython/core/displayhook.py +17 -7
- IPython/core/displaypub.py +14 -0
- IPython/core/history.py +18 -1
- IPython/core/historyapp.py +3 -3
- IPython/core/interactiveshell.py +130 -12
- IPython/core/magics/basic.py +42 -9
- IPython/core/magics/execution.py +18 -10
- IPython/core/release.py +2 -2
- IPython/core/tips.py +13 -13
- IPython/terminal/embed.py +2 -1
- IPython/terminal/interactiveshell.py +2 -3
- IPython/terminal/shortcuts/auto_suggest.py +16 -15
- IPython/utils/PyColorize.py +2 -2
- IPython/utils/_sysinfo.py +1 -1
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info}/METADATA +7 -3
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info}/RECORD +24 -24
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info}/WHEEL +1 -1
- {ipython-9.0.2.data → ipython-9.1.0.data}/data/share/man/man1/ipython.1 +0 -0
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info}/entry_points.txt +0 -0
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info/licenses}/COPYING.rst +0 -0
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info/licenses}/LICENSE +0 -0
- {ipython-9.0.2.dist-info → ipython-9.1.0.dist-info}/top_level.txt +0 -0
IPython/core/completer.py
CHANGED
|
@@ -1137,7 +1137,7 @@ class Completer(Configurable):
|
|
|
1137
1137
|
def _attr_matches(
|
|
1138
1138
|
self, text: str, include_prefix: bool = True
|
|
1139
1139
|
) -> tuple[Sequence[str], str]:
|
|
1140
|
-
m2 = self._ATTR_MATCH_RE.match(
|
|
1140
|
+
m2 = self._ATTR_MATCH_RE.match(text)
|
|
1141
1141
|
if not m2:
|
|
1142
1142
|
return [], ""
|
|
1143
1143
|
expr, attr = m2.group(1, 2)
|
|
@@ -2360,11 +2360,163 @@ class IPCompleter(Completer):
|
|
|
2360
2360
|
else:
|
|
2361
2361
|
return iter([])
|
|
2362
2362
|
|
|
2363
|
+
class _CompletionContextType(enum.Enum):
|
|
2364
|
+
ATTRIBUTE = "attribute" # For attribute completion
|
|
2365
|
+
GLOBAL = "global" # For global completion
|
|
2366
|
+
|
|
2367
|
+
def _determine_completion_context(self, line):
|
|
2368
|
+
"""
|
|
2369
|
+
Determine whether the cursor is in an attribute or global completion context.
|
|
2370
|
+
"""
|
|
2371
|
+
# Cursor in string/comment → GLOBAL.
|
|
2372
|
+
is_string, is_in_expression = self._is_in_string_or_comment(line)
|
|
2373
|
+
if is_string and not is_in_expression:
|
|
2374
|
+
return self._CompletionContextType.GLOBAL
|
|
2375
|
+
|
|
2376
|
+
# If we're in a template string expression, handle specially
|
|
2377
|
+
if is_string and is_in_expression:
|
|
2378
|
+
# Extract the expression part - look for the last { that isn't closed
|
|
2379
|
+
expr_start = line.rfind("{")
|
|
2380
|
+
if expr_start >= 0:
|
|
2381
|
+
# We're looking at the expression inside a template string
|
|
2382
|
+
expr = line[expr_start + 1 :]
|
|
2383
|
+
# Recursively determine the context of the expression
|
|
2384
|
+
return self._determine_completion_context(expr)
|
|
2385
|
+
|
|
2386
|
+
# Handle plain number literals - should be global context
|
|
2387
|
+
# Ex: 3. -42.14 but not 3.1.
|
|
2388
|
+
if re.search(r"(?<!\w)(?<!\d\.)([-+]?\d+\.(\d+)?)(?!\w)$", line):
|
|
2389
|
+
return self._CompletionContextType.GLOBAL
|
|
2390
|
+
|
|
2391
|
+
# Handle all other attribute matches np.ran, d[0].k, (a,b).count
|
|
2392
|
+
chain_match = re.search(r".*(.+\.(?:[a-zA-Z]\w*)?)$", line)
|
|
2393
|
+
if chain_match:
|
|
2394
|
+
return self._CompletionContextType.ATTRIBUTE
|
|
2395
|
+
|
|
2396
|
+
return self._CompletionContextType.GLOBAL
|
|
2397
|
+
|
|
2398
|
+
def _is_in_string_or_comment(self, text):
|
|
2399
|
+
"""
|
|
2400
|
+
Determine if the cursor is inside a string or comment.
|
|
2401
|
+
Returns (is_string, is_in_expression) tuple:
|
|
2402
|
+
- is_string: True if in any kind of string
|
|
2403
|
+
- is_in_expression: True if inside an f-string/t-string expression
|
|
2404
|
+
"""
|
|
2405
|
+
in_single_quote = False
|
|
2406
|
+
in_double_quote = False
|
|
2407
|
+
in_triple_single = False
|
|
2408
|
+
in_triple_double = False
|
|
2409
|
+
in_template_string = False # Covers both f-strings and t-strings
|
|
2410
|
+
in_expression = False # For expressions in f/t-strings
|
|
2411
|
+
expression_depth = 0 # Track nested braces in expressions
|
|
2412
|
+
i = 0
|
|
2413
|
+
|
|
2414
|
+
while i < len(text):
|
|
2415
|
+
# Check for f-string or t-string start
|
|
2416
|
+
if (
|
|
2417
|
+
i + 1 < len(text)
|
|
2418
|
+
and text[i] in ("f", "t")
|
|
2419
|
+
and (text[i + 1] == '"' or text[i + 1] == "'")
|
|
2420
|
+
and not (
|
|
2421
|
+
in_single_quote
|
|
2422
|
+
or in_double_quote
|
|
2423
|
+
or in_triple_single
|
|
2424
|
+
or in_triple_double
|
|
2425
|
+
)
|
|
2426
|
+
):
|
|
2427
|
+
in_template_string = True
|
|
2428
|
+
i += 1 # Skip the 'f' or 't'
|
|
2429
|
+
|
|
2430
|
+
# Handle triple quotes
|
|
2431
|
+
if i + 2 < len(text):
|
|
2432
|
+
if (
|
|
2433
|
+
text[i : i + 3] == '"""'
|
|
2434
|
+
and not in_single_quote
|
|
2435
|
+
and not in_triple_single
|
|
2436
|
+
):
|
|
2437
|
+
in_triple_double = not in_triple_double
|
|
2438
|
+
if not in_triple_double:
|
|
2439
|
+
in_template_string = False
|
|
2440
|
+
i += 3
|
|
2441
|
+
continue
|
|
2442
|
+
if (
|
|
2443
|
+
text[i : i + 3] == "'''"
|
|
2444
|
+
and not in_double_quote
|
|
2445
|
+
and not in_triple_double
|
|
2446
|
+
):
|
|
2447
|
+
in_triple_single = not in_triple_single
|
|
2448
|
+
if not in_triple_single:
|
|
2449
|
+
in_template_string = False
|
|
2450
|
+
i += 3
|
|
2451
|
+
continue
|
|
2452
|
+
|
|
2453
|
+
# Handle escapes
|
|
2454
|
+
if text[i] == "\\" and i + 1 < len(text):
|
|
2455
|
+
i += 2
|
|
2456
|
+
continue
|
|
2457
|
+
|
|
2458
|
+
# Handle nested braces within f-strings
|
|
2459
|
+
if in_template_string:
|
|
2460
|
+
# Special handling for consecutive opening braces
|
|
2461
|
+
if i + 1 < len(text) and text[i : i + 2] == "{{":
|
|
2462
|
+
i += 2
|
|
2463
|
+
continue
|
|
2464
|
+
|
|
2465
|
+
# Detect start of an expression
|
|
2466
|
+
if text[i] == "{":
|
|
2467
|
+
# Only increment depth and mark as expression if not already in an expression
|
|
2468
|
+
# or if we're at a top-level nested brace
|
|
2469
|
+
if not in_expression or (in_expression and expression_depth == 0):
|
|
2470
|
+
in_expression = True
|
|
2471
|
+
expression_depth += 1
|
|
2472
|
+
i += 1
|
|
2473
|
+
continue
|
|
2474
|
+
|
|
2475
|
+
# Detect end of an expression
|
|
2476
|
+
if text[i] == "}":
|
|
2477
|
+
expression_depth -= 1
|
|
2478
|
+
if expression_depth <= 0:
|
|
2479
|
+
in_expression = False
|
|
2480
|
+
expression_depth = 0
|
|
2481
|
+
i += 1
|
|
2482
|
+
continue
|
|
2483
|
+
|
|
2484
|
+
in_triple_quote = in_triple_single or in_triple_double
|
|
2485
|
+
|
|
2486
|
+
# Handle quotes - also reset template string when closing quotes are encountered
|
|
2487
|
+
if text[i] == '"' and not in_single_quote and not in_triple_quote:
|
|
2488
|
+
in_double_quote = not in_double_quote
|
|
2489
|
+
if not in_double_quote and not in_triple_quote:
|
|
2490
|
+
in_template_string = False
|
|
2491
|
+
elif text[i] == "'" and not in_double_quote and not in_triple_quote:
|
|
2492
|
+
in_single_quote = not in_single_quote
|
|
2493
|
+
if not in_single_quote and not in_triple_quote:
|
|
2494
|
+
in_template_string = False
|
|
2495
|
+
|
|
2496
|
+
# Check for comment
|
|
2497
|
+
if text[i] == "#" and not (
|
|
2498
|
+
in_single_quote or in_double_quote or in_triple_quote
|
|
2499
|
+
):
|
|
2500
|
+
return True, False
|
|
2501
|
+
|
|
2502
|
+
i += 1
|
|
2503
|
+
|
|
2504
|
+
is_string = (
|
|
2505
|
+
in_single_quote or in_double_quote or in_triple_single or in_triple_double
|
|
2506
|
+
)
|
|
2507
|
+
|
|
2508
|
+
# Return tuple (is_string, is_in_expression)
|
|
2509
|
+
return (
|
|
2510
|
+
is_string or (in_template_string and not in_expression),
|
|
2511
|
+
in_expression and expression_depth > 0,
|
|
2512
|
+
)
|
|
2513
|
+
|
|
2363
2514
|
@context_matcher()
|
|
2364
2515
|
def python_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
|
|
2365
2516
|
"""Match attributes or global python names"""
|
|
2366
|
-
text = context.
|
|
2367
|
-
|
|
2517
|
+
text = context.text_until_cursor
|
|
2518
|
+
completion_type = self._determine_completion_context(text)
|
|
2519
|
+
if completion_type == self._CompletionContextType.ATTRIBUTE:
|
|
2368
2520
|
try:
|
|
2369
2521
|
matches, fragment = self._attr_matches(text, include_prefix=False)
|
|
2370
2522
|
if text.endswith(".") and self.omit__names:
|
IPython/core/display_trap.py
CHANGED
|
@@ -58,6 +58,10 @@ class DisplayTrap(Configurable):
|
|
|
58
58
|
# Returning False will cause exceptions to propagate
|
|
59
59
|
return False
|
|
60
60
|
|
|
61
|
+
@property
|
|
62
|
+
def is_active(self) -> bool:
|
|
63
|
+
return self._nested_level != 0
|
|
64
|
+
|
|
61
65
|
def set(self):
|
|
62
66
|
"""Set the hook."""
|
|
63
67
|
if sys.displayhook is not self.hook:
|
IPython/core/displayhook.py
CHANGED
|
@@ -16,6 +16,8 @@ from traitlets.config.configurable import Configurable
|
|
|
16
16
|
from traitlets import Instance, Float
|
|
17
17
|
from warnings import warn
|
|
18
18
|
|
|
19
|
+
from .history import HistoryOutput
|
|
20
|
+
|
|
19
21
|
# TODO: Move the various attributes (cache_size, [others now moved]). Some
|
|
20
22
|
# of these are also attributes of InteractiveShell. They should be on ONE object
|
|
21
23
|
# only and the other objects should ask that one object for their values.
|
|
@@ -35,6 +37,7 @@ class DisplayHook(Configurable):
|
|
|
35
37
|
|
|
36
38
|
def __init__(self, shell=None, cache_size=1000, **kwargs):
|
|
37
39
|
super(DisplayHook, self).__init__(shell=shell, **kwargs)
|
|
40
|
+
self._is_active = False
|
|
38
41
|
cache_size_min = 3
|
|
39
42
|
if cache_size <= 0:
|
|
40
43
|
self.do_full_cache = 0
|
|
@@ -51,7 +54,7 @@ class DisplayHook(Configurable):
|
|
|
51
54
|
|
|
52
55
|
# we need a reference to the user-level namespace
|
|
53
56
|
self.shell = shell
|
|
54
|
-
|
|
57
|
+
|
|
55
58
|
self._,self.__,self.___ = '','',''
|
|
56
59
|
|
|
57
60
|
# these are deliberately global:
|
|
@@ -84,13 +87,13 @@ class DisplayHook(Configurable):
|
|
|
84
87
|
def quiet(self):
|
|
85
88
|
"""Should we silence the display hook because of ';'?"""
|
|
86
89
|
# do not print output if input ends in ';'
|
|
87
|
-
|
|
90
|
+
|
|
88
91
|
try:
|
|
89
92
|
cell = self.shell.history_manager.input_hist_parsed[-1]
|
|
90
93
|
except IndexError:
|
|
91
94
|
# some uses of ipshellembed may fail here
|
|
92
95
|
return False
|
|
93
|
-
|
|
96
|
+
|
|
94
97
|
return self.semicolon_at_end_of_expression(cell)
|
|
95
98
|
|
|
96
99
|
@staticmethod
|
|
@@ -110,7 +113,11 @@ class DisplayHook(Configurable):
|
|
|
110
113
|
|
|
111
114
|
def start_displayhook(self):
|
|
112
115
|
"""Start the displayhook, initializing resources."""
|
|
113
|
-
|
|
116
|
+
self._is_active = True
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def is_active(self):
|
|
120
|
+
return self._is_active
|
|
114
121
|
|
|
115
122
|
def write_output_prompt(self):
|
|
116
123
|
"""Write the output prompt.
|
|
@@ -242,7 +249,10 @@ class DisplayHook(Configurable):
|
|
|
242
249
|
|
|
243
250
|
def log_output(self, format_dict):
|
|
244
251
|
"""Log the output."""
|
|
245
|
-
|
|
252
|
+
self.shell.history_manager.outputs[self.prompt_count].append(
|
|
253
|
+
HistoryOutput(output_type="execute_result", bundle=format_dict)
|
|
254
|
+
)
|
|
255
|
+
if "text/plain" not in format_dict:
|
|
246
256
|
# nothing to do
|
|
247
257
|
return
|
|
248
258
|
if self.shell.logger.log_output:
|
|
@@ -254,6 +264,7 @@ class DisplayHook(Configurable):
|
|
|
254
264
|
"""Finish up all displayhook activities."""
|
|
255
265
|
sys.stdout.write(self.shell.separate_out2)
|
|
256
266
|
sys.stdout.flush()
|
|
267
|
+
self._is_active = False
|
|
257
268
|
|
|
258
269
|
def __call__(self, result=None):
|
|
259
270
|
"""Printing with history cache management.
|
|
@@ -280,13 +291,12 @@ class DisplayHook(Configurable):
|
|
|
280
291
|
cull_count = max(int(sz * self.cull_fraction), 2)
|
|
281
292
|
warn('Output cache limit (currently {sz} entries) hit.\n'
|
|
282
293
|
'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
|
|
283
|
-
|
|
294
|
+
|
|
284
295
|
for i, n in enumerate(sorted(oh)):
|
|
285
296
|
if i >= cull_count:
|
|
286
297
|
break
|
|
287
298
|
self.shell.user_ns.pop('_%i' % n, None)
|
|
288
299
|
oh.pop(n, None)
|
|
289
|
-
|
|
290
300
|
|
|
291
301
|
def flush(self):
|
|
292
302
|
if not self.do_full_cache:
|
IPython/core/displaypub.py
CHANGED
|
@@ -22,6 +22,7 @@ from traitlets import List
|
|
|
22
22
|
|
|
23
23
|
# This used to be defined here - it is imported for backwards compatibility
|
|
24
24
|
from .display_functions import publish_display_data
|
|
25
|
+
from .history import HistoryOutput
|
|
25
26
|
|
|
26
27
|
import typing as t
|
|
27
28
|
|
|
@@ -41,6 +42,7 @@ class DisplayPublisher(Configurable):
|
|
|
41
42
|
|
|
42
43
|
def __init__(self, shell=None, *args, **kwargs):
|
|
43
44
|
self.shell = shell
|
|
45
|
+
self._is_publishing = False
|
|
44
46
|
super().__init__(*args, **kwargs)
|
|
45
47
|
|
|
46
48
|
def _validate_data(self, data, metadata=None):
|
|
@@ -129,13 +131,25 @@ class DisplayPublisher(Configurable):
|
|
|
129
131
|
if self.shell is not None:
|
|
130
132
|
handlers = getattr(self.shell, "mime_renderers", {})
|
|
131
133
|
|
|
134
|
+
outputs = self.shell.history_manager.outputs
|
|
135
|
+
|
|
136
|
+
outputs[self.shell.execution_count].append(
|
|
137
|
+
HistoryOutput(output_type="display_data", bundle=data)
|
|
138
|
+
)
|
|
139
|
+
|
|
132
140
|
for mime, handler in handlers.items():
|
|
133
141
|
if mime in data:
|
|
134
142
|
handler(data[mime], metadata.get(mime, None))
|
|
135
143
|
return
|
|
136
144
|
|
|
145
|
+
self._is_publishing = True
|
|
137
146
|
if "text/plain" in data:
|
|
138
147
|
print(data["text/plain"])
|
|
148
|
+
self._is_publishing = False
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def is_publishing(self):
|
|
152
|
+
return self._is_publishing
|
|
139
153
|
|
|
140
154
|
def clear_output(self, wait=False):
|
|
141
155
|
"""Clear the output of the cell receiving output."""
|
IPython/core/history.py
CHANGED
|
@@ -14,7 +14,9 @@ import re
|
|
|
14
14
|
import threading
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
from collections import defaultdict
|
|
17
18
|
from contextlib import contextmanager
|
|
19
|
+
from dataclasses import dataclass
|
|
18
20
|
from decorator import decorator
|
|
19
21
|
from traitlets import (
|
|
20
22
|
Any,
|
|
@@ -583,6 +585,14 @@ class HistoryAccessor(HistoryAccessorBase):
|
|
|
583
585
|
yield from self.get_range(sess, s, e, raw=raw, output=output)
|
|
584
586
|
|
|
585
587
|
|
|
588
|
+
@dataclass
|
|
589
|
+
class HistoryOutput:
|
|
590
|
+
output_type: typing.Literal[
|
|
591
|
+
"out_stream", "err_stream", "display_data", "execute_result"
|
|
592
|
+
]
|
|
593
|
+
bundle: typing.Dict[str, str]
|
|
594
|
+
|
|
595
|
+
|
|
586
596
|
class HistoryManager(HistoryAccessor):
|
|
587
597
|
"""A class to organize all history-related functionality in one place."""
|
|
588
598
|
|
|
@@ -610,7 +620,11 @@ class HistoryManager(HistoryAccessor):
|
|
|
610
620
|
# execution count.
|
|
611
621
|
output_hist = Dict()
|
|
612
622
|
# The text/plain repr of outputs.
|
|
613
|
-
output_hist_reprs:
|
|
623
|
+
output_hist_reprs: typing.Dict[int, str] = Dict() # type: ignore [assignment]
|
|
624
|
+
# Maps execution_count to MIME bundles
|
|
625
|
+
outputs: typing.Dict[int, typing.List[HistoryOutput]] = defaultdict(list)
|
|
626
|
+
# Maps execution_count to exception tracebacks
|
|
627
|
+
exceptions: typing.Dict[int, typing.Dict[str, Any]] = Dict() # type: ignore [assignment]
|
|
614
628
|
|
|
615
629
|
# The number of the current session in the history database
|
|
616
630
|
session_number: int = Integer() # type: ignore [assignment]
|
|
@@ -749,6 +763,9 @@ class HistoryManager(HistoryAccessor):
|
|
|
749
763
|
"""Clear the session history, releasing all object references, and
|
|
750
764
|
optionally open a new session."""
|
|
751
765
|
self.output_hist.clear()
|
|
766
|
+
self.outputs.clear()
|
|
767
|
+
self.exceptions.clear()
|
|
768
|
+
|
|
752
769
|
# The directory history can't be completely empty
|
|
753
770
|
self.dir_hist[:] = [Path.cwd()]
|
|
754
771
|
|
IPython/core/historyapp.py
CHANGED
|
@@ -59,9 +59,9 @@ class HistoryTrim(BaseIPythonApplication):
|
|
|
59
59
|
print("There are already at most %d entries in the history database." % self.keep)
|
|
60
60
|
print("Not doing anything. Use --keep= argument to keep fewer entries")
|
|
61
61
|
return
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
print("Trimming history to the most recent %d entries." % self.keep)
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
inputs.pop() # Remove the extra element we got to check the length.
|
|
66
66
|
inputs.reverse()
|
|
67
67
|
if inputs:
|
|
@@ -71,7 +71,7 @@ class HistoryTrim(BaseIPythonApplication):
|
|
|
71
71
|
sessions = list(con.execute('SELECT session, start, end, num_cmds, remark FROM '
|
|
72
72
|
'sessions WHERE session >= ?', (first_session,)))
|
|
73
73
|
con.close()
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
# Create the new history database.
|
|
76
76
|
new_hist_file = profile_dir / "history.sqlite.new"
|
|
77
77
|
i = 0
|
IPython/core/interactiveshell.py
CHANGED
|
@@ -28,12 +28,13 @@ import traceback
|
|
|
28
28
|
import types
|
|
29
29
|
import warnings
|
|
30
30
|
from ast import stmt
|
|
31
|
+
from contextlib import contextmanager
|
|
31
32
|
from io import open as io_open
|
|
32
33
|
from logging import error
|
|
33
34
|
from pathlib import Path
|
|
34
35
|
from typing import Callable
|
|
35
36
|
from typing import List as ListType, Any as AnyType
|
|
36
|
-
from typing import Optional, Sequence, Tuple
|
|
37
|
+
from typing import Literal, Optional, Sequence, Tuple
|
|
37
38
|
from warnings import warn
|
|
38
39
|
|
|
39
40
|
from IPython.external.pickleshare import PickleShareDB
|
|
@@ -71,7 +72,7 @@ from IPython.core.error import InputRejected, UsageError
|
|
|
71
72
|
from IPython.core.events import EventManager, available_events
|
|
72
73
|
from IPython.core.extensions import ExtensionManager
|
|
73
74
|
from IPython.core.formatters import DisplayFormatter
|
|
74
|
-
from IPython.core.history import HistoryManager
|
|
75
|
+
from IPython.core.history import HistoryManager, HistoryOutput
|
|
75
76
|
from IPython.core.inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
|
|
76
77
|
from IPython.core.logger import Logger
|
|
77
78
|
from IPython.core.macro import Macro
|
|
@@ -324,6 +325,7 @@ def _modified_open(file, *args, **kwargs):
|
|
|
324
325
|
|
|
325
326
|
return io_open(file, *args, **kwargs)
|
|
326
327
|
|
|
328
|
+
|
|
327
329
|
class InteractiveShell(SingletonConfigurable):
|
|
328
330
|
"""An enhanced, interactive shell for Python."""
|
|
329
331
|
|
|
@@ -466,7 +468,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
466
468
|
# Monotonically increasing execution counter
|
|
467
469
|
execution_count = Integer(1)
|
|
468
470
|
filename = Unicode("<ipython console>")
|
|
469
|
-
ipython_dir= Unicode(
|
|
471
|
+
ipython_dir = Unicode("").tag(config=True) # Set to get_ipython_dir() in __init__
|
|
470
472
|
|
|
471
473
|
# Used to transform cells before running them, and check whether code is complete
|
|
472
474
|
input_transformer_manager = Instance('IPython.core.inputtransformer2.TransformerManager',
|
|
@@ -661,6 +663,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
661
663
|
# inside a single Trio event loop. If used, it is set from
|
|
662
664
|
# `ipykernel.kernelapp`.
|
|
663
665
|
self.trio_runner = None
|
|
666
|
+
self.showing_traceback = False
|
|
664
667
|
|
|
665
668
|
@property
|
|
666
669
|
def user_ns(self):
|
|
@@ -868,7 +871,7 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
868
871
|
cache_size=self.cache_size,
|
|
869
872
|
)
|
|
870
873
|
self.configurables.append(self.displayhook)
|
|
871
|
-
# This is a context manager that installs/
|
|
874
|
+
# This is a context manager that installs/removes the displayhook at
|
|
872
875
|
# the appropriate time.
|
|
873
876
|
self.display_trap = DisplayTrap(hook=self.displayhook)
|
|
874
877
|
|
|
@@ -2200,10 +2203,12 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
2200
2203
|
place, like a side channel.
|
|
2201
2204
|
"""
|
|
2202
2205
|
val = self.InteractiveTB.stb2text(stb)
|
|
2206
|
+
self.showing_traceback = True
|
|
2203
2207
|
try:
|
|
2204
2208
|
print(val)
|
|
2205
2209
|
except UnicodeEncodeError:
|
|
2206
2210
|
print(val.encode("utf-8", "backslashreplace").decode())
|
|
2211
|
+
self.showing_traceback = False
|
|
2207
2212
|
|
|
2208
2213
|
def showsyntaxerror(self, filename=None, running_compiled_code=False):
|
|
2209
2214
|
"""Display the syntax error that just occurred.
|
|
@@ -3006,6 +3011,51 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3006
3011
|
self.showtraceback()
|
|
3007
3012
|
warn('Unknown failure executing module: <%s>' % mod_name)
|
|
3008
3013
|
|
|
3014
|
+
@contextmanager
|
|
3015
|
+
def _tee(self, channel: Literal["stdout", "stderr"]):
|
|
3016
|
+
"""Capture output of a given standard stream and store it in history.
|
|
3017
|
+
|
|
3018
|
+
Uses patching of write method for maximal compatibility,
|
|
3019
|
+
because ipykernel checks for instances of the stream class,
|
|
3020
|
+
and stream classes in ipykernel implement more complex logic.
|
|
3021
|
+
"""
|
|
3022
|
+
stream = getattr(sys, channel)
|
|
3023
|
+
original_write = stream.write
|
|
3024
|
+
|
|
3025
|
+
def write(data, *args, **kwargs):
|
|
3026
|
+
"""Write data to both the original destination and the capture dictionary."""
|
|
3027
|
+
result = original_write(data, *args, **kwargs)
|
|
3028
|
+
if any(
|
|
3029
|
+
[
|
|
3030
|
+
self.display_pub.is_publishing,
|
|
3031
|
+
self.displayhook.is_active,
|
|
3032
|
+
self.showing_traceback,
|
|
3033
|
+
]
|
|
3034
|
+
):
|
|
3035
|
+
return result
|
|
3036
|
+
if not data:
|
|
3037
|
+
return result
|
|
3038
|
+
execution_count = self.execution_count
|
|
3039
|
+
output_stream = None
|
|
3040
|
+
outputs_by_counter = self.history_manager.outputs
|
|
3041
|
+
output_type = "out_stream" if channel == "stdout" else "err_stream"
|
|
3042
|
+
if execution_count in outputs_by_counter:
|
|
3043
|
+
outputs = outputs_by_counter[execution_count]
|
|
3044
|
+
if outputs[-1].output_type == output_type:
|
|
3045
|
+
output_stream = outputs[-1]
|
|
3046
|
+
if output_stream is None:
|
|
3047
|
+
output_stream = HistoryOutput(
|
|
3048
|
+
output_type=output_type, bundle={"stream": ""}
|
|
3049
|
+
)
|
|
3050
|
+
outputs_by_counter[execution_count].append(output_stream)
|
|
3051
|
+
|
|
3052
|
+
output_stream.bundle["stream"] += data # Append to existing stream
|
|
3053
|
+
return result
|
|
3054
|
+
|
|
3055
|
+
stream.write = write
|
|
3056
|
+
yield
|
|
3057
|
+
stream.write = original_write
|
|
3058
|
+
|
|
3009
3059
|
def run_cell(
|
|
3010
3060
|
self,
|
|
3011
3061
|
raw_cell,
|
|
@@ -3043,14 +3093,15 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3043
3093
|
result : :class:`ExecutionResult`
|
|
3044
3094
|
"""
|
|
3045
3095
|
result = None
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3096
|
+
with self._tee(channel="stdout"), self._tee(channel="stderr"):
|
|
3097
|
+
try:
|
|
3098
|
+
result = self._run_cell(
|
|
3099
|
+
raw_cell, store_history, silent, shell_futures, cell_id
|
|
3100
|
+
)
|
|
3101
|
+
finally:
|
|
3102
|
+
self.events.trigger("post_execute")
|
|
3103
|
+
if not silent:
|
|
3104
|
+
self.events.trigger("post_run_cell", result)
|
|
3054
3105
|
return result
|
|
3055
3106
|
|
|
3056
3107
|
def _run_cell(
|
|
@@ -3208,6 +3259,11 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3208
3259
|
|
|
3209
3260
|
def error_before_exec(value):
|
|
3210
3261
|
if store_history:
|
|
3262
|
+
if self.history_manager:
|
|
3263
|
+
# Store formatted traceback and error details
|
|
3264
|
+
self.history_manager.exceptions[self.execution_count] = (
|
|
3265
|
+
self._format_exception_for_storage(value)
|
|
3266
|
+
)
|
|
3211
3267
|
self.execution_count += 1
|
|
3212
3268
|
result.error_before_exec = value
|
|
3213
3269
|
self.last_execution_succeeded = False
|
|
@@ -3318,11 +3374,73 @@ class InteractiveShell(SingletonConfigurable):
|
|
|
3318
3374
|
# Write output to the database. Does nothing unless
|
|
3319
3375
|
# history output logging is enabled.
|
|
3320
3376
|
self.history_manager.store_output(self.execution_count)
|
|
3377
|
+
exec_count = self.execution_count
|
|
3378
|
+
if result.error_in_exec:
|
|
3379
|
+
# Store formatted traceback and error details
|
|
3380
|
+
self.history_manager.exceptions[exec_count] = (
|
|
3381
|
+
self._format_exception_for_storage(result.error_in_exec)
|
|
3382
|
+
)
|
|
3383
|
+
|
|
3321
3384
|
# Each cell is a *single* input, regardless of how many lines it has
|
|
3322
3385
|
self.execution_count += 1
|
|
3323
3386
|
|
|
3324
3387
|
return result
|
|
3325
3388
|
|
|
3389
|
+
def _format_exception_for_storage(
|
|
3390
|
+
self, exception, filename=None, running_compiled_code=False
|
|
3391
|
+
):
|
|
3392
|
+
"""
|
|
3393
|
+
Format an exception's traceback and details for storage, with special handling
|
|
3394
|
+
for different types of errors.
|
|
3395
|
+
"""
|
|
3396
|
+
etype = type(exception)
|
|
3397
|
+
evalue = exception
|
|
3398
|
+
tb = exception.__traceback__
|
|
3399
|
+
|
|
3400
|
+
# Handle SyntaxError and IndentationError with specific formatting
|
|
3401
|
+
if issubclass(etype, (SyntaxError, IndentationError)):
|
|
3402
|
+
if filename and isinstance(evalue, SyntaxError):
|
|
3403
|
+
try:
|
|
3404
|
+
evalue.filename = filename
|
|
3405
|
+
except:
|
|
3406
|
+
pass # Keep the original filename if modification fails
|
|
3407
|
+
|
|
3408
|
+
# Extract traceback if the error happened during compiled code execution
|
|
3409
|
+
elist = traceback.extract_tb(tb) if running_compiled_code else []
|
|
3410
|
+
stb = self.SyntaxTB.structured_traceback(etype, evalue, elist)
|
|
3411
|
+
|
|
3412
|
+
# Handle UsageError with a simple message
|
|
3413
|
+
elif etype is UsageError:
|
|
3414
|
+
stb = [f"UsageError: {evalue}"]
|
|
3415
|
+
|
|
3416
|
+
else:
|
|
3417
|
+
# Check if the exception (or its context) is an ExceptionGroup.
|
|
3418
|
+
def contains_exceptiongroup(val):
|
|
3419
|
+
if val is None:
|
|
3420
|
+
return False
|
|
3421
|
+
return isinstance(val, BaseExceptionGroup) or contains_exceptiongroup(
|
|
3422
|
+
val.__context__
|
|
3423
|
+
)
|
|
3424
|
+
|
|
3425
|
+
if contains_exceptiongroup(evalue):
|
|
3426
|
+
# Fallback: use the standard library's formatting for exception groups.
|
|
3427
|
+
stb = traceback.format_exception(etype, evalue, tb)
|
|
3428
|
+
else:
|
|
3429
|
+
try:
|
|
3430
|
+
# If the exception has a custom traceback renderer, use it.
|
|
3431
|
+
if hasattr(evalue, "_render_traceback_"):
|
|
3432
|
+
stb = evalue._render_traceback_()
|
|
3433
|
+
else:
|
|
3434
|
+
# Otherwise, use InteractiveTB to format the traceback.
|
|
3435
|
+
stb = self.InteractiveTB.structured_traceback(
|
|
3436
|
+
etype, evalue, tb, tb_offset=1
|
|
3437
|
+
)
|
|
3438
|
+
except Exception:
|
|
3439
|
+
# In case formatting fails, fallback to Python's built-in formatting.
|
|
3440
|
+
stb = traceback.format_exception(etype, evalue, tb)
|
|
3441
|
+
|
|
3442
|
+
return {"ename": etype.__name__, "evalue": str(evalue), "traceback": stb}
|
|
3443
|
+
|
|
3326
3444
|
def transform_cell(self, raw_cell):
|
|
3327
3445
|
"""Transform an input cell before parsing it.
|
|
3328
3446
|
|
IPython/core/magics/basic.py
CHANGED
|
@@ -21,7 +21,7 @@ class MagicsDisplay:
|
|
|
21
21
|
def __init__(self, magics_manager, ignore=None):
|
|
22
22
|
self.ignore = ignore if ignore else []
|
|
23
23
|
self.magics_manager = magics_manager
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def _lsmagic(self):
|
|
26
26
|
"""The main implementation of the %lsmagic"""
|
|
27
27
|
mesc = magic_escapes['line']
|
|
@@ -39,13 +39,13 @@ class MagicsDisplay:
|
|
|
39
39
|
|
|
40
40
|
def _repr_pretty_(self, p, cycle):
|
|
41
41
|
p.text(self._lsmagic())
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def __repr__(self):
|
|
44
44
|
return self.__str__()
|
|
45
45
|
|
|
46
46
|
def __str__(self):
|
|
47
47
|
return self._lsmagic()
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
def _jsonable(self):
|
|
50
50
|
"""turn magics dict into jsonable dict of the same structure
|
|
51
51
|
|
|
@@ -62,10 +62,10 @@ class MagicsDisplay:
|
|
|
62
62
|
classname = obj.__self__.__class__.__name__
|
|
63
63
|
except AttributeError:
|
|
64
64
|
classname = 'Other'
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
d[name] = classname
|
|
67
67
|
return magic_dict
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
def _repr_json_(self):
|
|
70
70
|
return self._jsonable()
|
|
71
71
|
|
|
@@ -561,13 +561,46 @@ Currently the magic system has the following functions:""",
|
|
|
561
561
|
|
|
562
562
|
cells = []
|
|
563
563
|
hist = list(self.shell.history_manager.get_range())
|
|
564
|
+
outputs = self.shell.history_manager.outputs
|
|
565
|
+
exceptions = self.shell.history_manager.exceptions
|
|
566
|
+
|
|
564
567
|
if(len(hist)<=1):
|
|
565
568
|
raise ValueError('History is empty, cannot export')
|
|
566
569
|
for session, execution_count, source in hist[:-1]:
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
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
|
+
|
|
571
604
|
nb = v4.new_notebook(cells=cells)
|
|
572
605
|
with io.open(outfname, "w", encoding="utf-8") as f:
|
|
573
606
|
write(nb, f, version=4)
|
IPython/core/magics/execution.py
CHANGED
|
@@ -1055,11 +1055,11 @@ class ExecutionMagics(Magics):
|
|
|
1055
1055
|
|
|
1056
1056
|
**Usage, in line mode**::
|
|
1057
1057
|
|
|
1058
|
-
%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
|
|
1058
|
+
%timeit [-n<N> -r<R> [-t|-c] -q -p<P> [-o|-v <V>]] statement
|
|
1059
1059
|
|
|
1060
1060
|
**or in cell mode**::
|
|
1061
1061
|
|
|
1062
|
-
%%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
|
|
1062
|
+
%%timeit [-n<N> -r<R> [-t|-c] -q -p<P> [-o|-v <V>]] setup_code
|
|
1063
1063
|
code
|
|
1064
1064
|
code...
|
|
1065
1065
|
|
|
@@ -1104,6 +1104,9 @@ class ExecutionMagics(Magics):
|
|
|
1104
1104
|
Return a ``TimeitResult`` that can be stored in a variable to inspect
|
|
1105
1105
|
the result in more details.
|
|
1106
1106
|
|
|
1107
|
+
-v <V>
|
|
1108
|
+
Like ``-o``, but save the ``TimeitResult`` directly to variable <V>.
|
|
1109
|
+
|
|
1107
1110
|
.. versionchanged:: 7.3
|
|
1108
1111
|
User variables are no longer expanded,
|
|
1109
1112
|
the magic line is always left unmodified.
|
|
@@ -1135,7 +1138,7 @@ class ExecutionMagics(Magics):
|
|
|
1135
1138
|
those from ``%timeit``."""
|
|
1136
1139
|
|
|
1137
1140
|
opts, stmt = self.parse_options(
|
|
1138
|
-
line, "n:r:tcp:
|
|
1141
|
+
line, "n:r:tcp:qov:", posix=False, strict=False, preserve_non_opts=True
|
|
1139
1142
|
)
|
|
1140
1143
|
if stmt == "" and cell is None:
|
|
1141
1144
|
return
|
|
@@ -1145,8 +1148,9 @@ class ExecutionMagics(Magics):
|
|
|
1145
1148
|
default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
|
|
1146
1149
|
repeat = int(getattr(opts, "r", default_repeat))
|
|
1147
1150
|
precision = int(getattr(opts, "p", 3))
|
|
1148
|
-
quiet =
|
|
1149
|
-
return_result =
|
|
1151
|
+
quiet = "q" in opts
|
|
1152
|
+
return_result = "o" in opts
|
|
1153
|
+
save_result = "v" in opts
|
|
1150
1154
|
if hasattr(opts, "t"):
|
|
1151
1155
|
timefunc = time.time
|
|
1152
1156
|
if hasattr(opts, "c"):
|
|
@@ -1207,7 +1211,7 @@ class ExecutionMagics(Magics):
|
|
|
1207
1211
|
if var_name in local_ns:
|
|
1208
1212
|
conflict_globs[var_name] = var_val
|
|
1209
1213
|
glob.update(local_ns)
|
|
1210
|
-
|
|
1214
|
+
|
|
1211
1215
|
exec(code, glob, ns)
|
|
1212
1216
|
timer.inner = ns["inner"]
|
|
1213
1217
|
|
|
@@ -1229,9 +1233,9 @@ class ExecutionMagics(Magics):
|
|
|
1229
1233
|
|
|
1230
1234
|
# Restore global vars from conflict_globs
|
|
1231
1235
|
if conflict_globs:
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
if not quiet
|
|
1236
|
+
glob.update(conflict_globs)
|
|
1237
|
+
|
|
1238
|
+
if not quiet:
|
|
1235
1239
|
# Check best timing is greater than zero to avoid a
|
|
1236
1240
|
# ZeroDivisionError.
|
|
1237
1241
|
# In cases where the slowest timing is lesser than a microsecond
|
|
@@ -1241,11 +1245,15 @@ class ExecutionMagics(Magics):
|
|
|
1241
1245
|
print("The slowest run took %0.2f times longer than the "
|
|
1242
1246
|
"fastest. This could mean that an intermediate result "
|
|
1243
1247
|
"is being cached." % (worst / best))
|
|
1244
|
-
|
|
1248
|
+
|
|
1245
1249
|
print( timeit_result )
|
|
1246
1250
|
|
|
1247
1251
|
if tc > tc_min:
|
|
1248
1252
|
print("Compiler time: %.2f s" % tc)
|
|
1253
|
+
|
|
1254
|
+
if save_result:
|
|
1255
|
+
self.shell.user_ns[opts.v] = timeit_result
|
|
1256
|
+
|
|
1249
1257
|
if return_result:
|
|
1250
1258
|
return timeit_result
|
|
1251
1259
|
|
IPython/core/release.py
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
# release. 'dev' as a _version_extra string means this is a development
|
|
17
17
|
# version
|
|
18
18
|
_version_major = 9
|
|
19
|
-
_version_minor =
|
|
20
|
-
_version_patch =
|
|
19
|
+
_version_minor = 1
|
|
20
|
+
_version_patch = 0
|
|
21
21
|
_version_extra = ".dev"
|
|
22
22
|
# _version_extra = "b2"
|
|
23
23
|
_version_extra = "" # Uncomment this for full releases
|
IPython/core/tips.py
CHANGED
|
@@ -48,7 +48,7 @@ _tips: Any = {
|
|
|
48
48
|
(
|
|
49
49
|
10,
|
|
50
50
|
11,
|
|
51
|
-
): "IPython first line of code was written {} years ago by Fernando Pérez".format(
|
|
51
|
+
): "IPython's first line of code was written {} years ago by Fernando Pérez".format(
|
|
52
52
|
datetime.now().year - 2001
|
|
53
53
|
),
|
|
54
54
|
(
|
|
@@ -60,11 +60,11 @@ _tips: Any = {
|
|
|
60
60
|
(
|
|
61
61
|
3,
|
|
62
62
|
8,
|
|
63
|
-
): "Today is
|
|
63
|
+
): "Today is International Women's Day: https://www.internationalwomensday.com/",
|
|
64
64
|
(
|
|
65
65
|
3,
|
|
66
66
|
31,
|
|
67
|
-
): "Happy
|
|
67
|
+
): "Happy International Transgender Day of Visibility! You are valid. You matter. https://en.wikipedia.org/wiki/International_Transgender_Day_of_Visibility",
|
|
68
68
|
},
|
|
69
69
|
"random": [
|
|
70
70
|
"Use `F2` or %edit with no arguments to open an empty editor with a temporary file.",
|
|
@@ -73,22 +73,22 @@ _tips: Any = {
|
|
|
73
73
|
"Use the IPython.lib.demo.Demo class to load any Python script as an interactive demo.",
|
|
74
74
|
"Put a ';' at the end of a line to suppress the printing of output.",
|
|
75
75
|
"You can use Ctrl-O to force a new line in terminal IPython",
|
|
76
|
-
"Use `object?` to see the help on `object`, `object??` to view
|
|
76
|
+
"Use `object?` to see the help on `object`, `object??` to view its source",
|
|
77
77
|
"`?` alone on a line will brings up IPython's help",
|
|
78
78
|
"You can use `%hist` to view history, see the options with `%history?`",
|
|
79
79
|
"You can change the editing mode of IPython to behave more like vi, or emacs.",
|
|
80
|
-
"IPython 9.0+
|
|
80
|
+
"IPython 9.0+ has hooks to integrate AI/LLM completions.",
|
|
81
81
|
"Use `%timeit` or `%%timeit`, and the `-r`, `-n`, and `-o` options to easily profile your code.",
|
|
82
|
-
"Use `ipython --help-all | less` to view all the IPython
|
|
83
|
-
"Use `--theme`, or the `%colors` magic to change
|
|
84
|
-
"The `%timeit` magic has
|
|
82
|
+
"Use `ipython --help-all | less` to view all the IPython configuration options.",
|
|
83
|
+
"Use `--theme`, or the `%colors` magic to change IPython's themes and colors.",
|
|
84
|
+
"The `%timeit` magic has a `-o` flag, which returns the results, making it easy to plot. See `%timeit?`.",
|
|
85
85
|
],
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
if os.name == "nt":
|
|
89
89
|
_tips["random"].extend(
|
|
90
90
|
[
|
|
91
|
-
"We can't show you all tips on
|
|
91
|
+
"We can't show you all tips on Windows as sometimes Unicode characters crash the Windows console, please help us debug it."
|
|
92
92
|
]
|
|
93
93
|
)
|
|
94
94
|
# unicode may crash windows console, so we filter out tips with non-ASCII characters.
|
|
@@ -100,10 +100,10 @@ if os.name == "nt":
|
|
|
100
100
|
else:
|
|
101
101
|
_tips["random"].extend(
|
|
102
102
|
[
|
|
103
|
-
"You can use
|
|
104
|
-
"You can find how to type a
|
|
105
|
-
"You can find how to type a
|
|
106
|
-
"IPython
|
|
103
|
+
"You can use LaTeX or Unicode completion, `\\alpha<tab>` will insert the α symbol.",
|
|
104
|
+
"You can find how to type a LaTeX symbol by back-completing it, eg `\\θ<tab>` will expand to `\\theta`.",
|
|
105
|
+
"You can find how to type a Unicode symbol by back-completing it, eg `\\Ⅷ<tab>` will expand to `\\ROMAN NUMERAL EIGHT`.",
|
|
106
|
+
"IPython supports combining unicode identifiers, eg F\\vec<tab> will become F⃗, useful for physics equations. Play with \\dot \\ddot and others.",
|
|
107
107
|
]
|
|
108
108
|
)
|
|
109
109
|
|
IPython/terminal/embed.py
CHANGED
|
@@ -395,12 +395,13 @@ def embed(*, header="", compile_flags=None, **kwargs):
|
|
|
395
395
|
config.InteractiveShellEmbed = config.TerminalInteractiveShell
|
|
396
396
|
kwargs["config"] = config
|
|
397
397
|
using = kwargs.get("using", "sync")
|
|
398
|
+
colors = kwargs.pop("colors", "nocolor")
|
|
398
399
|
if using:
|
|
399
400
|
kwargs["config"].update(
|
|
400
401
|
{
|
|
401
402
|
"TerminalInteractiveShell": {
|
|
402
403
|
"loop_runner": using,
|
|
403
|
-
"colors":
|
|
404
|
+
"colors": colors,
|
|
404
405
|
"autoawait": using != "sync",
|
|
405
406
|
}
|
|
406
407
|
}
|
|
@@ -355,7 +355,7 @@ class TerminalInteractiveShell(InteractiveShell):
|
|
|
355
355
|
return
|
|
356
356
|
|
|
357
357
|
def refresh_style(self):
|
|
358
|
-
self._style = self._make_style_from_name_or_cls(
|
|
358
|
+
self._style = self._make_style_from_name_or_cls("legacy")
|
|
359
359
|
|
|
360
360
|
# TODO: deprecate this
|
|
361
361
|
highlighting_style_overrides = Dict(
|
|
@@ -518,7 +518,6 @@ class TerminalInteractiveShell(InteractiveShell):
|
|
|
518
518
|
name = self.llm_prefix_from_history
|
|
519
519
|
|
|
520
520
|
if name == "no_prefix":
|
|
521
|
-
print("set tofun1", self.llm_prefix_from_history)
|
|
522
521
|
|
|
523
522
|
def no_prefix(history_manager):
|
|
524
523
|
return ""
|
|
@@ -974,7 +973,7 @@ class TerminalInteractiveShell(InteractiveShell):
|
|
|
974
973
|
self.alias_manager.soft_define_alias(cmd, cmd)
|
|
975
974
|
|
|
976
975
|
def __init__(self, *args, **kwargs) -> None:
|
|
977
|
-
super(
|
|
976
|
+
super().__init__(*args, **kwargs)
|
|
978
977
|
self._set_autosuggestions(self.autosuggestions_provider)
|
|
979
978
|
self.init_prompt_toolkit_cli()
|
|
980
979
|
self.init_term_title()
|
|
@@ -9,7 +9,7 @@ import prompt_toolkit
|
|
|
9
9
|
from prompt_toolkit.buffer import Buffer
|
|
10
10
|
from prompt_toolkit.key_binding import KeyPressEvent
|
|
11
11
|
from prompt_toolkit.key_binding.bindings import named_commands as nc
|
|
12
|
-
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory, Suggestion
|
|
12
|
+
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory, Suggestion
|
|
13
13
|
from prompt_toolkit.document import Document
|
|
14
14
|
from prompt_toolkit.history import History
|
|
15
15
|
from prompt_toolkit.shortcuts import PromptSession
|
|
@@ -103,9 +103,6 @@ class AppendAutoSuggestionInAnyLine(Processor):
|
|
|
103
103
|
if len(suggestions) == 0:
|
|
104
104
|
return noop("noop: no suggestions")
|
|
105
105
|
|
|
106
|
-
suggestions_longer_than_buffer: bool = (
|
|
107
|
-
len(suggestions) + ti.document.cursor_position_row > ti.document.line_count
|
|
108
|
-
)
|
|
109
106
|
if prompt_toolkit.VERSION < (3, 0, 49):
|
|
110
107
|
if len(suggestions) > 1 and prompt_toolkit.VERSION < (3, 0, 49):
|
|
111
108
|
if ti.lineno == ti.document.cursor_position_row:
|
|
@@ -132,7 +129,6 @@ class AppendAutoSuggestionInAnyLine(Processor):
|
|
|
132
129
|
return Transformation(fragments=ti.fragments + [(self.style, suggestion)])
|
|
133
130
|
if is_last_line:
|
|
134
131
|
if delta < len(suggestions):
|
|
135
|
-
extra = f"; {len(suggestions) - delta} line(s) hidden"
|
|
136
132
|
suggestion = f"… rest of suggestion ({len(suggestions) - delta} lines) and code hidden"
|
|
137
133
|
return Transformation([(self.style, suggestion)])
|
|
138
134
|
|
|
@@ -171,7 +167,7 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
171
167
|
_connected_apps: list[PromptSession]
|
|
172
168
|
|
|
173
169
|
# handle to the currently running llm task that appends suggestions to the
|
|
174
|
-
# current buffer; we keep a handle to it in order to
|
|
170
|
+
# current buffer; we keep a handle to it in order to cancel it when there is a cursor movement, or
|
|
175
171
|
# another request.
|
|
176
172
|
_llm_task: asyncio.Task | None = None
|
|
177
173
|
|
|
@@ -185,6 +181,7 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
185
181
|
self.skip_lines = 0
|
|
186
182
|
self._connected_apps = []
|
|
187
183
|
self._llm_provider = None
|
|
184
|
+
self._request_number = 0
|
|
188
185
|
|
|
189
186
|
def reset_history_position(self, _: Buffer) -> None:
|
|
190
187
|
self.skip_lines = 0
|
|
@@ -306,7 +303,7 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
306
303
|
|
|
307
304
|
def _cancel_running_llm_task(self) -> None:
|
|
308
305
|
"""
|
|
309
|
-
Try to
|
|
306
|
+
Try to cancel the currently running llm_task if exists, and set it to None.
|
|
310
307
|
"""
|
|
311
308
|
if self._llm_task is not None:
|
|
312
309
|
if self._llm_task.done():
|
|
@@ -350,10 +347,10 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
350
347
|
try:
|
|
351
348
|
await self._trigger_llm_core(buffer)
|
|
352
349
|
except Exception as e:
|
|
353
|
-
get_ipython().log.error("error")
|
|
350
|
+
get_ipython().log.error("error %s", e)
|
|
354
351
|
raise
|
|
355
352
|
|
|
356
|
-
# here we need a cancellable task so we can't just await the error
|
|
353
|
+
# here we need a cancellable task so we can't just await the error caught
|
|
357
354
|
self._llm_task = asyncio.create_task(error_catcher(buffer))
|
|
358
355
|
await self._llm_task
|
|
359
356
|
|
|
@@ -365,9 +362,8 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
365
362
|
provider to stream it's response back to us iteratively setting it as
|
|
366
363
|
the suggestion on the current buffer.
|
|
367
364
|
|
|
368
|
-
Unlike with JupyterAi, as we do not have multiple cell, the cell
|
|
369
|
-
is always set to `
|
|
370
|
-
time and ignore threply from past numbers.
|
|
365
|
+
Unlike with JupyterAi, as we do not have multiple cell, the cell id
|
|
366
|
+
is always set to `None`.
|
|
371
367
|
|
|
372
368
|
We set the prefix to the current cell content, but could also inset the
|
|
373
369
|
rest of the history or even just the non-fail history.
|
|
@@ -389,10 +385,12 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
389
385
|
|
|
390
386
|
hm = buffer.history.shell.history_manager
|
|
391
387
|
prefix = self._llm_prefixer(hm)
|
|
392
|
-
|
|
388
|
+
get_ipython().log.debug("prefix: %s", prefix)
|
|
393
389
|
|
|
390
|
+
self._request_number += 1
|
|
391
|
+
request_number = self._request_number
|
|
394
392
|
request = jai_models.InlineCompletionRequest(
|
|
395
|
-
number=
|
|
393
|
+
number=request_number,
|
|
396
394
|
prefix=prefix + buffer.document.text,
|
|
397
395
|
suffix="",
|
|
398
396
|
mime="text/x-python",
|
|
@@ -405,6 +403,9 @@ class NavigableAutoSuggestFromHistory(AutoSuggestFromHistory):
|
|
|
405
403
|
async for reply_and_chunks in self._llm_provider.stream_inline_completions(
|
|
406
404
|
request
|
|
407
405
|
):
|
|
406
|
+
if self._request_number != request_number:
|
|
407
|
+
# If a new suggestion was requested, skip processing this one.
|
|
408
|
+
return
|
|
408
409
|
if isinstance(reply_and_chunks, jai_models.InlineCompletionReply):
|
|
409
410
|
if len(reply_and_chunks.list.items) > 1:
|
|
410
411
|
raise ValueError(
|
|
@@ -427,7 +428,7 @@ async def llm_autosuggestion(event: KeyPressEvent):
|
|
|
427
428
|
This will first make sure that the current buffer have _MIN_LINES (7)
|
|
428
429
|
available lines to insert the LLM completion
|
|
429
430
|
|
|
430
|
-
Provisional as of 8.32, may change without
|
|
431
|
+
Provisional as of 8.32, may change without warnings
|
|
431
432
|
|
|
432
433
|
"""
|
|
433
434
|
_MIN_LINES = 5
|
IPython/utils/PyColorize.py
CHANGED
|
@@ -47,6 +47,7 @@ class Theme:
|
|
|
47
47
|
self.base = base
|
|
48
48
|
self.extra_style = extra_style
|
|
49
49
|
self.symbols = {**_default_symbols, **symbols}
|
|
50
|
+
self._formatter = Terminal256Formatter(style=self.as_pygments_style())
|
|
50
51
|
|
|
51
52
|
@cache
|
|
52
53
|
def as_pygments_style(self):
|
|
@@ -61,9 +62,8 @@ class Theme:
|
|
|
61
62
|
return MyStyle
|
|
62
63
|
|
|
63
64
|
def format(self, stream: TokenStream) -> str:
|
|
64
|
-
style = self.as_pygments_style()
|
|
65
65
|
|
|
66
|
-
return pygments.format(stream,
|
|
66
|
+
return pygments.format(stream, self._formatter)
|
|
67
67
|
|
|
68
68
|
def make_arrow(self, width: int):
|
|
69
69
|
"""generate the leading arrow in front of traceback or debugger"""
|
IPython/utils/_sysinfo.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# GENERATED BY setup.py
|
|
2
|
-
commit = "
|
|
2
|
+
commit = "f9097f68a"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ipython
|
|
3
|
-
Version: 9.0
|
|
3
|
+
Version: 9.1.0
|
|
4
4
|
Summary: IPython: Productive Interactive Computing
|
|
5
5
|
Author: The IPython Development Team
|
|
6
6
|
Author-email: ipython-dev@python.org
|
|
7
7
|
License: BSD-3-Clause
|
|
8
8
|
Project-URL: Homepage, https://ipython.org
|
|
9
9
|
Project-URL: Documentation, https://ipython.readthedocs.io/
|
|
10
|
-
Project-URL: Funding, https://
|
|
10
|
+
Project-URL: Funding, https://jupyter.org/about#donate
|
|
11
11
|
Project-URL: Source, https://github.com/ipython/ipython
|
|
12
12
|
Project-URL: Tracker, https://github.com/ipython/ipython/issues
|
|
13
13
|
Keywords: Interactive,Interpreter,Shell,Embedding
|
|
@@ -59,8 +59,11 @@ Requires-Dist: packaging; extra == "test"
|
|
|
59
59
|
Provides-Extra: test-extra
|
|
60
60
|
Requires-Dist: ipython[test]; extra == "test-extra"
|
|
61
61
|
Requires-Dist: curio; extra == "test-extra"
|
|
62
|
+
Requires-Dist: jupyter_ai; extra == "test-extra"
|
|
62
63
|
Requires-Dist: matplotlib!=3.2.0; extra == "test-extra"
|
|
63
64
|
Requires-Dist: nbformat; extra == "test-extra"
|
|
65
|
+
Requires-Dist: nbclient; extra == "test-extra"
|
|
66
|
+
Requires-Dist: ipykernel; extra == "test-extra"
|
|
64
67
|
Requires-Dist: numpy>=1.23; extra == "test-extra"
|
|
65
68
|
Requires-Dist: pandas; extra == "test-extra"
|
|
66
69
|
Requires-Dist: trio; extra == "test-extra"
|
|
@@ -71,6 +74,7 @@ Requires-Dist: ipython[doc,matplotlib,test,test_extra]; extra == "all"
|
|
|
71
74
|
Dynamic: author
|
|
72
75
|
Dynamic: author-email
|
|
73
76
|
Dynamic: license
|
|
77
|
+
Dynamic: license-file
|
|
74
78
|
|
|
75
79
|
IPython provides a rich toolkit to help you make the most out of using Python
|
|
76
80
|
interactively. Its main components are:
|
|
@@ -10,15 +10,15 @@ IPython/core/async_helpers.py,sha256=4x_ZSrPImXi0oXzwImaLc3eXlkdLi-4RXh2HcX8YDQg
|
|
|
10
10
|
IPython/core/autocall.py,sha256=zw7siKc1ocagCuXn4OuT0o7YbyZSuW3a7la204ANRk4,1983
|
|
11
11
|
IPython/core/builtin_trap.py,sha256=4Bls1x1Xaf3oGbj6GFXE--G6qZlNq7AYFjp_vyu55p8,3006
|
|
12
12
|
IPython/core/compilerop.py,sha256=tA8xHh10gp85brI2OYmvl7kW0TgDghdKbzmZE7nS4sw,6990
|
|
13
|
-
IPython/core/completer.py,sha256=
|
|
13
|
+
IPython/core/completer.py,sha256=X9gKNDyuOsDgdr4dDnFNdhyAlcFrCnHR-DwPZwj9rNc,126652
|
|
14
14
|
IPython/core/completerlib.py,sha256=C_1uFwR4eiqIsemMRbluMQV1WJ3qSfnGxO01PsGSpr8,12641
|
|
15
15
|
IPython/core/crashhandler.py,sha256=8-kyI6aNkqbaB_lBlbNKAOFv34HDBCpLggMfiu4oIDg,8747
|
|
16
16
|
IPython/core/debugger.py,sha256=I3LA4HQFEP5cy-kbbRvJqlLlSgVHSWBbp0cbPs3nU8M,41806
|
|
17
17
|
IPython/core/display.py,sha256=wQgVFY_U1O-a-jJSLb00nJ9m2w9-NsBhEBGnQUcWUd0,41129
|
|
18
18
|
IPython/core/display_functions.py,sha256=hlj1gXXrcIQU_ita03dHFesltOCViP1N3RcoLtLuyFI,12407
|
|
19
|
-
IPython/core/display_trap.py,sha256=
|
|
20
|
-
IPython/core/displayhook.py,sha256=
|
|
21
|
-
IPython/core/displaypub.py,sha256=
|
|
19
|
+
IPython/core/display_trap.py,sha256=r9AeMqllLicJvY8JfrGTQMkyxz37QT7X_RwwXxNk7R0,2185
|
|
20
|
+
IPython/core/displayhook.py,sha256=pArnwIsvICOivqoxLqg215F9O1V3NEEWnk8KktvYcvE,13258
|
|
21
|
+
IPython/core/displaypub.py,sha256=6i3-uceIUZ_ceqXiEr8RiPWebhoLiRObXk_cXvO84xo,5946
|
|
22
22
|
IPython/core/doctb.py,sha256=WTEOyUTAAnpyB2NCHhCA4fF7TyDRlW6H9tyRsoVVPjA,15617
|
|
23
23
|
IPython/core/error.py,sha256=lL5WP3E0sGNWkBTQL0u795wLQJCSrDCf328ft8TfCjk,1734
|
|
24
24
|
IPython/core/events.py,sha256=U-Qm93khPgrLrB09zqH8Hvb6QldPVES-LIuSdGsxLXk,5243
|
|
@@ -26,11 +26,11 @@ IPython/core/extensions.py,sha256=KgohNiowl71W-V0WYXWKw7g-q85QN9c_FxtraJoEOvY,50
|
|
|
26
26
|
IPython/core/formatters.py,sha256=9hyrvbkIxbO26VQvOsKVI3xbnLgJOAmJiQUo8U95V6k,36500
|
|
27
27
|
IPython/core/getipython.py,sha256=RjTylt9N3c8AFZ-Y440A8My4tfFCgO-lVkyOL0xoOzQ,894
|
|
28
28
|
IPython/core/guarded_eval.py,sha256=dQXW-e3wM6z9WGcszdJLhqiK0UCii303GOOXd3z3ze8,29400
|
|
29
|
-
IPython/core/history.py,sha256=
|
|
30
|
-
IPython/core/historyapp.py,sha256=
|
|
29
|
+
IPython/core/history.py,sha256=5hmGOe1H93tCtWj_d8HdFixDCr0kdEqahGJ-zUo03RQ,41183
|
|
30
|
+
IPython/core/historyapp.py,sha256=5H38INsWXRacscKz_5PQHYrEnHEayDtc1D1qcSyHRBU,5847
|
|
31
31
|
IPython/core/hooks.py,sha256=xBWTZqycxZi97yj01IFc-SoJBzV5B73IoDHbAAlKUpQ,5193
|
|
32
32
|
IPython/core/inputtransformer2.py,sha256=7sRleytrcAbp5PZMOrDw59MjUAGXg5BbaRbPkSW83-I,28909
|
|
33
|
-
IPython/core/interactiveshell.py,sha256=
|
|
33
|
+
IPython/core/interactiveshell.py,sha256=W6T0ImqgQShGLXjnx2-7t1cyJBVJz_WsZb3rlDw5BcU,158899
|
|
34
34
|
IPython/core/latex_symbols.py,sha256=DzFecvqWVSsdN7vWAsp0mlYAHRDQKfZGAmvuDUh0M-s,30127
|
|
35
35
|
IPython/core/logger.py,sha256=Iwe4xKMmxEdvSwHYPMfsTWkmdaqVCgvZT3R3I3qTmrU,8436
|
|
36
36
|
IPython/core/macro.py,sha256=OhvXWNhLe393rI2wTpMgbUVHWSnmC_ycHiYqzqSHXZU,1726
|
|
@@ -44,21 +44,21 @@ IPython/core/prefilter.py,sha256=JHQ3feaD4bhoBDqZcEgmlDjQ2sfRXC1DNjgJhpaMU7E,257
|
|
|
44
44
|
IPython/core/profileapp.py,sha256=bFMFIyehxeF9pDUtxw_6D3b0nxeqsupKTe7XhH7GMkc,10711
|
|
45
45
|
IPython/core/profiledir.py,sha256=-vjOa1I_UajMZJblJRYXh16Y0RaAUn5a2swQBsw2qEU,8459
|
|
46
46
|
IPython/core/pylabtools.py,sha256=LfNV9xCJ3flCfJXmv1NaCRYj9jZDtHAQ5oSEHWo3Gmg,17376
|
|
47
|
-
IPython/core/release.py,sha256=
|
|
47
|
+
IPython/core/release.py,sha256=XcLV70aE1VVBrEWoihRzaJS3zSNXH3BAqhmKVKu4BY8,1505
|
|
48
48
|
IPython/core/shellapp.py,sha256=oZIzj_sqIXrN3qyyhinZ1gLXvFviKYHkmS4H3wVEb74,19307
|
|
49
49
|
IPython/core/splitinput.py,sha256=bAX1puQjvYB-otJyqiqeOhWj6dooWuQeNVx2YdaKQs8,5006
|
|
50
50
|
IPython/core/tbtools.py,sha256=X4iB5zKAT2y4TK1R9l3d3kiW5htrzKn3qxalFFe2xzI,16880
|
|
51
|
-
IPython/core/tips.py,sha256=
|
|
51
|
+
IPython/core/tips.py,sha256=oLWJtS_nnd2s1fQunXXvvHxItmbtargZWPCkr5mVGj8,6200
|
|
52
52
|
IPython/core/ultratb.py,sha256=ItaUt56wPnptv6f5ecbcBR3FtHljTDoIRHKsU-ZWGqI,46265
|
|
53
53
|
IPython/core/usage.py,sha256=agrZE5eZIvJnXoqI8VV9e-oWZx5LbLxUq9MdQpEyts4,13542
|
|
54
54
|
IPython/core/magics/__init__.py,sha256=pkd-UfzjDGp5UHuFKjw192vZnigpTP9ftXzG3oLdiS8,1619
|
|
55
55
|
IPython/core/magics/ast_mod.py,sha256=06OoRO7Z7Jzfc-cflf8Z3wyqF17fkYv6fJ_Nw4d7eQE,10295
|
|
56
56
|
IPython/core/magics/auto.py,sha256=yEouIjsQ6LmfSEfNvkZbNmNDFl19KLRnaJciYdR7a1A,4816
|
|
57
|
-
IPython/core/magics/basic.py,sha256=
|
|
57
|
+
IPython/core/magics/basic.py,sha256=uFkd-gTzlSVkNDSu8Rg4fbS_IK2raEhx1SYA6kWZ4hg,23968
|
|
58
58
|
IPython/core/magics/code.py,sha256=h_dho9niPvtf_IpoOZf5GAD6CYbT0EQGsfLfutyX-7I,28144
|
|
59
59
|
IPython/core/magics/config.py,sha256=QBL5uY7m-Q7C46mO3q1Yio9s73w1TnI9y__j5E-j44Y,4881
|
|
60
60
|
IPython/core/magics/display.py,sha256=STRq66GlZwcvFyBxbkqslclpP_s9LnqD0ew9Z3S4-Jo,3130
|
|
61
|
-
IPython/core/magics/execution.py,sha256=
|
|
61
|
+
IPython/core/magics/execution.py,sha256=eKILRIhGdzKPI2jauYMkmhXFoDh88Y-YHaRhetDccLI,62070
|
|
62
62
|
IPython/core/magics/extension.py,sha256=Jj6OlkM71PS0j1HfEMDc-jU2Exwo9Ff_K0nD7e_W4N0,2477
|
|
63
63
|
IPython/core/magics/history.py,sha256=Aw9gBzK4AJbe-gvRdMW7n-_zxxHuMyHvHJtRDuCwwug,12629
|
|
64
64
|
IPython/core/magics/logging.py,sha256=VuDiF5QZrgzTT7Lr1NkkMCtUM1EHoGCw2pYlKsSQc4Q,6867
|
|
@@ -95,8 +95,8 @@ IPython/sphinxext/ipython_console_highlighting.py,sha256=VzlykN7guz3dQV9nFuZM_x2
|
|
|
95
95
|
IPython/sphinxext/ipython_directive.py,sha256=hOQCdWx2N7WzBJVHMw7qVvAwLJxBZJxFCElqR4uXvqY,45154
|
|
96
96
|
IPython/terminal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
97
|
IPython/terminal/debugger.py,sha256=0LdBmCKVHKNGpmBKdb4bBgKlyuTVyfz2Dg2Y8wE4FTM,6937
|
|
98
|
-
IPython/terminal/embed.py,sha256=
|
|
99
|
-
IPython/terminal/interactiveshell.py,sha256=
|
|
98
|
+
IPython/terminal/embed.py,sha256=uR1Z7wp5z5SpYto7sa9A63sPDtX5h0XD048Y3gDE_V0,16164
|
|
99
|
+
IPython/terminal/interactiveshell.py,sha256=QdoTKJmFHEIVBG9COJkpzbU4HgILzCXfR8DmsFEJmic,39820
|
|
100
100
|
IPython/terminal/ipapp.py,sha256=d2Rog4DRkVv0_fReqZOuorKMXAtEqsCskwPejtjj0Lg,12512
|
|
101
101
|
IPython/terminal/magics.py,sha256=49ZVJzbAUkG_EFpebxIBEqm3tEClvqefoeM6QnxGrrk,7705
|
|
102
102
|
IPython/terminal/prompts.py,sha256=5IoXb-pXA4MWu3gAfEuyIwZUbDg6mxxJuMkOqRBmYa0,4555
|
|
@@ -114,7 +114,7 @@ IPython/terminal/pt_inputhooks/tk.py,sha256=FjejvtwbvpeBZLoBCci1RDo_jWD5qElMy7PP
|
|
|
114
114
|
IPython/terminal/pt_inputhooks/wx.py,sha256=9yI52lDSZ3O_5Gww_3IeenEk_3PepLIME3Onh4X3kW0,7126
|
|
115
115
|
IPython/terminal/shortcuts/__init__.py,sha256=irSX9mwHzeLDQ95fXRGdZxduRknwATtESvm2NIov7KU,18563
|
|
116
116
|
IPython/terminal/shortcuts/auto_match.py,sha256=9uT1fDb-c4Ew7TSIs_zET1jSxDlbfWGluxfW_pj39tk,3066
|
|
117
|
-
IPython/terminal/shortcuts/auto_suggest.py,sha256=
|
|
117
|
+
IPython/terminal/shortcuts/auto_suggest.py,sha256=9ecW0Su5xSuwl2wzbnflTLZJ1p97DjlwnvZ7h2U5-as,23163
|
|
118
118
|
IPython/terminal/shortcuts/filters.py,sha256=MgRTQWq8YfIyWvMASuQ9BGKq5RQwiEY5trSyMnMtJAo,10998
|
|
119
119
|
IPython/testing/__init__.py,sha256=9t97XO03Ez9GdZA5FWZYmfyHZt2c3AqQe2dj_0AiPJY,784
|
|
120
120
|
IPython/testing/decorators.py,sha256=0MmtdZsh0EehAIV73V3hTCM9gr-elFr4QTRP7sJqPc8,4430
|
|
@@ -134,7 +134,7 @@ IPython/testing/plugin/test_example.txt,sha256=CGM8aZIYHlePDdAnR1yX3MfDGu0OceZpU
|
|
|
134
134
|
IPython/testing/plugin/test_exampleip.txt,sha256=5gLcj8iCk-WCOGz0ObpQpuZMhGwS1jUMyH3mouGxQJI,814
|
|
135
135
|
IPython/testing/plugin/test_ipdoctest.py,sha256=Lc3qQdZ3amXf9EKA7JlXf30b3BzP8RwdNS9-SMRe2P0,1907
|
|
136
136
|
IPython/testing/plugin/test_refs.py,sha256=y-Y2Q8niRIbaanbwpIzvEwwaHkJfAq10HYfb4bAXHBc,715
|
|
137
|
-
IPython/utils/PyColorize.py,sha256=
|
|
137
|
+
IPython/utils/PyColorize.py,sha256=crC0QJ6WwmXD-5YfVtT2MJHGzUtizfZaubrs2ZAL7KU,15573
|
|
138
138
|
IPython/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
139
|
IPython/utils/_process_cli.py,sha256=tJWYMEgNYgeMx9v-n3YLbKW0tPbFtpczfDH28RC3n4A,2020
|
|
140
140
|
IPython/utils/_process_common.py,sha256=hMFRGOJh-n-uBcSAOnr2qetQXAthMVpS8mwRcZuQqlo,7306
|
|
@@ -142,7 +142,7 @@ IPython/utils/_process_emscripten.py,sha256=lGLQb2IgmanNtb502KflfuKIhgOF119Ji3cw
|
|
|
142
142
|
IPython/utils/_process_posix.py,sha256=aOEtguhS3vdWngBpws1XQURO8Ozqd5gRiCk9VLky6tA,7502
|
|
143
143
|
IPython/utils/_process_win32.py,sha256=Pcf6ZiqMbqDT79edzegE_AX3D367UtE8bbhT41no54A,6775
|
|
144
144
|
IPython/utils/_process_win32_controller.py,sha256=hi2eR7mLbl3TTMCVbgps85GppxdtYbhOYK_l13WvYaM,21343
|
|
145
|
-
IPython/utils/_sysinfo.py,sha256=
|
|
145
|
+
IPython/utils/_sysinfo.py,sha256=X56pgylat0KRjRqiH-0qv-TF0np8n9Kytjg4vfzVfBI,45
|
|
146
146
|
IPython/utils/capture.py,sha256=h5yL5Lxq8bgO1SFpoNDYjEi6mh1IW_2X9CE7vOsUxE4,5137
|
|
147
147
|
IPython/utils/coloransi.py,sha256=CML-SkzLa7oaIK1qypb3uwcfPXDeKHxZQiMJ0IWvUY0,293
|
|
148
148
|
IPython/utils/contexts.py,sha256=w5_uXc0WTU3KKV1kcCW9A0_Mz5mGRoeGWMq_P_eo-Dg,1610
|
|
@@ -174,11 +174,11 @@ IPython/utils/text.py,sha256=6s-y4KvDmnJxLs0urf5D-1auZGSnj2xmXgQ-9jVu0N8,18788
|
|
|
174
174
|
IPython/utils/timing.py,sha256=nND-ZUBkHWfYevvbRG-YfOSIFczz_epzMqWK5PH6nqA,4275
|
|
175
175
|
IPython/utils/tokenutil.py,sha256=x6KQ6ZCGOY7j5GQcr7byJRZSBFgyBcfkTiLtjxkl9f8,6552
|
|
176
176
|
IPython/utils/wildcard.py,sha256=6EEc3OEYp-IuSoidL6nwpaHg--GxnzbAJTmFiz77CNE,4612
|
|
177
|
-
ipython-9.0.
|
|
178
|
-
ipython-9.0.
|
|
179
|
-
ipython-9.0.
|
|
180
|
-
ipython-9.0.
|
|
181
|
-
ipython-9.0.
|
|
182
|
-
ipython-9.0.
|
|
183
|
-
ipython-9.0.
|
|
184
|
-
ipython-9.0.
|
|
177
|
+
ipython-9.1.0.data/data/share/man/man1/ipython.1,sha256=PVdQP2hHmHyUEwzLOPcgavnCe9jTDVrM1jKZt4cnF_Q,2058
|
|
178
|
+
ipython-9.1.0.dist-info/licenses/COPYING.rst,sha256=NBr8vXKYh7cEb-e5j8T07f867Y048G7v2bMGcPBD3xc,1639
|
|
179
|
+
ipython-9.1.0.dist-info/licenses/LICENSE,sha256=4OOQdI7UQKuJPKHxNaiKkgqvVAnbuQpbQnx1xeUSaPs,1720
|
|
180
|
+
ipython-9.1.0.dist-info/METADATA,sha256=FYcWyhwJGVxHfAZZkEYIalF34kXVo3AIhLmxW6wvDr4,4431
|
|
181
|
+
ipython-9.1.0.dist-info/WHEEL,sha256=yXGKzRL_Pyu4U5B7OsZI5LuVpv54e1VlLBvthN9VZ6E,90
|
|
182
|
+
ipython-9.1.0.dist-info/entry_points.txt,sha256=z5BEEohWgg0SHdgdeNABf4T3fu-lr9W6F_bWOQHLdVs,83
|
|
183
|
+
ipython-9.1.0.dist-info/top_level.txt,sha256=PKjvHtNCBZ9EHTmd2mwJ1J_k3j0F6D1lTFzIcJFFPEU,8
|
|
184
|
+
ipython-9.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|