Skip to content

Commit 0303a1e

Browse files
authored
Merge branch '3.13' into backport-8a00c9a-3.13
2 parents a583aeb + 924a6ce commit 0303a1e

File tree

8 files changed

+45
-8
lines changed

8 files changed

+45
-8
lines changed

Doc/howto/perf_profiling.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,12 @@ the :option:`!-X` option takes precedence over the environment variable.
162162

163163
Example, using the environment variable::
164164

165-
$ PYTHONPERFSUPPORT=1 perf record -F 9999 -g -o perf.data python script.py
165+
$ PYTHONPERFSUPPORT=1 perf record -F 9999 -g -o perf.data python my_script.py
166166
$ perf report -g -i perf.data
167167

168168
Example, using the :option:`!-X` option::
169169

170-
$ perf record -F 9999 -g -o perf.data python -X perf script.py
170+
$ perf record -F 9999 -g -o perf.data python -X perf my_script.py
171171
$ perf report -g -i perf.data
172172

173173
Example, using the :mod:`sys` APIs in file :file:`example.py`:
@@ -236,7 +236,7 @@ When using the perf JIT mode, you need an extra step before you can run ``perf
236236
report``. You need to call the ``perf inject`` command to inject the JIT
237237
information into the ``perf.data`` file.::
238238

239-
$ perf record -F 9999 -g --call-graph dwarf -o perf.data python -Xperf_jit my_script.py
239+
$ perf record -F 9999 -g -k 1 --call-graph dwarf -o perf.data python -Xperf_jit my_script.py
240240
$ perf inject -i perf.data --jit --output perf.jit.data
241241
$ perf report -g -i perf.jit.data
242242

Lib/_pyrepl/console.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ def repaint(self) -> None: ...
153153

154154

155155
class InteractiveColoredConsole(code.InteractiveConsole):
156+
STATEMENT_FAILED = object()
157+
156158
def __init__(
157159
self,
158160
locals: dict[str, object] | None = None,
@@ -174,6 +176,16 @@ def _excepthook(self, typ, value, tb):
174176
limit=traceback.BUILTIN_EXCEPTION_LIMIT)
175177
self.write(''.join(lines))
176178

179+
def runcode(self, code):
180+
try:
181+
exec(code, self.locals)
182+
except SystemExit:
183+
raise
184+
except BaseException:
185+
self.showtraceback()
186+
return self.STATEMENT_FAILED
187+
return None
188+
177189
def runsource(self, source, filename="<input>", symbol="single"):
178190
try:
179191
tree = self.compile.compiler(
@@ -211,5 +223,7 @@ def runsource(self, source, filename="<input>", symbol="single"):
211223
if code is None:
212224
return True
213225

214-
self.runcode(code)
226+
result = self.runcode(code)
227+
if result is self.STATEMENT_FAILED:
228+
break
215229
return False

Lib/asyncio/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def callback():
7575
self.write("\nKeyboardInterrupt\n")
7676
else:
7777
self.showtraceback()
78-
78+
return self.STATEMENT_FAILED
7979

8080
class REPLThread(threading.Thread):
8181

Lib/test/test_asyncio/test_tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2694,7 +2694,7 @@ def __str__(self):
26942694
initial_refcount = sys.getrefcount(obj)
26952695

26962696
coro = coroutine_function()
2697-
with contextlib.closing(asyncio.new_event_loop()) as loop:
2697+
with contextlib.closing(asyncio.EventLoop()) as loop:
26982698
task = asyncio.Task.__new__(asyncio.Task)
26992699

27002700
for _ in range(5):

Lib/test/test_pyrepl/test_interact.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,19 @@ def test_multiple_statements_output(self):
5353
self.assertFalse(more)
5454
self.assertEqual(f.getvalue(), "1\n")
5555

56+
@force_not_colorized
57+
def test_multiple_statements_fail_early(self):
58+
console = InteractiveColoredConsole()
59+
code = dedent("""\
60+
raise Exception('foobar')
61+
print('spam&eggs')
62+
""")
63+
f = io.StringIO()
64+
with contextlib.redirect_stderr(f):
65+
console.runsource(code)
66+
self.assertIn('Exception: foobar', f.getvalue())
67+
self.assertNotIn('spam&eggs', f.getvalue())
68+
5669
def test_empty(self):
5770
namespace = {}
5871
code = ""

Lib/test/test_repl.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,15 @@ def f():
294294
self.assertEqual(traceback_lines, expected_lines)
295295

296296

297-
class TestAsyncioREPLContextVars(unittest.TestCase):
297+
class TestAsyncioREPL(unittest.TestCase):
298+
def test_multiple_statements_fail_early(self):
299+
user_input = "1 / 0; print('afterwards')"
300+
p = spawn_repl("-m", "asyncio")
301+
p.stdin.write(user_input)
302+
output = kill_python(p)
303+
self.assertIn("ZeroDivisionError", output)
304+
self.assertNotIn("afterwards", output)
305+
298306
def test_toplevel_contextvars_sync(self):
299307
user_input = dedent("""\
300308
from contextvars import ContextVar
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Execution of multiple statements in the new REPL now stops immediately upon
2+
the first exception encountered. Patch by Bartosz Sławecki.

Tools/build/compute-changes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def compute_changes() -> None:
6565
outputs = process_changed_files(files)
6666
else:
6767
# Otherwise, just run the tests
68-
outputs = Outputs(run_tests=True)
68+
outputs = Outputs(run_tests=True, run_windows_tests=True)
6969
outputs = process_target_branch(outputs, target_branch)
7070

7171
if outputs.run_tests:

0 commit comments

Comments
 (0)