Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0cb9d18

Browse files
authored
Merge branch 'main' into debugger-ignore-modules
2 parents 21de9fc + fb1fdbf commit 0cb9d18

27 files changed

Lines changed: 534 additions & 148 deletions

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111

1212
steps:
13-
- uses: actions/checkout@v4
13+
- uses: actions/checkout@v5
1414
- name: Set up Python
1515
uses: actions/setup-python@v5
1616
with:

.github/workflows/downstream.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
python-version: "3.13"
3030

3131
steps:
32-
- uses: actions/checkout@v4
32+
- uses: actions/checkout@v5
3333
- name: Set up Python ${{ matrix.python-version }}
3434
uses: actions/setup-python@v5
3535
with:
@@ -88,4 +88,4 @@ jobs:
8888
- name: Test pyflyby (IPython integration only)
8989
run: |
9090
cd ../pyflyby
91-
pytest tests/test_interactive.py -k 'not test_timeit_complete_autoimport_member_1'
91+
pytest tests/test_interactive.py

.github/workflows/mypy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
python-version: ["3.x"]
1919

2020
steps:
21-
- uses: actions/checkout@v4
21+
- uses: actions/checkout@v5
2222
- name: Set up Python ${{ matrix.python-version }}
2323
uses: actions/setup-python@v5
2424
with:

.github/workflows/nightly-wheel-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
if: github.event_name != 'pull_request' && (github.event_name != 'schedule' || github.repository_owner == 'ipython')
1414

1515
steps:
16-
- uses: actions/checkout@v4
16+
- uses: actions/checkout@v5
1717
- name: Set up Python
1818
uses: actions/setup-python@v5
1919
with:

.github/workflows/python-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ubuntu-latest
1919
timeout-minutes: 5
2020
steps:
21-
- uses: actions/checkout@v4
21+
- uses: actions/checkout@v5
2222
with:
2323
fetch-depth: 0
2424
- name: Set up Python

.github/workflows/ruff.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
python-version: ["3.x"]
1919

2020
steps:
21-
- uses: actions/checkout@v4
21+
- uses: actions/checkout@v5
2222
- name: Set up Python ${{ matrix.python-version }}
2323
uses: actions/setup-python@v5
2424
with:

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
want-latest-entry-point-code: true
5858

5959
steps:
60-
- uses: actions/checkout@v4
60+
- uses: actions/checkout@v5
6161
- name: Set up Python ${{ matrix.python-version }}
6262
uses: actions/setup-python@v5
6363
with:

IPython/core/completer.py

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@
218218
EvaluationContext,
219219
_validate_policy_overrides,
220220
)
221-
from IPython.core.error import TryNext
221+
from IPython.core.error import TryNext, UsageError
222222
from IPython.core.inputtransformer2 import ESC_MAGIC
223223
from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
224224
from IPython.testing.skipdoctest import skip_doctest
@@ -1219,6 +1219,10 @@ def _strip_code_before_operator(self, code: str) -> str:
12191219
else:
12201220
return code
12211221

1222+
def _extract_code(self, line: str):
1223+
"""No-op in Completer, but can be used in subclasses to customise behaviour"""
1224+
return line
1225+
12221226
def _attr_matches(
12231227
self, text: str, include_prefix: bool = True
12241228
) -> tuple[Sequence[str], str]:
@@ -2244,6 +2248,57 @@ def file_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
22442248
"suppress": False,
22452249
}
22462250

2251+
def _extract_code(self, line: str) -> str:
2252+
"""Extract code from magics if any."""
2253+
2254+
if not line:
2255+
return line
2256+
maybe_magic, *rest = line.split(maxsplit=1)
2257+
if not rest:
2258+
return line
2259+
args = rest[0]
2260+
known_magics = self.shell.magics_manager.lsmagic()
2261+
line_magics = known_magics["line"]
2262+
magic_name = maybe_magic.lstrip(self.magic_escape)
2263+
if magic_name not in line_magics:
2264+
return line
2265+
2266+
if not maybe_magic.startswith(self.magic_escape):
2267+
all_variables = [*self.namespace.keys(), *self.global_namespace.keys()]
2268+
if magic_name in all_variables:
2269+
# short circuit if we see a line starting with say `time`
2270+
# but time is defined as a variable (in addition to being
2271+
# a magic). In these cases users need to use explicit `%time`.
2272+
return line
2273+
2274+
magic_method = line_magics[magic_name]
2275+
2276+
try:
2277+
if magic_name == "timeit":
2278+
opts, stmt = magic_method.__self__.parse_options(
2279+
args,
2280+
"n:r:tcp:qov:",
2281+
posix=False,
2282+
strict=False,
2283+
preserve_non_opts=True,
2284+
)
2285+
return stmt
2286+
elif magic_name == "prun":
2287+
opts, stmt = magic_method.__self__.parse_options(
2288+
args, "D:l:rs:T:q", list_all=True, posix=False
2289+
)
2290+
return stmt
2291+
elif hasattr(magic_method, "parser") and getattr(
2292+
magic_method, "has_arguments", False
2293+
):
2294+
# e.g. %debug, %time
2295+
args, extra = magic_method.parser.parse_argstring(args, partial=True)
2296+
return " ".join(extra)
2297+
except UsageError:
2298+
return line
2299+
2300+
return line
2301+
22472302
@context_matcher()
22482303
def magic_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
22492304
"""Match magics."""
@@ -2255,7 +2310,7 @@ def magic_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
22552310
line_magics = lsm['line']
22562311
cell_magics = lsm['cell']
22572312
pre = self.magic_escape
2258-
pre2 = pre+pre
2313+
pre2 = pre + pre
22592314

22602315
explicit_magic = text.startswith(pre)
22612316

@@ -2619,6 +2674,7 @@ def _is_in_string_or_comment(self, text):
26192674
def python_matcher(self, context: CompletionContext) -> SimpleMatcherResult:
26202675
"""Match attributes or global python names"""
26212676
text = context.text_until_cursor
2677+
text = self._extract_code(text)
26222678
completion_type = self._determine_completion_context(text)
26232679
if completion_type == self._CompletionContextType.ATTRIBUTE:
26242680
try:
@@ -3476,7 +3532,7 @@ def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
34763532
full_text=full_text,
34773533
cursor_position=cursor_pos,
34783534
cursor_line=cursor_line,
3479-
token=text,
3535+
token=self._extract_code(text),
34803536
limit=MATCHES_LIMIT,
34813537
)
34823538

IPython/core/displaypub.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class DisplayPublisher(Configurable):
4343
def __init__(self, shell=None, *args, **kwargs):
4444
self.shell = shell
4545
self._is_publishing = False
46+
self._in_post_execute = False
47+
if self.shell:
48+
self._setup_execution_tracking()
4649
super().__init__(*args, **kwargs)
4750

4851
def _validate_data(self, data, metadata=None):
@@ -62,6 +65,19 @@ def _validate_data(self, data, metadata=None):
6265
if not isinstance(metadata, dict):
6366
raise TypeError("metadata must be a dict, got: %r" % data)
6467

68+
def _setup_execution_tracking(self):
69+
"""Set up hooks to track execution state"""
70+
self.shell.events.register("post_execute", self._on_post_execute)
71+
self.shell.events.register("pre_execute", self._on_pre_execute)
72+
73+
def _on_post_execute(self):
74+
"""Called at start of post_execute phase"""
75+
self._in_post_execute = True
76+
77+
def _on_pre_execute(self):
78+
"""Called at start of pre_execute phase"""
79+
self._in_post_execute = False
80+
6581
# use * to indicate transient, update are keyword-only
6682
def publish(
6783
self,
@@ -133,7 +149,13 @@ def publish(
133149

134150
outputs = self.shell.history_manager.outputs
135151

136-
outputs[self.shell.execution_count].append(
152+
target_execution_count = self.shell.execution_count
153+
if self._in_post_execute:
154+
# We're in post_execute, so this is likely a matplotlib flush
155+
# Use execution_count - 1 to associate with the cell that created the plot
156+
target_execution_count = self.shell.execution_count - 1
157+
158+
outputs[target_execution_count].append(
137159
HistoryOutput(output_type="display_data", bundle=data)
138160
)
139161

IPython/core/magic_arguments.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,12 @@ def error(self, message):
161161
"""
162162
raise UsageError(message)
163163

164-
def parse_argstring(self, argstring):
164+
def parse_argstring(self, argstring, *, partial=False):
165165
""" Split a string into an argument list and parse that argument list.
166166
"""
167167
argv = arg_split(argstring)
168+
if partial:
169+
return self.parse_known_args(argv)
168170
return self.parse_args(argv)
169171

170172

@@ -190,10 +192,10 @@ def construct_parser(magic_func):
190192
return parser
191193

192194

193-
def parse_argstring(magic_func, argstring):
195+
def parse_argstring(magic_func, argstring, *, partial=False):
194196
""" Parse the string of arguments for the given magic function.
195197
"""
196-
return magic_func.parser.parse_argstring(argstring)
198+
return magic_func.parser.parse_argstring(argstring, partial=partial)
197199

198200

199201
def real_name(magic_func):

0 commit comments

Comments
 (0)