diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index ad107aad5db3bd7..083a70ce2405e39 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -791,6 +791,9 @@ tkinter :class:`tkinter.ttk.Style`. (Contributed by Serhiy Storchaka in :gh:`68166`.) +* Add the :meth:`!after_info` method for Tkinter widgets. + (Contributed by Cheryl Sabella in :gh:`77020`.) + traceback --------- diff --git a/Grammar/python.gram b/Grammar/python.gram index 3943d7fec5db039..05d7837e3aa6dba 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -78,6 +78,9 @@ _PyPegen_parse(Parser *p) # Fail if e can be parsed, without consuming any input. # ~ # Commit to the current alternative, even if it fails to parse. +# &&e +# Eager parse e. The parser will not backtrack and will immediately +# fail with SyntaxError if e cannot be parsed. # # STARTING RULES diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h index 1831f58899b7458..11f2a100bf531e6 100644 --- a/Include/internal/pycore_ceval_state.h +++ b/Include/internal/pycore_ceval_state.h @@ -20,7 +20,7 @@ struct _pending_call { int flags; }; -#define PENDINGCALLSARRAYSIZE 32 +#define PENDINGCALLSARRAYSIZE 300 #define MAXPENDINGCALLS PENDINGCALLSARRAYSIZE /* For interpreter-level pending calls, we want to avoid spending too @@ -31,7 +31,9 @@ struct _pending_call { # define MAXPENDINGCALLSLOOP MAXPENDINGCALLS #endif -#define MAXPENDINGCALLS_MAIN PENDINGCALLSARRAYSIZE +/* We keep the number small to preserve as much compatibility + as possible with earlier versions. */ +#define MAXPENDINGCALLS_MAIN 32 /* For the main thread, we want to make sure all pending calls are run at once, for the sake of prompt signal handling. This is unlikely to cause any problems since there should be very few diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 49d1056f0504671..020e8493e57c0c1 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -1570,9 +1570,9 @@ def test_max_pending(self): self.assertEqual(added, maxpending) with self.subTest('not main-only'): - # Per-interpreter pending calls has the same low limit + # Per-interpreter pending calls has a much higher limit # on how many may be pending at a time. - maxpending = 32 + maxpending = 300 l = [] added = self.pendingcalls_submit(l, 1, main=False) diff --git a/Lib/test/test_tkinter/test_misc.py b/Lib/test/test_tkinter/test_misc.py index 81a20b698a72eb4..6dca2a3920e06af 100644 --- a/Lib/test/test_tkinter/test_misc.py +++ b/Lib/test/test_tkinter/test_misc.py @@ -232,6 +232,46 @@ def callback(): with self.assertRaises(tkinter.TclError): root.tk.call('after', 'info', idle1) + def test_after_info(self): + root = self.root + + # No events. + self.assertEqual(root.after_info(), ()) + + # Add timer. + timer = root.after(1, lambda: 'break') + + # With no parameter, it returns a tuple of the event handler ids. + self.assertEqual(root.after_info(), (timer, )) + root.after_cancel(timer) + + timer1 = root.after(5000, lambda: 'break') + timer2 = root.after(5000, lambda: 'break') + idle1 = root.after_idle(lambda: 'break') + # Only contains new events and not 'timer'. + self.assertEqual(root.after_info(), (idle1, timer2, timer1)) + + # With a parameter returns a tuple of (script, type). + timer1_info = root.after_info(timer1) + self.assertEqual(len(timer1_info), 2) + self.assertEqual(timer1_info[1], 'timer') + idle1_info = root.after_info(idle1) + self.assertEqual(len(idle1_info), 2) + self.assertEqual(idle1_info[1], 'idle') + + root.after_cancel(timer1) + with self.assertRaises(tkinter.TclError): + root.after_info(timer1) + root.after_cancel(timer2) + with self.assertRaises(tkinter.TclError): + root.after_info(timer2) + root.after_cancel(idle1) + with self.assertRaises(tkinter.TclError): + root.after_info(idle1) + + # No events. + self.assertEqual(root.after_info(), ()) + def test_clipboard(self): root = self.root root.clipboard_clear() diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 19611937fc278b0..8927fccc2893209 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -384,6 +384,7 @@ def f(): ]) @requires_subprocess() + @force_not_colorized def test_encoded_file(self): # Test that tracebacks are correctly printed for encoded source files: # - correct line number (Issue2384) @@ -410,7 +411,7 @@ def do_test(firstlines, message, charset, lineno): """.format(firstlines, message)) process = subprocess.Popen([sys.executable, TESTFN], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env={}) + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = process.communicate() stdout = stdout.decode(output_encoding).splitlines() finally: diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index f685430a7d36ade..5755f7697de91ae 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -8,6 +8,7 @@ interpreter_requires_environment) from test import support from test.support import os_helper +from test.support import force_not_colorized try: import _testcapi @@ -938,11 +939,12 @@ def test_env_limit(self): stdout = stdout.rstrip() self.assertEqual(stdout, b'10') + @force_not_colorized def check_env_var_invalid(self, nframe): with support.SuppressCrashReport(): ok, stdout, stderr = assert_python_failure( '-c', 'pass', - PYTHONTRACEMALLOC=str(nframe), __cleanenv=True) + PYTHONTRACEMALLOC=str(nframe)) if b'ValueError: the number of frames must be in range' in stderr: return diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index fd7b48e35199900..70a1ed46fd07743 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -897,6 +897,21 @@ def after_cancel(self, id): pass self.tk.call('after', 'cancel', id) + def after_info(self, id=None): + """Return information about existing event handlers. + + With no argument, return a tuple of the identifiers for all existing + event handlers created by the after and after_idle commands for this + interpreter. If id is supplied, it specifies an existing handler; id + must have been the return value from some previous call to after or + after_idle and it must not have triggered yet or been canceled. If the + id doesn't exist, a TclError is raised. Otherwise, the return value is + a tuple containing (script, type) where script is a reference to the + function to be called by the event handler and type is either 'idle' + or 'timer' to indicate what kind of event handler it is. + """ + return self.tk.splitlist(self.tk.call('after', 'info', id)) + def bell(self, displayof=0): """Ring a display's bell.""" self.tk.call(('bell',) + self._displayof(displayof)) diff --git a/Misc/NEWS.d/next/Library/2018-02-13-10-02-54.bpo-32839.McbVz3.rst b/Misc/NEWS.d/next/Library/2018-02-13-10-02-54.bpo-32839.McbVz3.rst new file mode 100644 index 000000000000000..0a2e3e3c540c486 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-13-10-02-54.bpo-32839.McbVz3.rst @@ -0,0 +1 @@ +Add the :meth:`after_info` method for Tkinter widgets. diff --git a/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst b/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst index 8eb68ebe99ba155..daa5fe7c0f29171 100644 --- a/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst +++ b/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst @@ -6,4 +6,4 @@ class was dynamically created, the class held strong references to other objects which took up a significant amount of memory, and the cache contained the sole strong reference to the class. The fix for the regression leads to a slowdown in :func:`getattr_static`, but the function should still -be signficantly faster than it was in Python 3.11. Patch by Alex Waygood. +be significantly faster than it was in Python 3.11. Patch by Alex Waygood. diff --git a/iOS/README.rst b/iOS/README.rst index df429b64cec77ff..a0ffa5737aae437 100644 --- a/iOS/README.rst +++ b/iOS/README.rst @@ -50,7 +50,7 @@ iOS specific arguments to configure Unless you know what you're doing, changing the name of the Python framework on iOS is not advised. If you use this option, you won't be able - to run the ``make testios`` target without making signficant manual + to run the ``make testios`` target without making significant manual alterations, and you won't be able to use any binary packages unless you compile them yourself using your own framework name.