[Python-checkins] gh-125470: Fix warning in `Python/generated_cases.c.h` (#125471)
https://github.com/python/cpython/commit/0c8c665581ede95fe119f902b070e395614b78ed
commit: 0c8c665581ede95fe119f902b070e395614b78ed
branch: main
author: sobolevn
committer: sobolevn
date: 2024-10-14T23:46:17+03:00
summary:
gh-125470: Fix warning in `Python/generated_cases.c.h` (#125471)
Co-authored-by: Kirill Podoprigora
files:
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index b22916aeaa248b..e6525657cabc2b 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -611,7 +611,9 @@ dummy_func(
// specializations, but there is no output.
// At the end we just skip over the STORE_FAST.
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
+#ifndef NDEBUG
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+#endif
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
int next_oparg;
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 0ed361a2ee7fb0..15a6c7bc1a7966 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -737,7 +737,9 @@
_PyStackRef left;
right = stack_pointer[-1];
left = stack_pointer[-2];
+#ifndef NDEBUG
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+#endif
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
int next_oparg;
#if TIER_ONE
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 7bd1b7dd5aba27..a9290986c24f45 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -183,7 +183,9 @@
/* Skip 1 cache entry */
// _BINARY_OP_INPLACE_ADD_UNICODE
{
+#ifndef NDEBUG
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+#endif
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
int next_oparg;
#if TIER_ONE
___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]
[Python-checkins] [3.12] Fix idlelib typos (GH-125484) (#125488)
https://github.com/python/cpython/commit/86296bbc178aa2f7094c8d7ab9eb4175f78d105f commit: 86296bbc178aa2f7094c8d7ab9eb4175f78d105f branch: 3.12 author: Miss Islington (bot) <[email protected]> committer: terryjreedy date: 2024-10-14T21:34:38Z summary: [3.12] Fix idlelib typos (GH-125484) (#125488) Fix idlelib typos (GH-125484) Propagate fixes in Doc/library/idle.rst to help.html. Change 'interruptable' to 'interruptible' in run.py. The latter was reported by ember91 in PR 125473. (cherry picked from commit 3fea1d000ef0a74062fd3fe218ad94618b08d9f2) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/help.html M Lib/idlelib/run.py diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 827d230b54e159..2a4adc6a4d395f 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -5,7 +5,7 @@ -IDLE — Python 3.13.0a2 documentation +IDLE — Python 3.14.0a0 documentation @@ -18,7 +18,7 @@ @@ -26,6 +26,7 @@ + https://docs.python.org/3/library/idle.html"; /> @@ -45,6 +46,8 @@ + + @@ -184,7 +187,7 @@ Navigation - 3.13.0a2 Documentation » + 3.14.0a0 Documentation » The Python Standard Library » @@ -554,7 +557,7 @@ Key bindingsControl key on Windows and -Unix and the Command key on macOS. (And all such dicussions +Unix and the Command key on macOS. (And all such discussions assume that the keys have not been re-bound to something else.) Arrow keys move the cursor one character or line. @@ -562,8 +565,8 @@ Key bindingsHome and End go to the beginning or end of the line. Page Up and Page Down go up or down one screen. C-Home and C-End go to beginning or end of the file. -Backspace and Del (or C-d) delete the previous or -next character. +Backspace and Del (or C-d) delete the previous +or next character. C-Backspace and C-Del delete one word left or right. C-k deletes (‘kills’) everything to the right. @@ -694,7 +697,7 @@ Shell window -C-c attemps to interrupt statement execution (but may fail). +C-c attempts to interrupt statement execution (but may fail). C-d closes Shell if typed at a >>> prompt. Alt-p and Alt-n (C-p and C-n on macOS) retrieve to the current prompt the previous or next previously @@ -1136,7 +1139,7 @@ Navigation - 3.13.0a2 Documentation » + 3.14.0a0 Documentation » The Python Standard Library » @@ -1180,7 +1183,7 @@ Navigation -Last updated on Jan 17, 2024 (06:57 UTC). +Last updated on Oct 14, 2024 (20:27 UTC). Found a bug? diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 476a7b26c004b5..2faeba678c7262 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -101,11 +101,11 @@ def handle_tk_events(tcl=tcl): # Thread shared globals: Establish a queue between a subthread (which handles # the socket) and the main thread (which runs user code), plus global -# completion, exit and interruptable (the main thread) flags: +# completion, exit and interruptible (the main thread) flags: exit_now = False quitting = False -interruptable = False +interruptible = False def main(del_exitfunc=False): """Start the Python execution server in a subprocess @@ -575,14 +575,14 @@ def __init__(self, rpchandler): self.locals = {} def runcode(self, code): -global interruptable +global interruptible try: self.user_exc_info = None -interruptable = True +interruptible = True try: exec(code, self.locals) finally: -interruptable = False +interruptible = False except SystemExit as e: if e.args: # SystemExit called with an argument. ob = e.args[0] @@ -608,7 +608,7 @@ def runcode(self, code): flush_stdout() def interrupt_the_server(self): -if interruptable: +if interruptible: thread.interrupt_main() def start_the_debugger(self, gui_adap_oid): ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] gh-124944: Add socket.SO_ORIGINAL_DST (#124945)
https://github.com/python/cpython/commit/1bffd7a2a738506a4ad50c6c3c2c32926cce6d14 commit: 1bffd7a2a738506a4ad50c6c3c2c32926cce6d14 branch: main author: Steven Jin committer: erlend-aasland date: 2024-10-15T00:36:38+02:00 summary: gh-124944: Add socket.SO_ORIGINAL_DST (#124945) files: A Misc/NEWS.d/next/Library/2024-10-03-17-13-22.gh-issue-124944.YyLAzf.rst M Modules/socketmodule.c M Modules/socketmodule.h M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Library/2024-10-03-17-13-22.gh-issue-124944.YyLAzf.rst b/Misc/NEWS.d/next/Library/2024-10-03-17-13-22.gh-issue-124944.YyLAzf.rst new file mode 100644 index 00..66af712c5ae5a8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-03-17-13-22.gh-issue-124944.YyLAzf.rst @@ -0,0 +1 @@ +Add ``SO_ORIGINAL_DST`` to the :mod:`socket` module. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 0829d2358129d2..744e5e0c0b2b54 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7921,6 +7921,9 @@ socket_exec(PyObject *m) #ifdef SO_OOBINLINE ADD_INT_MACRO(m, SO_OOBINLINE); #endif +#ifdef SO_ORIGINAL_DST +ADD_INT_MACRO(m, SO_ORIGINAL_DST); +#endif #ifndef __GNU__ #ifdef SO_REUSEPORT ADD_INT_MACRO(m, SO_REUSEPORT); diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index a77c620c2ef630..e1d96377728eb9 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -172,6 +172,10 @@ typedef int socklen_t; # undef AF_VSOCK #endif +#ifdef HAVE_LINUX_NETFILTER_IPV4_H +# include +#endif + #ifdef HAVE_SOCKADDR_ALG # include diff --git a/configure b/configure index 0cc73e4e66552d..c5bec6a1b0d7c2 100755 --- a/configure +++ b/configure @@ -11092,6 +11092,12 @@ if test "x$ac_cv_header_linux_memfd_h" = xyes then : printf "%s\n" "#define HAVE_LINUX_MEMFD_H 1" >>confdefs.h +fi +ac_fn_c_check_header_compile "$LINENO" "linux/netfilter_ipv4.h" "ac_cv_header_linux_netfilter_ipv4_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_netfilter_ipv4_h" = xyes +then : + printf "%s\n" "#define HAVE_LINUX_NETFILTER_IPV4_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "linux/random.h" "ac_cv_header_linux_random_h" "$ac_includes_default" if test "x$ac_cv_header_linux_random_h" = xyes diff --git a/configure.ac b/configure.ac index 1864e94ace9243..d4b7942190207a 100644 --- a/configure.ac +++ b/configure.ac @@ -3013,7 +3013,7 @@ AC_DEFINE([STDC_HEADERS], [1], AC_CHECK_HEADERS([ \ alloca.h asm/types.h bluetooth.h conio.h direct.h dlfcn.h endian.h errno.h fcntl.h grp.h \ io.h langinfo.h libintl.h libutil.h linux/auxvec.h sys/auxv.h linux/fs.h linux/limits.h linux/memfd.h \ - linux/random.h linux/soundcard.h \ + linux/netfilter_ipv4.h linux/random.h linux/soundcard.h \ linux/tipc.h linux/wait.h netdb.h net/ethernet.h netinet/in.h netpacket/packet.h poll.h process.h pthread.h pty.h \ sched.h setjmp.h shadow.h signal.h spawn.h stropts.h sys/audioio.h sys/bsdtty.h sys/devpoll.h \ sys/endian.h sys/epoll.h sys/event.h sys/eventfd.h sys/file.h sys/ioctl.h sys/kern_control.h \ diff --git a/pyconfig.h.in b/pyconfig.h.in index 7f02603e26f5d0..1947d8ee14f83e 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -739,6 +739,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_MEMFD_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_NETFILTER_IPV4_H + /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_NETLINK_H ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] gh-124958: Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles ... (#125486)
https://github.com/python/cpython/commit/0b28ea4a35dc7c68c97127f7aad8f0175d77c520
commit: 0b28ea4a35dc7c68c97127f7aad8f0175d77c520
branch: main
author: Thomas Grainger
committer: 1st1
date: 2024-10-14T15:45:58-07:00
summary:
gh-124958: Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and
_PyFuture refcycles ... (#125486)
* Revert "gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture
refcycles (#12… (#125476)"
This reverts commit e99650b80ace3893c2a80b3f2a4aca99cb305191.
* fix incompatability with gh-124392
files:
A Misc/NEWS.d/next/Library/2024-10-04-08-46-00.gh-issue-124958.rea9-x.rst
M Lib/asyncio/futures.py
M Lib/asyncio/taskgroups.py
M Lib/test/test_asyncio/test_futures.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
index 5f6fa2348726cf..c95fce035cd548 100644
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -190,8 +190,7 @@ def result(self):
the future is done and has an exception set, this exception is raised.
"""
if self._state == _CANCELLED:
-exc = self._make_cancelled_error()
-raise exc
+raise self._make_cancelled_error()
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Result is not ready.')
self.__log_traceback = False
@@ -208,8 +207,7 @@ def exception(self):
InvalidStateError.
"""
if self._state == _CANCELLED:
-exc = self._make_cancelled_error()
-raise exc
+raise self._make_cancelled_error()
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Exception is not set.')
self.__log_traceback = False
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index f2ee9648c43876..9fa772ca9d02cc 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -66,6 +66,20 @@ async def __aenter__(self):
return self
async def __aexit__(self, et, exc, tb):
+tb = None
+try:
+return await self._aexit(et, exc)
+finally:
+# Exceptions are heavy objects that can have object
+# cycles (bad for GC); let's not keep a reference to
+# a bunch of them. It would be nicer to use a try/finally
+# in __aexit__ directly but that introduced some diff noise
+self._parent_task = None
+self._errors = None
+self._base_error = None
+exc = None
+
+async def _aexit(self, et, exc):
self._exiting = True
if (exc is not None and
@@ -122,7 +136,10 @@ async def __aexit__(self, et, exc, tb):
assert not self._tasks
if self._base_error is not None:
-raise self._base_error
+try:
+raise self._base_error
+finally:
+exc = None
if self._parent_cancel_requested:
# If this flag is set we *must* call uncancel().
@@ -133,8 +150,14 @@ async def __aexit__(self, et, exc, tb):
# Propagate CancelledError if there is one, except if there
# are other errors -- those have priority.
-if propagate_cancellation_error is not None and not self._errors:
-raise propagate_cancellation_error
+try:
+if propagate_cancellation_error is not None and not self._errors:
+try:
+raise propagate_cancellation_error
+finally:
+exc = None
+finally:
+propagate_cancellation_error = None
if et is not None and not issubclass(et, exceptions.CancelledError):
self._errors.append(exc)
@@ -146,14 +169,14 @@ async def __aexit__(self, et, exc, tb):
if self._parent_task.cancelling():
self._parent_task.uncancel()
self._parent_task.cancel()
-# Exceptions are heavy objects that can have object
-# cycles (bad for GC); let's not keep a reference to
-# a bunch of them.
try:
-me = BaseExceptionGroup('unhandled errors in a TaskGroup',
self._errors)
-raise me from None
+raise BaseExceptionGroup(
+'unhandled errors in a TaskGroup',
+self._errors,
+) from None
finally:
-self._errors = None
+exc = None
+
def create_task(self, coro, *, name=None, context=None):
"""Create a new task in this group and return it.
diff --git a/Lib/test/test_asyncio/test_futures.py
b/Lib/test/test_asyncio/test_futures.py
index 458b70451a306a..c566b28adb2408 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -659,6 +659,28 @@ def __del__(self):
fut = self._new_future(loop=self.loop)
fut.set_result(Evil())
+
[Python-checkins] [3.13] Fix idlelib typos (GH-125484) (#125487)
https://github.com/python/cpython/commit/6fb48c69fc6d73567177db1b65ba11a52c62a143 commit: 6fb48c69fc6d73567177db1b65ba11a52c62a143 branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: terryjreedy date: 2024-10-14T21:38:40Z summary: [3.13] Fix idlelib typos (GH-125484) (#125487) Fix idlelib typos (GH-125484) Propagate fixes in Doc/library/idle.rst to help.html. Change 'interruptable' to 'interruptible' in run.py. The latter was reported by ember91 in PR 125473. (cherry picked from commit 3fea1d000ef0a74062fd3fe218ad94618b08d9f2) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/help.html M Lib/idlelib/run.py diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 827d230b54e159..2a4adc6a4d395f 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -5,7 +5,7 @@ -IDLE — Python 3.13.0a2 documentation +IDLE — Python 3.14.0a0 documentation @@ -18,7 +18,7 @@ @@ -26,6 +26,7 @@ + https://docs.python.org/3/library/idle.html"; /> @@ -45,6 +46,8 @@ + + @@ -184,7 +187,7 @@ Navigation - 3.13.0a2 Documentation » + 3.14.0a0 Documentation » The Python Standard Library » @@ -554,7 +557,7 @@ Key bindingsControl key on Windows and -Unix and the Command key on macOS. (And all such dicussions +Unix and the Command key on macOS. (And all such discussions assume that the keys have not been re-bound to something else.) Arrow keys move the cursor one character or line. @@ -562,8 +565,8 @@ Key bindingsHome and End go to the beginning or end of the line. Page Up and Page Down go up or down one screen. C-Home and C-End go to beginning or end of the file. -Backspace and Del (or C-d) delete the previous or -next character. +Backspace and Del (or C-d) delete the previous +or next character. C-Backspace and C-Del delete one word left or right. C-k deletes (‘kills’) everything to the right. @@ -694,7 +697,7 @@ Shell window -C-c attemps to interrupt statement execution (but may fail). +C-c attempts to interrupt statement execution (but may fail). C-d closes Shell if typed at a >>> prompt. Alt-p and Alt-n (C-p and C-n on macOS) retrieve to the current prompt the previous or next previously @@ -1136,7 +1139,7 @@ Navigation - 3.13.0a2 Documentation » + 3.14.0a0 Documentation » The Python Standard Library » @@ -1180,7 +1183,7 @@ Navigation -Last updated on Jan 17, 2024 (06:57 UTC). +Last updated on Oct 14, 2024 (20:27 UTC). Found a bug? diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 8f98e73258e778..a30db99a619a93 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -108,11 +108,11 @@ def handle_tk_events(tcl=tcl): # Thread shared globals: Establish a queue between a subthread (which handles # the socket) and the main thread (which runs user code), plus global -# completion, exit and interruptable (the main thread) flags: +# completion, exit and interruptible (the main thread) flags: exit_now = False quitting = False -interruptable = False +interruptible = False def main(del_exitfunc=False): """Start the Python execution server in a subprocess @@ -582,14 +582,14 @@ def __init__(self, rpchandler): self.locals = {} def runcode(self, code): -global interruptable +global interruptible try: self.user_exc_info = None -interruptable = True +interruptible = True try: exec(code, self.locals) finally: -interruptable = False +interruptible = False except SystemExit as e: if e.args: # SystemExit called with an argument. ob = e.args[0] @@ -615,7 +615,7 @@ def runcode(self, code): flush_stdout() def interrupt_the_server(self): -if interruptable: +if interruptible: thread.interrupt_main() def start_the_debugger(self, gui_adap_oid): ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] gh-124872: Replace enter/exit events with "switched" (#124776)
https://github.com/python/cpython/commit/843d28f59d2616d052d9d45f31823976da07f0f3
commit: 843d28f59d2616d052d9d45f31823976da07f0f3
branch: main
author: Richard Hansen
committer: 1st1
date: 2024-10-14T12:28:41-07:00
summary:
gh-124872: Replace enter/exit events with "switched" (#124776)
Users want to know when the current context switches to a different
context object. Right now this happens when and only when a context
is entered or exited, so the enter and exit events are synonymous with
"switched". However, if the changes proposed for gh-99633 are
implemented, the current context will also switch for reasons other
than context enter or exit. Since users actually care about context
switches and not enter or exit, replace the enter and exit events with
a single switched event.
The former exit event was emitted just before exiting the context.
The new switched event is emitted after the context is exited to match
the semantics users expect of an event with a past-tense name. If
users need the ability to clean up before the switch takes effect,
another event type can be added in the future. It is not added here
because YAGNI.
I skipped 0 in the enum as a matter of practice. Skipping 0 makes it
easier to troubleshoot when code forgets to set zeroed memory, and it
aligns with best practices for other tools (e.g.,
https://protobuf.dev/programming-guides/dos-donts/#unspecified-enum).
files:
M Doc/c-api/contextvars.rst
M Include/cpython/context.h
M Lib/test/test_capi/test_watchers.py
M Modules/_testcapi/watchers.c
M Python/context.c
M Tools/c-analyzer/cpython/ignored.tsv
diff --git a/Doc/c-api/contextvars.rst b/Doc/c-api/contextvars.rst
index 8eba54a80dc80d..b7c6550ff34aac 100644
--- a/Doc/c-api/contextvars.rst
+++ b/Doc/c-api/contextvars.rst
@@ -123,16 +123,10 @@ Context object management functions:
Enumeration of possible context object watcher events:
- - ``Py_CONTEXT_EVENT_ENTER``: A context has been entered, causing the
- :term:`current context` to switch to it. The object passed to the watch
- callback is the now-current :class:`contextvars.Context` object. Each
- enter event will eventually have a corresponding exit event for the same
- context object after any subsequently entered contexts have themselves
been
- exited.
- - ``Py_CONTEXT_EVENT_EXIT``: A context is about to be exited, which will
- cause the :term:`current context` to switch back to what it was before the
- context was entered. The object passed to the watch callback is the
- still-current :class:`contextvars.Context` object.
+ - ``Py_CONTEXT_SWITCHED``: The :term:`current context` has switched to a
+ different context. The object passed to the watch callback is the
+ now-current :class:`contextvars.Context` object, or None if no context is
+ current.
.. versionadded:: 3.14
diff --git a/Include/cpython/context.h b/Include/cpython/context.h
index 3c9be7873b9399..3a7a4b459c09ad 100644
--- a/Include/cpython/context.h
+++ b/Include/cpython/context.h
@@ -29,20 +29,11 @@ PyAPI_FUNC(int) PyContext_Exit(PyObject *);
typedef enum {
/*
- * A context has been entered, causing the "current context" to switch to
- * it. The object passed to the watch callback is the now-current
- * contextvars.Context object. Each enter event will eventually have a
- * corresponding exit event for the same context object after any
- * subsequently entered contexts have themselves been exited.
+ * The current context has switched to a different context. The object
+ * passed to the watch callback is the now-current contextvars.Context
+ * object, or None if no context is current.
*/
-Py_CONTEXT_EVENT_ENTER,
-/*
- * A context is about to be exited, which will cause the "current context"
- * to switch back to what it was before the context was entered. The
- * object passed to the watch callback is the still-current
- * contextvars.Context object.
- */
-Py_CONTEXT_EVENT_EXIT,
+Py_CONTEXT_SWITCHED = 1,
} PyContextEvent;
/*
diff --git a/Lib/test/test_capi/test_watchers.py
b/Lib/test/test_capi/test_watchers.py
index f21d2627c6094b..4680d6765de122 100644
--- a/Lib/test/test_capi/test_watchers.py
+++ b/Lib/test/test_capi/test_watchers.py
@@ -577,68 +577,62 @@ class TestContextObjectWatchers(unittest.TestCase):
def context_watcher(self, which_watcher):
wid = _testcapi.add_context_watcher(which_watcher)
try:
-yield wid
+switches = _testcapi.get_context_switches(which_watcher)
+except ValueError:
+switches = None
+try:
+yield switches
finally:
_testcapi.clear_context_watcher(wid)
-def assert_event_counts(self, exp_enter_0, exp_exit_0,
-exp_enter_1, exp_exit_1):
-self.assertEqual(
-exp_enter_0, _testcapi.get_context_watcher_num_enter_events(0))
-
[Python-checkins] Fix idlelib typos (#125484)
https://github.com/python/cpython/commit/3fea1d000ef0a74062fd3fe218ad94618b08d9f2
commit: 3fea1d000ef0a74062fd3fe218ad94618b08d9f2
branch: main
author: Terry Jan Reedy
committer: terryjreedy
date: 2024-10-14T17:11:58-04:00
summary:
Fix idlelib typos (#125484)
Propagate fixes in Doc/library/idle.rst to help.html.
Change 'interruptable' to 'interruptible' in run.py.
The latter was reported by ember91 in PR 125473.
files:
M Lib/idlelib/help.html
M Lib/idlelib/run.py
diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html
index 827d230b54e159..2a4adc6a4d395f 100644
--- a/Lib/idlelib/help.html
+++ b/Lib/idlelib/help.html
@@ -5,7 +5,7 @@
-IDLE — Python 3.13.0a2 documentation
+IDLE — Python 3.14.0a0 documentation
@@ -18,7 +18,7 @@
@@ -26,6 +26,7 @@
+
https://docs.python.org/3/library/idle.html"; />
@@ -45,6 +46,8 @@
+
+
@@ -184,7 +187,7 @@ Navigation
- 3.13.0a2 Documentation »
+ 3.14.0a0 Documentation »
The Python
Standard Library »
@@ -554,7 +557,7 @@ Key bindingsControl
key on Windows and
-Unix and the Command key
on macOS. (And all such dicussions
+Unix and the Command key
on macOS. (And all such discussions
assume that the keys have not been re-bound to something else.)
Arrow keys move the cursor one character or line.
@@ -562,8 +565,8 @@ Key bindingsHome and End go to the beginning or end
of the line.
Page Up and Page Down go up or down one
screen.
C-Home and C-End go to beginning or end
of the file.
-Backspace and Del (or C-d) delete
the previous or
-next character.
+Backspace and Del (or C-d) delete the previous
+or next character.
C-Backspace and C-Del delete one word left
or right.
C-k deletes (‘kills’) everything to the right.
@@ -694,7 +697,7 @@ Shell window
-C-c attemps to interrupt statement execution (but may
fail).
+C-c attempts to interrupt statement execution (but may
fail).
C-d closes Shell if typed at a >>>
prompt.
Alt-p and Alt-n (C-p and C-n on macOS)
retrieve to the current prompt the previous or next previously
@@ -1136,7 +1139,7 @@ Navigation
- 3.13.0a2 Documentation »
+ 3.14.0a0 Documentation »
The Python
Standard Library »
@@ -1180,7 +1183,7 @@ Navigation
-Last updated on Jan 17, 2024 (06:57 UTC).
+Last updated on Oct 14, 2024 (20:27 UTC).
Found a bug?
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index 8f98e73258e778..a30db99a619a93 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -108,11 +108,11 @@ def handle_tk_events(tcl=tcl):
# Thread shared globals: Establish a queue between a subthread (which handles
# the socket) and the main thread (which runs user code), plus global
-# completion, exit and interruptable (the main thread) flags:
+# completion, exit and interruptible (the main thread) flags:
exit_now = False
quitting = False
-interruptable = False
+interruptible = False
def main(del_exitfunc=False):
"""Start the Python execution server in a subprocess
@@ -582,14 +582,14 @@ def __init__(self, rpchandler):
self.locals = {}
def runcode(self, code):
-global interruptable
+global interruptible
try:
self.user_exc_info = None
-interruptable = True
+interruptible = True
try:
exec(code, self.locals)
finally:
-interruptable = False
+interruptible = False
except SystemExit as e:
if e.args: # SystemExit called with an argument.
ob = e.args[0]
@@ -615,7 +615,7 @@ def runcode(self, code):
flush_stdout()
def interrupt_the_server(self):
-if interruptable:
+if interruptible:
thread.interrupt_main()
def start_the_debugger(self, gui_adap_oid):
___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]
[Python-checkins] gh-85453: Improve variable mark up for datetime.rst (#120702)
https://github.com/python/cpython/commit/2a5cdb251674ce8d9a824c102f7cd846d944cfa4 commit: 2a5cdb251674ce8d9a824c102f7cd846d944cfa4 branch: main author: edson duarte committer: erlend-aasland date: 2024-10-15T00:02:58+02:00 summary: gh-85453: Improve variable mark up for datetime.rst (#120702) Variables and literals are marked up using backticks. files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index f0b465bc9ce39c..2f81080d525f86 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -180,19 +180,19 @@ Objects of the :class:`date` type are always naive. An object of type :class:`.time` or :class:`.datetime` may be aware or naive. -A :class:`.datetime` object *d* is aware if both of the following hold: +A :class:`.datetime` object ``d`` is aware if both of the following hold: 1. ``d.tzinfo`` is not ``None`` 2. ``d.tzinfo.utcoffset(d)`` does not return ``None`` -Otherwise, *d* is naive. +Otherwise, ``d`` is naive. -A :class:`.time` object *t* is aware if both of the following hold: +A :class:`.time` object ``t`` is aware if both of the following hold: 1. ``t.tzinfo`` is not ``None`` 2. ``t.tzinfo.utcoffset(None)`` does not return ``None``. -Otherwise, *t* is naive. +Otherwise, ``t`` is naive. The distinction between aware and naive doesn't apply to :class:`timedelta` objects. @@ -358,8 +358,8 @@ Supported operations: ++---+ | ``q, r = divmod(t1, t2)`` | Computes the quotient and the remainder: | || ``q = t1 // t2`` (3) and ``r = t1 % t2``. | -|| q is an integer and r is a :class:`timedelta` | -|| object. | +|| ``q`` is an integer and ``r`` is a | +|| :class:`timedelta` object. | ++---+ | ``+t1``| Returns a :class:`timedelta` object with the | || same value. (2) | @@ -526,7 +526,7 @@ Other constructors, all class methods: January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 <= ordinal <= - date.max.toordinal()``. For any date *d*, + date.max.toordinal()``. For any date ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -730,7 +730,7 @@ Instance methods: .. method:: date.toordinal() Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 - has ordinal 1. For any :class:`date` object *d*, + has ordinal 1. For any :class:`date` object ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -782,7 +782,7 @@ Instance methods: .. method:: date.__str__() - For a date *d*, ``str(d)`` is equivalent to ``d.isoformat()``. + For a date ``d``, ``str(d)`` is equivalent to ``d.isoformat()``. .. method:: date.ctime() @@ -1063,7 +1063,7 @@ Other constructors, all class methods: is used. If the *date* argument is a :class:`.datetime` object, its time components and :attr:`.tzinfo` attributes are ignored. - For any :class:`.datetime` object *d*, + For any :class:`.datetime` object ``d``, ``d == datetime.combine(d.date(), d.time(), d.tzinfo)``. .. versionchanged:: 3.6 @@ -1270,11 +1270,11 @@ Supported operations: If both are naive, or both are aware and have the same :attr:`~.datetime.tzinfo` attribute, the :attr:`~.datetime.tzinfo` attributes are ignored, and the result is a :class:`timedelta` - object *t* such that ``datetime2 + t == datetime1``. No time zone adjustments + object ``t`` such that ``datetime2 + t == datetime1``. No time zone adjustments are done in this case. If both are aware and have different :attr:`~.datetime.tzinfo` attributes, ``a-b`` acts - as if *a* and *b* were first converted to naive UTC datetimes. The + as if ``a`` and ``b`` were first converted to naive UTC datetimes. The result is ``(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())`` except that the implementation never overflows. @@ -1454,11 +1454,11 @@ Instance methods: .. method:: datetime.utctimetuple() - If :class:`.datetime` instance *d* is naive, this is the same as + If :class:`.datetime` instance ``d`` is naive, this is the same as ``d.timetuple()`` except that :attr:`~.time.struct_time.tm_isdst` is forced to 0 regardless of what ``d.dst()`` returns. DST is never in effect for a UTC time. - If *d* is aware, *d* is normalized to UTC time, by subtracting + If ``d`` is aware, ``d`` is normalized to UTC time, by subtracting ``d.utcoffset()``, and a :class:`time.struct_time` for the normalized time is returned. :attr:`!tm_isdst` is for
[Python-checkins] [3.13] gh-85453: Improve variable mark up for datetime.rst (GH-120702) (#125490)
https://github.com/python/cpython/commit/624a8e4f976bf64851d51ff7ff7d7e24ad87c142 commit: 624a8e4f976bf64851d51ff7ff7d7e24ad87c142 branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: erlend-aasland date: 2024-10-14T22:08:30Z summary: [3.13] gh-85453: Improve variable mark up for datetime.rst (GH-120702) (#125490) Variables and literals are marked up using backticks. (cherry picked from commit 2a5cdb251674ce8d9a824c102f7cd846d944cfa4) Co-authored-by: edson duarte files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 4775aa628e9385..211e625c4303b0 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -180,19 +180,19 @@ Objects of the :class:`date` type are always naive. An object of type :class:`.time` or :class:`.datetime` may be aware or naive. -A :class:`.datetime` object *d* is aware if both of the following hold: +A :class:`.datetime` object ``d`` is aware if both of the following hold: 1. ``d.tzinfo`` is not ``None`` 2. ``d.tzinfo.utcoffset(d)`` does not return ``None`` -Otherwise, *d* is naive. +Otherwise, ``d`` is naive. -A :class:`.time` object *t* is aware if both of the following hold: +A :class:`.time` object ``t`` is aware if both of the following hold: 1. ``t.tzinfo`` is not ``None`` 2. ``t.tzinfo.utcoffset(None)`` does not return ``None``. -Otherwise, *t* is naive. +Otherwise, ``t`` is naive. The distinction between aware and naive doesn't apply to :class:`timedelta` objects. @@ -358,8 +358,8 @@ Supported operations: ++---+ | ``q, r = divmod(t1, t2)`` | Computes the quotient and the remainder: | || ``q = t1 // t2`` (3) and ``r = t1 % t2``. | -|| q is an integer and r is a :class:`timedelta` | -|| object. | +|| ``q`` is an integer and ``r`` is a | +|| :class:`timedelta` object. | ++---+ | ``+t1``| Returns a :class:`timedelta` object with the | || same value. (2) | @@ -526,7 +526,7 @@ Other constructors, all class methods: January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 <= ordinal <= - date.max.toordinal()``. For any date *d*, + date.max.toordinal()``. For any date ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -697,7 +697,7 @@ Instance methods: .. method:: date.toordinal() Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 - has ordinal 1. For any :class:`date` object *d*, + has ordinal 1. For any :class:`date` object ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -749,7 +749,7 @@ Instance methods: .. method:: date.__str__() - For a date *d*, ``str(d)`` is equivalent to ``d.isoformat()``. + For a date ``d``, ``str(d)`` is equivalent to ``d.isoformat()``. .. method:: date.ctime() @@ -1030,7 +1030,7 @@ Other constructors, all class methods: is used. If the *date* argument is a :class:`.datetime` object, its time components and :attr:`.tzinfo` attributes are ignored. - For any :class:`.datetime` object *d*, + For any :class:`.datetime` object ``d``, ``d == datetime.combine(d.date(), d.time(), d.tzinfo)``. .. versionchanged:: 3.6 @@ -1237,11 +1237,11 @@ Supported operations: If both are naive, or both are aware and have the same :attr:`~.datetime.tzinfo` attribute, the :attr:`~.datetime.tzinfo` attributes are ignored, and the result is a :class:`timedelta` - object *t* such that ``datetime2 + t == datetime1``. No time zone adjustments + object ``t`` such that ``datetime2 + t == datetime1``. No time zone adjustments are done in this case. If both are aware and have different :attr:`~.datetime.tzinfo` attributes, ``a-b`` acts - as if *a* and *b* were first converted to naive UTC datetimes. The + as if ``a`` and ``b`` were first converted to naive UTC datetimes. The result is ``(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())`` except that the implementation never overflows. @@ -1421,11 +1421,11 @@ Instance methods: .. method:: datetime.utctimetuple() - If :class:`.datetime` instance *d* is naive, this is the same as + If :class:`.datetime` instance ``d`` is naive, this is the same as ``d.timetuple()`` except that :attr:`~.time.struct_time.tm_isdst` is forced to 0 regardless of what ``d.dst()`` returns. DST is never in effect for a UTC time. - If *d* is aware, *d* is normalized to UTC time, by subtracting + If ``d`` is awa
[Python-checkins] [3.12] gh-85453: Improve variable mark up for datetime.rst (GH-120702) (#125491)
https://github.com/python/cpython/commit/449f2c98bdd04694a987639a91f4fab366c2e9d4 commit: 449f2c98bdd04694a987639a91f4fab366c2e9d4 branch: 3.12 author: Miss Islington (bot) <[email protected]> committer: erlend-aasland date: 2024-10-14T22:09:23Z summary: [3.12] gh-85453: Improve variable mark up for datetime.rst (GH-120702) (#125491) Variables and literals are marked up using backticks. (cherry picked from commit 2a5cdb251674ce8d9a824c102f7cd846d944cfa4) Co-authored-by: edson duarte files: M Doc/library/datetime.rst diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 671554f2cf3d0d..54ab05e4e66549 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -180,19 +180,19 @@ Objects of the :class:`date` type are always naive. An object of type :class:`.time` or :class:`.datetime` may be aware or naive. -A :class:`.datetime` object *d* is aware if both of the following hold: +A :class:`.datetime` object ``d`` is aware if both of the following hold: 1. ``d.tzinfo`` is not ``None`` 2. ``d.tzinfo.utcoffset(d)`` does not return ``None`` -Otherwise, *d* is naive. +Otherwise, ``d`` is naive. -A :class:`.time` object *t* is aware if both of the following hold: +A :class:`.time` object ``t`` is aware if both of the following hold: 1. ``t.tzinfo`` is not ``None`` 2. ``t.tzinfo.utcoffset(None)`` does not return ``None``. -Otherwise, *t* is naive. +Otherwise, ``t`` is naive. The distinction between aware and naive doesn't apply to :class:`timedelta` objects. @@ -358,8 +358,8 @@ Supported operations: ++---+ | ``q, r = divmod(t1, t2)`` | Computes the quotient and the remainder: | || ``q = t1 // t2`` (3) and ``r = t1 % t2``. | -|| q is an integer and r is a :class:`timedelta` | -|| object. | +|| ``q`` is an integer and ``r`` is a | +|| :class:`timedelta` object. | ++---+ | ``+t1``| Returns a :class:`timedelta` object with the | || same value. (2) | @@ -526,7 +526,7 @@ Other constructors, all class methods: January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 <= ordinal <= - date.max.toordinal()``. For any date *d*, + date.max.toordinal()``. For any date ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -678,7 +678,7 @@ Instance methods: .. method:: date.toordinal() Return the proleptic Gregorian ordinal of the date, where January 1 of year 1 - has ordinal 1. For any :class:`date` object *d*, + has ordinal 1. For any :class:`date` object ``d``, ``date.fromordinal(d.toordinal()) == d``. @@ -730,7 +730,7 @@ Instance methods: .. method:: date.__str__() - For a date *d*, ``str(d)`` is equivalent to ``d.isoformat()``. + For a date ``d``, ``str(d)`` is equivalent to ``d.isoformat()``. .. method:: date.ctime() @@ -1011,7 +1011,7 @@ Other constructors, all class methods: is used. If the *date* argument is a :class:`.datetime` object, its time components and :attr:`.tzinfo` attributes are ignored. - For any :class:`.datetime` object *d*, + For any :class:`.datetime` object ``d``, ``d == datetime.combine(d.date(), d.time(), d.tzinfo)``. .. versionchanged:: 3.6 @@ -1200,11 +1200,11 @@ Supported operations: If both are naive, or both are aware and have the same :attr:`~.datetime.tzinfo` attribute, the :attr:`~.datetime.tzinfo` attributes are ignored, and the result is a :class:`timedelta` - object *t* such that ``datetime2 + t == datetime1``. No time zone adjustments + object ``t`` such that ``datetime2 + t == datetime1``. No time zone adjustments are done in this case. If both are aware and have different :attr:`~.datetime.tzinfo` attributes, ``a-b`` acts - as if *a* and *b* were first converted to naive UTC datetimes. The + as if ``a`` and ``b`` were first converted to naive UTC datetimes. The result is ``(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())`` except that the implementation never overflows. @@ -1377,11 +1377,11 @@ Instance methods: .. method:: datetime.utctimetuple() - If :class:`.datetime` instance *d* is naive, this is the same as + If :class:`.datetime` instance ``d`` is naive, this is the same as ``d.timetuple()`` except that :attr:`~.time.struct_time.tm_isdst` is forced to 0 regardless of what ``d.dst()`` returns. DST is never in effect for a UTC time. - If *d* is aware, *d* is normalized to UTC time, by subtracting + If ``d`` is awa
[Python-checkins] gh-125269: Use `AC_LINK_IF_ELSE` to detect if `-latomic` is needed (#125416)
https://github.com/python/cpython/commit/8d42e2d915c3096e7eac1c649751d1da567bb7c3
commit: 8d42e2d915c3096e7eac1c649751d1da567bb7c3
branch: main
author: Sam Gross
committer: colesbury
date: 2024-10-14T20:09:48-04:00
summary:
gh-125269: Use `AC_LINK_IF_ELSE` to detect if `-latomic` is needed (#125416)
We previously used `AC_RUN_IF_ELSE` with a short test program to detect
if `-latomic` is needed, but that requires choosing a specific default
value when cross-compiling because the test program is not run.
Some cross compilation targets like `wasm32-emscripten` do not support
`-latomic`, while other cross compilation targets, like
`arm-linux-gnueabi` require it.
files:
A Misc/NEWS.d/next/Build/2024-10-13-21-11-30.gh-issue-125269.BC-fdo.rst
M configure
M configure.ac
diff --git
a/Misc/NEWS.d/next/Build/2024-10-13-21-11-30.gh-issue-125269.BC-fdo.rst
b/Misc/NEWS.d/next/Build/2024-10-13-21-11-30.gh-issue-125269.BC-fdo.rst
new file mode 100644
index 00..24f5469e8a664b
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2024-10-13-21-11-30.gh-issue-125269.BC-fdo.rst
@@ -0,0 +1,2 @@
+Fix detection of whether ``-latomic`` is needed when cross-compiling CPython
+using the configure script.
diff --git a/configure b/configure
index c5bec6a1b0d7c2..be119f108a060b 100755
--- a/configure
+++ b/configure
@@ -28999,10 +28999,6 @@ printf %s "checking whether libatomic is needed by
... " >&6; }
if test ${ac_cv_libatomic_needed+y}
then :
printf %s "(cached) " >&6
-else $as_nop
- if test "$cross_compiling" = yes
-then :
-ac_cv_libatomic_needed=no
else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -29044,16 +29040,14 @@ int main()
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"
+if ac_fn_c_try_link "$LINENO"
then :
ac_cv_libatomic_needed=no
else $as_nop
ac_cv_libatomic_needed=yes
fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+conftest$ac_exeext conftest.$ac_ext
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libatomic_needed"
>&5
printf "%s\n" "$ac_cv_libatomic_needed" >&6; }
diff --git a/configure.ac b/configure.ac
index d4b7942190207a..582851695e400f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7497,7 +7497,7 @@ CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include
${CPPFLAGS}"
AC_CACHE_CHECK([whether libatomic is needed by ],
[ac_cv_libatomic_needed],
-[AC_RUN_IFELSE([AC_LANG_SOURCE([[
+[AC_LINK_IFELSE([AC_LANG_SOURCE([[
// pyatomic.h needs uint64_t and Py_ssize_t types
#include // int64_t, intptr_t
#ifdef HAVE_SYS_TYPES_H
@@ -7534,9 +7534,8 @@ int main()
return 0; // all good
}
]])],
- [ac_cv_libatomic_needed=no], dnl build succeeded
- [ac_cv_libatomic_needed=yes], dnl build failed
- [ac_cv_libatomic_needed=no]) dnl cross compilation
+ [ac_cv_libatomic_needed=no], dnl build and link succeeded
+ [ac_cv_libatomic_needed=yes]) dnl build and link failed
])
AS_VAR_IF([ac_cv_libatomic_needed], [yes],
___
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]
[Python-checkins] gh-125323: Remove some unsafe Py_DECREFs in bytecodes.c, replacing them with PyStackRef_CLOSEs (GH-125324)
https://github.com/python/cpython/commit/4b358ee647809019813f106eb901f466a3846d98
commit: 4b358ee647809019813f106eb901f466a3846d98
branch: main
author: Ken Jin
committer: markshannon
date: 2024-10-14T09:17:51+01:00
summary:
gh-125323: Remove some unsafe Py_DECREFs in bytecodes.c, replacing them with
PyStackRef_CLOSEs (GH-125324)
files:
M Include/internal/pycore_stackref.h
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
diff --git a/Include/internal/pycore_stackref.h
b/Include/internal/pycore_stackref.h
index 7d1eb11aa5ecb8..0e6410466b924b 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -153,6 +153,8 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
return PyStackRef_FromPyObjectSteal(PyStackRef_AsPyObjectSteal(stackref));
}
+#define PyStackRef_CLOSE_SPECIALIZED(stackref, dealloc)
PyStackRef_CLOSE(stackref)
+
#else // Py_GIL_DISABLED
@@ -177,6 +179,7 @@ static const _PyStackRef PyStackRef_NULL = { .bits = 0 };
#define PyStackRef_DUP(stackref)
PyStackRef_FromPyObjectSteal(Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref)))
+#define PyStackRef_CLOSE_SPECIALIZED(stackref, dealloc)
_Py_DECREF_SPECIALIZED(PyStackRef_AsPyObjectBorrow(stackref), dealloc)
#endif // Py_GIL_DISABLED
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 34fdfcb05e3c18..299608f252c546 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -474,8 +474,8 @@ dummy_func(
STAT_INC(BINARY_OP, hit);
PyObject *res_o = _PyLong_Multiply((PyLongObject *)left_o,
(PyLongObject *)right_o);
-_Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free);
-_Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(right, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(left, (destructor)PyObject_Free);
INPUTS_DEAD();
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -487,8 +487,8 @@ dummy_func(
STAT_INC(BINARY_OP, hit);
PyObject *res_o = _PyLong_Add((PyLongObject *)left_o,
(PyLongObject *)right_o);
-_Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free);
-_Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(right, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(left, (destructor)PyObject_Free);
INPUTS_DEAD();
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -500,8 +500,8 @@ dummy_func(
STAT_INC(BINARY_OP, hit);
PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o,
(PyLongObject *)right_o);
-_Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free);
-_Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(right, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(left, (destructor)PyObject_Free);
INPUTS_DEAD();
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -594,8 +594,8 @@ dummy_func(
STAT_INC(BINARY_OP, hit);
PyObject *res_o = PyUnicode_Concat(left_o, right_o);
-_Py_DECREF_SPECIALIZED(left_o, _PyUnicode_ExactDealloc);
-_Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc);
+PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
INPUTS_DEAD();
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
@@ -636,12 +636,12 @@ dummy_func(
* that the string is safe to mutate.
*/
assert(Py_REFCNT(left_o) >= 2);
-_Py_DECREF_NO_DEALLOC(left_o);
+PyStackRef_CLOSE(left);
DEAD(left);
PyObject *temp = PyStackRef_AsPyObjectBorrow(*target_local);
PyUnicode_Append(&temp, right_o);
*target_local = PyStackRef_FromPyObjectSteal(temp);
-_Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc);
+PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
DEAD(right);
ERROR_IF(PyStackRef_IsNull(*target_local), error);
#if TIER_ONE
@@ -755,7 +755,7 @@ dummy_func(
PyObject *res_o = PyList_GET_ITEM(list, index);
assert(res_o != NULL);
Py_INCREF(res_o);
-_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
+PyStackRef_CLOSE_SPECIALIZED(sub_st, (destructor)PyObject_Free);
DEAD(sub_st);
PyStackRef_CLOSE(list_st);
res = PyStackRef_FromPyObjectSteal(re
[Python-checkins] gh-121797: Add class method Fraction.from_number() (GH-121800)
https://github.com/python/cpython/commit/b52c7306ea4470f9d7548655c2a1b89a07ff5504
commit: b52c7306ea4470f9d7548655c2a1b89a07ff5504
branch: main
author: Serhiy Storchaka
committer: serhiy-storchaka
date: 2024-10-14T07:54:59Z
summary:
gh-121797: Add class method Fraction.from_number() (GH-121800)
It is an alternative constructor which only accepts a single numeric argument.
Unlike to Fraction.from_float() and Fraction.from_decimal() it accepts any
real numbers supported by the standard constructor (int, float, Decimal,
Rational numbers, objects with as_integer_ratio()).
Unlike to the standard constructor, it does not accept strings.
files:
A Misc/NEWS.d/next/Library/2024-07-15-19-34-56.gh-issue-121797.qDqj59.rst
M Doc/library/fractions.rst
M Doc/whatsnew/3.14.rst
M Lib/fractions.py
M Lib/test/test_fractions.py
diff --git a/Doc/library/fractions.rst b/Doc/library/fractions.rst
index 2ee154952549ac..fc7f9a6301a915 100644
--- a/Doc/library/fractions.rst
+++ b/Doc/library/fractions.rst
@@ -166,6 +166,16 @@ another rational number, or from a string.
instance.
+ .. classmethod:: from_number(number)
+
+ Alternative constructor which only accepts instances of
+ :class:`numbers.Integral`, :class:`numbers.Rational`,
+ :class:`float` or :class:`decimal.Decimal`, and objects with
+ the :meth:`!as_integer_ratio` method, but not strings.
+
+ .. versionadded:: 3.14
+
+
.. method:: limit_denominator(max_denominator=100)
Finds and returns the closest :class:`Fraction` to ``self`` that has
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index c62a3ca5872eef..b22d1bd1e99d4e 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -263,6 +263,10 @@ fractions
:meth:`!as_integer_ratio` method to a :class:`~fractions.Fraction`.
(Contributed by Serhiy Storchaka in :gh:`82017`.)
+* Add alternative :class:`~fractions.Fraction` constructor
+ :meth:`Fraction.from_number() `.
+ (Contributed by Serhiy Storchaka in :gh:`121797`.)
+
functools
-
diff --git a/Lib/fractions.py b/Lib/fractions.py
index 34fd0803d1b1ab..f0cbc8c2e6c012 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -279,7 +279,8 @@ def __new__(cls, numerator=0, denominator=None):
numerator = -numerator
else:
-raise TypeError("argument should be a string or a number")
+raise TypeError("argument should be a string or a Rational "
+"instance or have the as_integer_ratio()
method")
elif type(numerator) is int is type(denominator):
pass # *very* normal case
@@ -305,6 +306,28 @@ def __new__(cls, numerator=0, denominator=None):
self._denominator = denominator
return self
+@classmethod
+def from_number(cls, number):
+"""Converts a finite real number to a rational number, exactly.
+
+Beware that Fraction.from_number(0.3) != Fraction(3, 10).
+
+"""
+if type(number) is int:
+return cls._from_coprime_ints(number, 1)
+
+elif isinstance(number, numbers.Rational):
+return cls._from_coprime_ints(number.numerator, number.denominator)
+
+elif (isinstance(number, float) or
+ (not isinstance(number, type) and
+ hasattr(number, 'as_integer_ratio'))):
+return cls._from_coprime_ints(*number.as_integer_ratio())
+
+else:
+raise TypeError("argument should be a Rational instance or "
+"have the as_integer_ratio() method")
+
@classmethod
def from_float(cls, f):
"""Converts a finite float to a rational number, exactly.
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index 4907f4093f52c9..98dccbec9566ac 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -283,6 +283,13 @@ def __repr__(self):
class RectComplex(Rect, complex):
pass
+class Ratio:
+def __init__(self, ratio):
+self._ratio = ratio
+def as_integer_ratio(self):
+return self._ratio
+
+
class FractionTest(unittest.TestCase):
def assertTypedEquals(self, expected, actual):
@@ -355,14 +362,9 @@ def testInitFromDecimal(self):
self.assertRaises(OverflowError, F, Decimal('-inf'))
def testInitFromIntegerRatio(self):
-class Ratio:
-def __init__(self, ratio):
-self._ratio = ratio
-def as_integer_ratio(self):
-return self._ratio
-
self.assertEqual((7, 3), _components(F(Ratio((7, 3)
-errmsg = "argument should be a string or a number"
+errmsg = (r"argument should be a string or a Rational instance or "
+ r"have the as_integer_ratio\(\) method")
# the type also has an "as_integer_ratio" attribute.
self.assertRaisesRegex(TypeError, errmsg, F, Ratio)
# bad ratio
@@ -388,6 +390,8 @@ class B(metacl
[Python-checkins] gh-121798: Add class method Decimal.from_number() (GH-121801)
https://github.com/python/cpython/commit/5217328f93f599755bd70418952392c54f705a71
commit: 5217328f93f599755bd70418952392c54f705a71
branch: main
author: Serhiy Storchaka
committer: serhiy-storchaka
date: 2024-10-14T08:24:01Z
summary:
gh-121798: Add class method Decimal.from_number() (GH-121801)
It is an alternate constructor which only accepts a single numeric argument.
Unlike to Decimal.from_float() it accepts also Decimal.
Unlike to the standard constructor, it does not accept strings and tuples.
files:
A Misc/NEWS.d/next/Library/2024-07-15-19-25-25.gh-issue-121798.GmuBDu.rst
M Doc/library/decimal.rst
M Doc/whatsnew/3.14.rst
M Lib/_pydecimal.py
M Lib/test/test_decimal.py
M Modules/_decimal/_decimal.c
M Modules/_decimal/docstrings.h
diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst
index 916f17cadfaa7e..c9a3e448cad063 100644
--- a/Doc/library/decimal.rst
+++ b/Doc/library/decimal.rst
@@ -598,6 +598,23 @@ Decimal objects
.. versionadded:: 3.1
+ .. classmethod:: from_number(number)
+
+ Alternative constructor that only accepts instances of
+ :class:`float`, :class:`int` or :class:`Decimal`, but not strings
+ or tuples.
+
+ .. doctest::
+
+ >>> Decimal.from_number(314)
+ Decimal('314')
+ >>> Decimal.from_number(0.1)
+ Decimal('0.155511151231257827021181583404541015625')
+ >>> Decimal.from_number(Decimal('3.14'))
+ Decimal('3.14')
+
+ .. versionadded:: 3.14
+
.. method:: fma(other, third, context=None)
Fused multiply-add. Return self*other+third with no rounding of the
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index b22d1bd1e99d4e..25e69a59bdec62 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -239,6 +239,12 @@ ctypes
to help match a non-default ABI.
(Contributed by Petr Viktorin in :gh:`97702`.)
+decimal
+---
+
+* Add alternative :class:`~decimal.Decimal` constructor
+ :meth:`Decimal.from_number() `.
+ (Contributed by Serhiy Storchaka in :gh:`121798`.)
dis
---
diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py
index 75df3db262470b..5b60570c6c592a 100644
--- a/Lib/_pydecimal.py
+++ b/Lib/_pydecimal.py
@@ -582,6 +582,21 @@ def __new__(cls, value="0", context=None):
raise TypeError("Cannot convert %r to Decimal" % value)
+@classmethod
+def from_number(cls, number):
+"""Converts a real number to a decimal number, exactly.
+
+>>> Decimal.from_number(314) # int
+Decimal('314')
+>>> Decimal.from_number(0.1) # float
+Decimal('0.155511151231257827021181583404541015625')
+>>> Decimal.from_number(Decimal('3.14')) # another decimal instance
+Decimal('3.14')
+"""
+if isinstance(number, (int, Decimal, float)):
+return cls(number)
+raise TypeError("Cannot convert %r to Decimal" % number)
+
@classmethod
def from_float(cls, f):
"""Converts a float to a decimal number, exactly.
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index d1e7e69e7e951b..bc6c6427740949 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -812,6 +812,29 @@ def test_explicit_context_create_from_float(self):
x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
+def test_from_number(self, cls=None):
+Decimal = self.decimal.Decimal
+if cls is None:
+cls = Decimal
+
+def check(arg, expected):
+d = cls.from_number(arg)
+self.assertIs(type(d), cls)
+self.assertEqual(d, expected)
+
+check(314, Decimal(314))
+check(3.14, Decimal.from_float(3.14))
+check(Decimal('3.14'), Decimal('3.14'))
+self.assertRaises(TypeError, cls.from_number, 3+4j)
+self.assertRaises(TypeError, cls.from_number, '314')
+self.assertRaises(TypeError, cls.from_number, (0, (3, 1, 4), 0))
+self.assertRaises(TypeError, cls.from_number, object())
+
+def test_from_number_subclass(self, cls=None):
+class DecimalSubclass(self.decimal.Decimal):
+pass
+self.test_from_number(DecimalSubclass)
+
def test_unicode_digits(self):
Decimal = self.decimal.Decimal
diff --git
a/Misc/NEWS.d/next/Library/2024-07-15-19-25-25.gh-issue-121798.GmuBDu.rst
b/Misc/NEWS.d/next/Library/2024-07-15-19-25-25.gh-issue-121798.GmuBDu.rst
new file mode 100644
index 00..5706e4bffeb4a1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-07-15-19-25-25.gh-issue-121798.GmuBDu.rst
@@ -0,0 +1,2 @@
+Add alternative :class:`~decimal.Decimal` constructor
+:meth:`Decimal.from_number() `.
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index a33c9793b5ad17..c564813036e504 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_d
[Python-checkins] gh-125139: use `_PyRecursiveMutex` in `_thread.RLock` (#125144)
https://github.com/python/cpython/commit/67f6e08147bc005e460d82fcce85bf5d56009cf5
commit: 67f6e08147bc005e460d82fcce85bf5d56009cf5
branch: main
author: Kumar Aditya
committer: kumaraditya303
date: 2024-10-14T14:06:31+05:30
summary:
gh-125139: use `_PyRecursiveMutex` in `_thread.RLock` (#125144)
files:
M Include/internal/pycore_lock.h
M Modules/_threadmodule.c
M Python/lock.c
diff --git a/Include/internal/pycore_lock.h b/Include/internal/pycore_lock.h
index cd7deda00c7bee..57cbce8f126aca 100644
--- a/Include/internal/pycore_lock.h
+++ b/Include/internal/pycore_lock.h
@@ -160,8 +160,9 @@ typedef struct {
PyAPI_FUNC(int) _PyRecursiveMutex_IsLockedByCurrentThread(_PyRecursiveMutex
*m);
PyAPI_FUNC(void) _PyRecursiveMutex_Lock(_PyRecursiveMutex *m);
+extern PyLockStatus _PyRecursiveMutex_LockTimed(_PyRecursiveMutex *m, PyTime_t
timeout, _PyLockFlags flags);
PyAPI_FUNC(void) _PyRecursiveMutex_Unlock(_PyRecursiveMutex *m);
-
+extern int _PyRecursiveMutex_TryUnlock(_PyRecursiveMutex *m);
// A readers-writer (RW) lock. The lock supports multiple concurrent readers or
// a single writer. The lock is write-preferring: if a writer is waiting while
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 9617f9cafe76ff..d4408aa9e42d9d 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -726,11 +726,6 @@ lock_dealloc(PyObject *op)
Py_DECREF(tp);
}
-static inline PyLockStatus
-acquire_timed(PyThread_type_lock lock, PyTime_t timeout)
-{
-return PyThread_acquire_lock_timed_with_retries(lock, timeout);
-}
static int
lock_acquire_parse_args(PyObject *args, PyObject *kwds,
@@ -973,10 +968,7 @@ static PyType_Spec lock_type_spec = {
typedef struct {
PyObject_HEAD
-PyThread_type_lock rlock_lock;
-PyThread_ident_t rlock_owner;
-unsigned long rlock_count;
-PyObject *in_weakreflist;
+_PyRecursiveMutex lock;
} rlockobject;
static int
@@ -992,59 +984,26 @@ rlock_dealloc(PyObject *op)
{
rlockobject *self = (rlockobject*)op;
PyObject_GC_UnTrack(self);
-if (self->in_weakreflist != NULL)
-PyObject_ClearWeakRefs((PyObject *) self);
-/* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
- in rlock_new() */
-if (self->rlock_lock != NULL) {
-/* Unlock the lock so it's safe to free it */
-if (self->rlock_count > 0)
-PyThread_release_lock(self->rlock_lock);
-
-PyThread_free_lock(self->rlock_lock);
-}
+PyObject_ClearWeakRefs((PyObject *) self);
PyTypeObject *tp = Py_TYPE(self);
tp->tp_free(self);
Py_DECREF(tp);
}
-static bool
-rlock_is_owned_by(rlockobject *self, PyThread_ident_t tid)
-{
-PyThread_ident_t owner_tid =
-_Py_atomic_load_ullong_relaxed(&self->rlock_owner);
-return owner_tid == tid && self->rlock_count > 0;
-}
static PyObject *
rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds)
{
rlockobject *self = (rlockobject*)op;
PyTime_t timeout;
-PyThread_ident_t tid;
-PyLockStatus r = PY_LOCK_ACQUIRED;
-if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
+if (lock_acquire_parse_args(args, kwds, &timeout) < 0) {
return NULL;
-
-tid = PyThread_get_thread_ident_ex();
-if (rlock_is_owned_by(self, tid)) {
-unsigned long count = self->rlock_count + 1;
-if (count <= self->rlock_count) {
-PyErr_SetString(PyExc_OverflowError,
-"Internal lock count overflowed");
-return NULL;
-}
-self->rlock_count = count;
-Py_RETURN_TRUE;
-}
-r = acquire_timed(self->rlock_lock, timeout);
-if (r == PY_LOCK_ACQUIRED) {
-assert(self->rlock_count == 0);
-_Py_atomic_store_ullong_relaxed(&self->rlock_owner, tid);
-self->rlock_count = 1;
}
-else if (r == PY_LOCK_INTR) {
+
+PyLockStatus r = _PyRecursiveMutex_LockTimed(&self->lock, timeout,
+ _PY_LOCK_HANDLE_SIGNALS |
_PY_LOCK_DETACH);
+if (r == PY_LOCK_INTR) {
return NULL;
}
@@ -1078,17 +1037,12 @@ static PyObject *
rlock_release(PyObject *op, PyObject *Py_UNUSED(ignored))
{
rlockobject *self = (rlockobject*)op;
-PyThread_ident_t tid = PyThread_get_thread_ident_ex();
-if (!rlock_is_owned_by(self, tid)) {
+if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) {
PyErr_SetString(PyExc_RuntimeError,
"cannot release un-acquired lock");
return NULL;
}
-if (--self->rlock_count == 0) {
-_Py_atomic_store_ullong_relaxed(&self->rlock_owner, 0);
-PyThread_release_lock(self->rlock_lock);
-}
Py_RETURN_NONE;
}
@@ -1116,25 +1070,15 @@ rlock_acquire_restore(PyObject *op, PyObject *args)
{
rlockobject *self = (rlockobject*)op;
PyThread_ident_t owner;
-unsigned long count;
-int r = 1;
+Py_ssize_t count;
-if (!PyArg_ParseTuple(args, "(k"
[Python-checkins] GH-125323: Convert DECREF_INPUTS_AND_REUSE_FLOAT into a function that takes PyStackRefs. (GH-125439)
https://github.com/python/cpython/commit/06ca33020e1168459fc6c3e0df93664daf801339
commit: 06ca33020e1168459fc6c3e0df93664daf801339
branch: main
author: Mark Shannon
committer: markshannon
date: 2024-10-14T14:18:57+01:00
summary:
GH-125323: Convert DECREF_INPUTS_AND_REUSE_FLOAT into a function that takes
PyStackRefs. (GH-125439)
files:
M Include/internal/pycore_ceval.h
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_stackref.h
M Include/internal/pycore_uop_metadata.h
M Objects/floatobject.c
M Python/bytecodes.c
M Python/ceval_macros.h
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Tools/cases_generator/analyzer.py
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 594fbb1c8e443b..cff2b1f7114793 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -316,6 +316,8 @@ _Py_eval_breaker_bit_is_set(PyThreadState *tstate,
uintptr_t bit)
void _Py_set_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
void _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit);
+PyAPI_FUNC(PyObject *) _PyFloat_FromDouble_ConsumeInputs(_PyStackRef left,
_PyStackRef right, double value);
+
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_opcode_metadata.h
b/Include/internal/pycore_opcode_metadata.h
index 8fec45b1e8d5c3..c18423476d3962 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -1015,13 +1015,13 @@ extern const struct opcode_metadata
_PyOpcode_opcode_metadata[266];
#ifdef NEED_OPCODE_METADATA
const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG |
HAS_ESCAPES_FLAG },
-[BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG },
+[BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_LOCAL_FLAG |
HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-[BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG },
+[BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
-[BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG },
+[BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG |
HAS_ERROR_FLAG },
[BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[BINARY_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG
},
diff --git a/Include/internal/pycore_stackref.h
b/Include/internal/pycore_stackref.h
index 0e6410466b924b..588e57f6cd97e0 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -76,6 +76,13 @@ PyStackRef_AsPyObjectBorrow(_PyStackRef stackref)
#define PyStackRef_IsDeferred(ref) (((ref).bits & Py_TAG_BITS) ==
Py_TAG_DEFERRED)
+static inline PyObject *
+PyStackRef_NotDeferred_AsPyObject(_PyStackRef stackref)
+{
+assert(!PyStackRef_IsDeferred(stackref));
+return (PyObject *)stackref.bits;
+}
+
static inline PyObject *
PyStackRef_AsPyObjectSteal(_PyStackRef stackref)
{
diff --git a/Include/internal/pycore_uop_metadata.h
b/Include/internal/pycore_uop_metadata.h
index fd41e9a5fe862b..2f0a7fb2f6e549 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -69,9 +69,9 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_GUARD_BOTH_FLOAT] = HAS_EXIT_FLAG,
[_GUARD_NOS_FLOAT] = HAS_EXIT_FLAG,
[_GUARD_TOS_FLOAT] = HAS_EXIT_FLAG,
-[_BINARY_OP_MULTIPLY_FLOAT] = HAS_PURE_FLAG,
-[_BINARY_OP_ADD_FLOAT] = HAS_PURE_FLAG,
-[_BINARY_OP_SUBTRACT_FLOAT] = HAS_PURE_FLAG,
+[_BINARY_OP_MULTIPLY_FLOAT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
+[_BINARY_OP_ADD_FLOAT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
+[_BINARY_OP_SUBTRACT_FLOAT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
[_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG,
[_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
[_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG |
HAS_ERROR_FLAG,
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index a48a210adee3b9..d66863febe8c86 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -134,6 +134,41 @@ PyFloat_FromDouble(double fval)
return (PyObject *) op;
}
+#ifdef Py_GIL_DISABLED
+
+PyObject *_PyFloat_FromDouble_ConsumeInputs(_PyStackRef left, _PyStackRef
right, double value)
+{
+PyStackRef_CLOSE(left);
+PyStackRef_CLOSE(right);
+return PyFloat_FromDouble(value);
+}
+
+#else // Py_GIL_DISABLED
+
+PyObje
[Python-checkins] gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL (#124999)
https://github.com/python/cpython/commit/6a08a753b702ac63c9b6ac58dd204d1fe9662e9d
commit: 6a08a753b702ac63c9b6ac58dd204d1fe9662e9d
branch: main
author: Wulian
committer: ambv
date: 2024-10-14T15:53:50+02:00
summary:
gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL
(#124999)
Co-authored-by: Nice Zombies
Co-authored-by: Łukasz Langa
files:
A Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
M Lib/_pyrepl/console.py
M Lib/codeop.py
M Lib/test/test_pyrepl/test_interact.py
diff --git a/Lib/_pyrepl/console.py b/Lib/_pyrepl/console.py
index 3e72a56807f6fb..03266c4dfc2dd8 100644
--- a/Lib/_pyrepl/console.py
+++ b/Lib/_pyrepl/console.py
@@ -174,7 +174,13 @@ def _excepthook(self, typ, value, tb):
def runsource(self, source, filename="", symbol="single"):
try:
-tree = ast.parse(source)
+tree = self.compile.compiler(
+source,
+filename,
+"exec",
+ast.PyCF_ONLY_AST,
+incomplete_input=False,
+)
except (SyntaxError, OverflowError, ValueError):
self.showsyntaxerror(filename, source=source)
return False
@@ -185,7 +191,7 @@ def runsource(self, source, filename="",
symbol="single"):
the_symbol = symbol if stmt is last_stmt else "exec"
item = wrapper([stmt])
try:
-code = self.compile.compiler(item, filename, the_symbol,
dont_inherit=True)
+code = self.compile.compiler(item, filename, the_symbol)
except SyntaxError as e:
if e.args[0] == "'await' outside function":
python = os.path.basename(sys.executable)
diff --git a/Lib/codeop.py b/Lib/codeop.py
index a0276b52d484e3..adf000ba29f88c 100644
--- a/Lib/codeop.py
+++ b/Lib/codeop.py
@@ -44,6 +44,7 @@
# Caveat emptor: These flags are undocumented on purpose and depending
# on their effect outside the standard library is **unsupported**.
PyCF_DONT_IMPLY_DEDENT = 0x200
+PyCF_ONLY_AST = 0x400
PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
def _maybe_compile(compiler, source, filename, symbol):
@@ -109,12 +110,14 @@ class Compile:
def __init__(self):
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
-def __call__(self, source, filename, symbol, **kwargs):
-flags = self.flags
+def __call__(self, source, filename, symbol, flags=0, **kwargs):
+flags |= self.flags
if kwargs.get('incomplete_input', True) is False:
flags &= ~PyCF_DONT_IMPLY_DEDENT
flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT
codeob = compile(source, filename, symbol, flags, True)
+if flags & PyCF_ONLY_AST:
+return codeob # this is an ast.Module in this case
for feature in _features:
if codeob.co_flags & feature.compiler_flag:
self.flags |= feature.compiler_flag
diff --git a/Lib/test/test_pyrepl/test_interact.py
b/Lib/test/test_pyrepl/test_interact.py
index b7adaffbac0e22..0c6df4e5dae869 100644
--- a/Lib/test/test_pyrepl/test_interact.py
+++ b/Lib/test/test_pyrepl/test_interact.py
@@ -119,13 +119,38 @@ def
test_runsource_shows_syntax_error_for_failed_compilation(self):
def test_no_active_future(self):
console = InteractiveColoredConsole()
-source = "x: int = 1; print(__annotate__(1))"
+source = dedent("""\
+x: int = 1
+print(__annotate__(1))
+""")
f = io.StringIO()
with contextlib.redirect_stdout(f):
result = console.runsource(source)
self.assertFalse(result)
self.assertEqual(f.getvalue(), "{'x': }\n")
+def test_future_annotations(self):
+console = InteractiveColoredConsole()
+source = dedent("""\
+from __future__ import annotations
+def g(x: int): ...
+print(g.__annotations__)
+""")
+f = io.StringIO()
+with contextlib.redirect_stdout(f):
+result = console.runsource(source)
+self.assertFalse(result)
+self.assertEqual(f.getvalue(), "{'x': 'int'}\n")
+
+def test_future_barry_as_flufl(self):
+console = InteractiveColoredConsole()
+f = io.StringIO()
+with contextlib.redirect_stdout(f):
+result = console.runsource("from __future__ import
barry_as_FLUFL\n")
+result = console.runsource("""print("black" <> 'blue')\n""")
+self.assertFalse(result)
+self.assertEqual(f.getvalue(), "True\n")
+
class TestMoreLines(unittest.TestCase):
def test_invalid_syntax_single_line(self):
diff --git
a/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
b/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
new file mode 100644
index 00..332d6bb54d80c7
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT
[Python-checkins] gh-112088: aclocal version is updated to 1.16.5 in docs (#125457)
https://github.com/python/cpython/commit/45df264f3ffbc0893cbfd257131d3abe21043786 commit: 45df264f3ffbc0893cbfd257131d3abe21043786 branch: main author: Mikhail Efimov committer: vstinner date: 2024-10-14T16:53:08+02:00 summary: gh-112088: aclocal version is updated to 1.16.5 in docs (#125457) files: M Doc/using/configure.rst M Doc/whatsnew/3.13.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 4976418ba33cf8..10cdf2376229ff 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -29,7 +29,7 @@ Features and minimum versions required to build CPython: * Tcl/Tk 8.5.12 for the :mod:`tkinter` module. -* Autoconf 2.71 and aclocal 1.16.4 are required to regenerate the +* Autoconf 2.71 and aclocal 1.16.5 are required to regenerate the :file:`configure` script. .. versionchanged:: 3.1 @@ -56,7 +56,7 @@ Features and minimum versions required to build CPython: Tcl/Tk version 8.5.12 is now required for the :mod:`tkinter` module. .. versionchanged:: 3.13 - Autoconf 2.71, aclocal 1.16.4 and SQLite 3.15.2 are now required. + Autoconf 2.71, aclocal 1.16.5 and SQLite 3.15.2 are now required. See also :pep:`7` "Style Guide for C Code" and :pep:`11` "CPython platform support". diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index a2897097aaba57..f9e74a9b8ff9c6 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -2495,9 +2495,9 @@ Build Changes * Building CPython now requires a compiler with support for the C11 atomic library, GCC built-in atomic functions, or MSVC interlocked intrinsics. -* Autoconf 2.71 and aclocal 1.16.4 are now required to regenerate +* Autoconf 2.71 and aclocal 1.16.5 are now required to regenerate the :file:`configure` script. - (Contributed by Christian Heimes in :gh:`89886`.) + (Contributed by Christian Heimes in :gh:`89886` and by Victor Stinner in :gh:`112090`.) * SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension module. ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] [3.13] gh-112088: aclocal version is updated to 1.16.5 in docs (GH-125457) (#125459)
https://github.com/python/cpython/commit/6c81928ba75efb17e1b3287ccf9500835d51c841 commit: 6c81928ba75efb17e1b3287ccf9500835d51c841 branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: vstinner date: 2024-10-14T15:02:06Z summary: [3.13] gh-112088: aclocal version is updated to 1.16.5 in docs (GH-125457) (#125459) gh-112088: aclocal version is updated to 1.16.5 in docs (GH-125457) (cherry picked from commit 45df264f3ffbc0893cbfd257131d3abe21043786) Co-authored-by: Mikhail Efimov files: M Doc/using/configure.rst M Doc/whatsnew/3.13.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 052289bd827366..d5a6ffb7bb334e 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -29,7 +29,7 @@ Features and minimum versions required to build CPython: * Tcl/Tk 8.5.12 for the :mod:`tkinter` module. -* Autoconf 2.71 and aclocal 1.16.4 are required to regenerate the +* Autoconf 2.71 and aclocal 1.16.5 are required to regenerate the :file:`configure` script. .. versionchanged:: 3.1 @@ -56,7 +56,7 @@ Features and minimum versions required to build CPython: Tcl/Tk version 8.5.12 is now required for the :mod:`tkinter` module. .. versionchanged:: 3.13 - Autoconf 2.71, aclocal 1.16.4 and SQLite 3.15.2 are now required. + Autoconf 2.71, aclocal 1.16.5 and SQLite 3.15.2 are now required. See also :pep:`7` "Style Guide for C Code" and :pep:`11` "CPython platform support". diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index a2897097aaba57..f9e74a9b8ff9c6 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -2495,9 +2495,9 @@ Build Changes * Building CPython now requires a compiler with support for the C11 atomic library, GCC built-in atomic functions, or MSVC interlocked intrinsics. -* Autoconf 2.71 and aclocal 1.16.4 are now required to regenerate +* Autoconf 2.71 and aclocal 1.16.5 are now required to regenerate the :file:`configure` script. - (Contributed by Christian Heimes in :gh:`89886`.) + (Contributed by Christian Heimes in :gh:`89886` and by Victor Stinner in :gh:`112090`.) * SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension module. ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] [3.12] gh-86357: argparse: use str() consistently and explicitly to print choices (GH-117766) (GH-125432)
https://github.com/python/cpython/commit/21524eec48f5b1c807f185253e9350cfdd897ce0
commit: 21524eec48f5b1c807f185253e9350cfdd897ce0
branch: 3.12
author: Serhiy Storchaka
committer: serhiy-storchaka
date: 2024-10-14T07:04:44Z
summary:
[3.12] gh-86357: argparse: use str() consistently and explicitly to print
choices (GH-117766) (GH-125432)
(cherry picked from commit 66b3922b97388c328c9bd8df050eef11c0261fae)
Signed-off-by: Jan Chren ~rindeal
Co-authored-by: rindeal
files:
A Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
M Lib/argparse.py
M Lib/test/test_argparse.py
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 0e13ea5860da97..22c9b07db18a4f 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -588,8 +588,7 @@ def _metavar_formatter(self, action, default_metavar):
if action.metavar is not None:
result = action.metavar
elif action.choices is not None:
-choice_strs = [str(choice) for choice in action.choices]
-result = '{%s}' % ','.join(choice_strs)
+result = '{%s}' % ','.join(map(str, action.choices))
else:
result = default_metavar
@@ -637,8 +636,7 @@ def _expand_help(self, action):
if hasattr(params[name], '__name__'):
params[name] = params[name].__name__
if params.get('choices') is not None:
-choices_str = ', '.join([str(c) for c in params['choices']])
-params['choices'] = choices_str
+params['choices'] = ', '.join(map(str, params['choices']))
return self._get_help_string(action) % params
def _iter_indented_subactions(self, action):
@@ -763,7 +761,7 @@ def _get_action_name(argument):
elif argument.dest not in (None, SUPPRESS):
return argument.dest
elif argument.choices:
-return '{' + ','.join(argument.choices) + '}'
+return '{%s}' % ','.join(map(str, argument.choices))
else:
return None
@@ -2600,8 +2598,8 @@ def _check_value(self, action, value):
if isinstance(choices, str):
choices = iter(choices)
if value not in choices:
-args = {'value': value,
-'choices': ', '.join(map(repr, action.choices))}
+args = {'value': str(value),
+'choices': ', '.join(map(str, action.choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
raise ArgumentError(action, msg % args)
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 956c1cd505a96e..d8a4a00292d230 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -15,6 +15,7 @@
import argparse
import warnings
+from enum import StrEnum
from test.support import os_helper
from unittest import mock
@@ -1021,6 +1022,34 @@ class
TestDisallowLongAbbreviationAllowsShortGroupingPrefix(ParserTestCase):
]
+class TestStrEnumChoices(TestCase):
+class Color(StrEnum):
+RED = "red"
+GREEN = "green"
+BLUE = "blue"
+
+def test_parse_enum_value(self):
+parser = argparse.ArgumentParser()
+parser.add_argument('--color', choices=self.Color)
+args = parser.parse_args(['--color', 'red'])
+self.assertEqual(args.color, self.Color.RED)
+
+def test_help_message_contains_enum_choices(self):
+parser = argparse.ArgumentParser()
+parser.add_argument('--color', choices=self.Color, help='Choose a
color')
+self.assertIn('[--color {red,green,blue}]', parser.format_usage())
+self.assertIn(' --color {red,green,blue}', parser.format_help())
+
+def test_invalid_enum_value_raises_error(self):
+parser = argparse.ArgumentParser(exit_on_error=False)
+parser.add_argument('--color', choices=self.Color)
+self.assertRaisesRegex(
+argparse.ArgumentError,
+r"invalid choice: 'yellow' \(choose from red, green, blue\)",
+parser.parse_args,
+['--color', 'yellow'],
+)
+
#
# Positional tests
#
@@ -2422,7 +2451,7 @@ def
test_wrong_argument_subparsers_no_destination_error(self):
parser.parse_args(('baz',))
self.assertRegex(
excinfo.exception.stderr,
-r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from
'foo', 'bar'\)\n$"
+r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from
foo, bar\)\n$"
)
def test_optional_subparsers(self):
diff --git
a/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
b/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
new file mode 100644
index 00..d090f931f0238d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
@@ -0,0 +1 @@
+Always use :func:`str` to print ``choices`` in :mod:`argparse`.
[Python-checkins] [3.13] gh-86357: argparse: use str() consistently and explicitly to print choices (GH-117766) (GH-125431)
https://github.com/python/cpython/commit/d3d306a9d63e879d4eac42694b94ed4a7f440332
commit: d3d306a9d63e879d4eac42694b94ed4a7f440332
branch: 3.13
author: Serhiy Storchaka
committer: serhiy-storchaka
date: 2024-10-14T07:09:06Z
summary:
[3.13] gh-86357: argparse: use str() consistently and explicitly to print
choices (GH-117766) (GH-125431)
(cherry picked from commit 66b3922b97388c328c9bd8df050eef11c0261fae)
Signed-off-by: Jan Chren ~rindeal
Co-authored-by: rindeal
files:
A Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
M Lib/argparse.py
M Lib/test/test_argparse.py
diff --git a/Lib/argparse.py b/Lib/argparse.py
index 663e40c8e2d7a6..395bb1cd13b966 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -547,8 +547,7 @@ def _metavar_formatter(self, action, default_metavar):
if action.metavar is not None:
result = action.metavar
elif action.choices is not None:
-choice_strs = [str(choice) for choice in action.choices]
-result = '{%s}' % ','.join(choice_strs)
+result = '{%s}' % ','.join(map(str, action.choices))
else:
result = default_metavar
@@ -596,8 +595,7 @@ def _expand_help(self, action):
if hasattr(params[name], '__name__'):
params[name] = params[name].__name__
if params.get('choices') is not None:
-choices_str = ', '.join([str(c) for c in params['choices']])
-params['choices'] = choices_str
+params['choices'] = ', '.join(map(str, params['choices']))
return self._get_help_string(action) % params
def _iter_indented_subactions(self, action):
@@ -714,7 +712,7 @@ def _get_action_name(argument):
elif argument.dest not in (None, SUPPRESS):
return argument.dest
elif argument.choices:
-return '{' + ','.join(argument.choices) + '}'
+return '{%s}' % ','.join(map(str, argument.choices))
else:
return None
@@ -2595,8 +2593,8 @@ def _check_value(self, action, value):
if isinstance(choices, str):
choices = iter(choices)
if value not in choices:
-args = {'value': value,
-'choices': ', '.join(map(repr, action.choices))}
+args = {'value': str(value),
+'choices': ', '.join(map(str, action.choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
raise ArgumentError(action, msg % args)
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 373c04b61a2615..77af8642c077a0 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -15,6 +15,7 @@
import argparse
import warnings
+from enum import StrEnum
from test.support import os_helper, captured_stderr
from unittest import mock
@@ -1021,6 +1022,34 @@ class
TestDisallowLongAbbreviationAllowsShortGroupingPrefix(ParserTestCase):
]
+class TestStrEnumChoices(TestCase):
+class Color(StrEnum):
+RED = "red"
+GREEN = "green"
+BLUE = "blue"
+
+def test_parse_enum_value(self):
+parser = argparse.ArgumentParser()
+parser.add_argument('--color', choices=self.Color)
+args = parser.parse_args(['--color', 'red'])
+self.assertEqual(args.color, self.Color.RED)
+
+def test_help_message_contains_enum_choices(self):
+parser = argparse.ArgumentParser()
+parser.add_argument('--color', choices=self.Color, help='Choose a
color')
+self.assertIn('[--color {red,green,blue}]', parser.format_usage())
+self.assertIn(' --color {red,green,blue}', parser.format_help())
+
+def test_invalid_enum_value_raises_error(self):
+parser = argparse.ArgumentParser(exit_on_error=False)
+parser.add_argument('--color', choices=self.Color)
+self.assertRaisesRegex(
+argparse.ArgumentError,
+r"invalid choice: 'yellow' \(choose from red, green, blue\)",
+parser.parse_args,
+['--color', 'yellow'],
+)
+
#
# Positional tests
#
@@ -2486,7 +2515,7 @@ def
test_wrong_argument_subparsers_no_destination_error(self):
parser.parse_args(('baz',))
self.assertRegex(
excinfo.exception.stderr,
-r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from
'foo', 'bar'\)\n$"
+r"error: argument {foo,bar}: invalid choice: 'baz' \(choose from
foo, bar\)\n$"
)
def test_optional_subparsers(self):
diff --git
a/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
b/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
new file mode 100644
index 00..d090f931f0238d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-04-19-05-58-50.gh-issue-117766.J3xepp.rst
@@ -0,0 +1 @@
+Always use :func:`str` to print ``choices`` in :mod:`arg
[Python-checkins] gh-111178: fix USAN failures for `partialobject` (#124733)
https://github.com/python/cpython/commit/c77121e9f19702b1ab280299394e38e8f15c0fd3 commit: c77121e9f19702b1ab280299394e38e8f15c0fd3 branch: main author: Bénédikt Tran <[email protected]> committer: vstinner date: 2024-10-14T16:23:05+02:00 summary: gh-78: fix USAN failures for `partialobject` (#124733) files: M Modules/_functoolsmodule.c diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 4ab3adc0fe44cc..802b1cf792c555 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -144,10 +144,13 @@ typedef struct { vectorcallfunc vectorcall; } partialobject; +// cast a PyObject pointer PTR to a partialobject pointer (no type checks) +#define _PyPartialObject_CAST(PTR) ((partialobject *)(PTR)) + static void partial_setvectorcall(partialobject *pto); static struct PyModuleDef _functools_module; static PyObject * -partial_call(partialobject *pto, PyObject *args, PyObject *kwargs); +partial_call(PyObject *pto, PyObject *args, PyObject *kwargs); static inline _functools_state * get_functools_state_by_type(PyTypeObject *type) @@ -307,8 +310,9 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) } static int -partial_clear(partialobject *pto) +partial_clear(PyObject *self) { +partialobject *pto = _PyPartialObject_CAST(self); Py_CLEAR(pto->fn); Py_CLEAR(pto->args); Py_CLEAR(pto->kw); @@ -317,8 +321,9 @@ partial_clear(partialobject *pto) } static int -partial_traverse(partialobject *pto, visitproc visit, void *arg) +partial_traverse(PyObject *self, visitproc visit, void *arg) { +partialobject *pto = _PyPartialObject_CAST(self); Py_VISIT(Py_TYPE(pto)); Py_VISIT(pto->fn); Py_VISIT(pto->args); @@ -328,16 +333,16 @@ partial_traverse(partialobject *pto, visitproc visit, void *arg) } static void -partial_dealloc(partialobject *pto) +partial_dealloc(PyObject *self) { -PyTypeObject *tp = Py_TYPE(pto); +PyTypeObject *tp = Py_TYPE(self); /* bpo-31095: UnTrack is needed before calling any callbacks */ -PyObject_GC_UnTrack(pto); -if (pto->weakreflist != NULL) { -PyObject_ClearWeakRefs((PyObject *) pto); +PyObject_GC_UnTrack(self); +if (_PyPartialObject_CAST(self)->weakreflist != NULL) { +PyObject_ClearWeakRefs(self); } -(void)partial_clear(pto); -tp->tp_free(pto); +(void)partial_clear(self); +tp->tp_free(self); Py_DECREF(tp); } @@ -360,14 +365,14 @@ partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto, { pto->vectorcall = NULL; Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); -return _PyObject_MakeTpCall(tstate, (PyObject *)pto, -args, nargs, kwnames); +return _PyObject_MakeTpCall(tstate, (PyObject *)pto, args, nargs, kwnames); } static PyObject * -partial_vectorcall(partialobject *pto, PyObject *const *args, +partial_vectorcall(PyObject *self, PyObject *const *args, size_t nargsf, PyObject *kwnames) { +partialobject *pto = _PyPartialObject_CAST(self);; PyThreadState *tstate = _PyThreadState_GET(); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); @@ -468,15 +473,16 @@ partial_setvectorcall(partialobject *pto) * but that is unlikely (why use partial without arguments?), * so we don't optimize that */ else { -pto->vectorcall = (vectorcallfunc)partial_vectorcall; +pto->vectorcall = partial_vectorcall; } } // Not converted to argument clinic, because of `*args, **kwargs` arguments. static PyObject * -partial_call(partialobject *pto, PyObject *args, PyObject *kwargs) +partial_call(PyObject *self, PyObject *args, PyObject *kwargs) { +partialobject *pto = _PyPartialObject_CAST(self); assert(PyCallable_Check(pto->fn)); assert(PyTuple_Check(pto->args)); assert(PyDict_Check(pto->kw)); @@ -587,8 +593,9 @@ static PyGetSetDef partial_getsetlist[] = { }; static PyObject * -partial_repr(partialobject *pto) +partial_repr(PyObject *self) { +partialobject *pto = _PyPartialObject_CAST(self); PyObject *result = NULL; PyObject *arglist; PyObject *mod; @@ -597,7 +604,7 @@ partial_repr(partialobject *pto) PyObject *key, *value; int status; -status = Py_ReprEnter((PyObject *)pto); +status = Py_ReprEnter(self); if (status != 0) { if (status < 0) return NULL; @@ -608,7 +615,7 @@ partial_repr(partialobject *pto) if (arglist == NULL) goto done; /* Pack positional arguments */ -assert (PyTuple_Check(pto->args)); +assert(PyTuple_Check(pto->args)); n = PyTuple_GET_SIZE(pto->args); for (i = 0; i < n; i++) { Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, @@ -643,11 +650,11 @@ partial_repr(partialobject *pto) Py_DECREF(arglist); done: -Py_ReprLeave((PyObject *)pto); +Py_ReprLeave(self); return result; error: Py_DECREF
[Python-checkins] [3.13] gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (GH-124959) (#125463)
https://github.com/python/cpython/commit/4e08c9829269525f097407ef017ebffd165e4ea9 commit: 4e08c9829269525f097407ef017ebffd165e4ea9 branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: 1st1 date: 2024-10-14T15:45:49Z summary: [3.13] gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (GH-124959) (#125463) gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (GH-124959) (cherry picked from commit d5dbbf4372cd3dbf3eead1cc70ddc4261c061fd9) Co-authored-by: Thomas Grainger files: A Misc/NEWS.d/next/Library/2024-10-04-08-46-00.gh-issue-124958.rea9-x.rst M Lib/asyncio/futures.py M Lib/asyncio/taskgroups.py M Lib/test/test_asyncio/test_futures.py M Lib/test/test_asyncio/test_taskgroups.py diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 9c1b5e49e1a70b..51932639097bbd 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -191,8 +191,7 @@ def result(self): the future is done and has an exception set, this exception is raised. """ if self._state == _CANCELLED: -exc = self._make_cancelled_error() -raise exc +raise self._make_cancelled_error() if self._state != _FINISHED: raise exceptions.InvalidStateError('Result is not ready.') self.__log_traceback = False @@ -209,8 +208,7 @@ def exception(self): InvalidStateError. """ if self._state == _CANCELLED: -exc = self._make_cancelled_error() -raise exc +raise self._make_cancelled_error() if self._state != _FINISHED: raise exceptions.InvalidStateError('Exception is not set.') self.__log_traceback = False diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index f2ee9648c43876..9fa772ca9d02cc 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -66,6 +66,20 @@ async def __aenter__(self): return self async def __aexit__(self, et, exc, tb): +tb = None +try: +return await self._aexit(et, exc) +finally: +# Exceptions are heavy objects that can have object +# cycles (bad for GC); let's not keep a reference to +# a bunch of them. It would be nicer to use a try/finally +# in __aexit__ directly but that introduced some diff noise +self._parent_task = None +self._errors = None +self._base_error = None +exc = None + +async def _aexit(self, et, exc): self._exiting = True if (exc is not None and @@ -122,7 +136,10 @@ async def __aexit__(self, et, exc, tb): assert not self._tasks if self._base_error is not None: -raise self._base_error +try: +raise self._base_error +finally: +exc = None if self._parent_cancel_requested: # If this flag is set we *must* call uncancel(). @@ -133,8 +150,14 @@ async def __aexit__(self, et, exc, tb): # Propagate CancelledError if there is one, except if there # are other errors -- those have priority. -if propagate_cancellation_error is not None and not self._errors: -raise propagate_cancellation_error +try: +if propagate_cancellation_error is not None and not self._errors: +try: +raise propagate_cancellation_error +finally: +exc = None +finally: +propagate_cancellation_error = None if et is not None and not issubclass(et, exceptions.CancelledError): self._errors.append(exc) @@ -146,14 +169,14 @@ async def __aexit__(self, et, exc, tb): if self._parent_task.cancelling(): self._parent_task.uncancel() self._parent_task.cancel() -# Exceptions are heavy objects that can have object -# cycles (bad for GC); let's not keep a reference to -# a bunch of them. try: -me = BaseExceptionGroup('unhandled errors in a TaskGroup', self._errors) -raise me from None +raise BaseExceptionGroup( +'unhandled errors in a TaskGroup', +self._errors, +) from None finally: -self._errors = None +exc = None + def create_task(self, coro, *, name=None, context=None): """Create a new task in this group and return it. diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index 2417712a9c9b64..32e7b5d9047c06 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -659,6 +659,28 @@ def __del__(self): fut = self._new_future(loop=self.loop) fut.set_result(Evil()) +de
[Python-checkins] [3.13] gh-125461: Remove Python 2 from identifiers in doc (GH-125462) (GH-125464)
https://github.com/python/cpython/commit/7966c7d69e43d2b946c5933f5249091466ba1f5e commit: 7966c7d69e43d2b946c5933f5249091466ba1f5e branch: 3.13 author: Miss Islington (bot) <[email protected]> committer: willingc date: 2024-10-14T08:49:35-07:00 summary: [3.13] gh-125461: Remove Python 2 from identifiers in doc (GH-125462) (GH-125464) gh-125461: Remove Python 2 from identifiers in doc (GH-125462) Remove Python 2 from identifiers in doc (cherry picked from commit 5dac0dceda9097d46a0b5a6ad7c927e002c6c7a5) Co-authored-by: Paul Hoffman files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index c2f5f145bb22b2..bffef9db8fb632 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -284,11 +284,10 @@ UAX-31, with elaboration and changes as defined below; see also :pep:`3131` for further details. Within the ASCII range (U+0001..U+007F), the valid characters for identifiers -are the same as in Python 2.x: the uppercase and lowercase letters ``A`` through +include the uppercase and lowercase letters ``A`` through ``Z``, the underscore ``_`` and, except for the first character, the digits ``0`` through ``9``. - -Python 3.0 introduces additional characters from outside the ASCII range (see +Python 3.0 introduced additional characters from outside the ASCII range (see :pep:`3131`). For these characters, the classification uses the version of the Unicode Character Database as included in the :mod:`unicodedata` module. ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] [3.12] gh-125461: Remove Python 2 from identifiers in doc (GH-125462) (#125465)
https://github.com/python/cpython/commit/f1a6f687774ca09255c48d76deb060bd09c8e1ca commit: f1a6f687774ca09255c48d76deb060bd09c8e1ca branch: 3.12 author: Miss Islington (bot) <[email protected]> committer: willingc date: 2024-10-14T08:49:56-07:00 summary: [3.12] gh-125461: Remove Python 2 from identifiers in doc (GH-125462) (#125465) gh-125461: Remove Python 2 from identifiers in doc (GH-125462) Remove Python 2 from identifiers in doc (cherry picked from commit 5dac0dceda9097d46a0b5a6ad7c927e002c6c7a5) Co-authored-by: Paul Hoffman files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index cfae01ba97a555..41d8fbaee97750 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -284,11 +284,10 @@ UAX-31, with elaboration and changes as defined below; see also :pep:`3131` for further details. Within the ASCII range (U+0001..U+007F), the valid characters for identifiers -are the same as in Python 2.x: the uppercase and lowercase letters ``A`` through +include the uppercase and lowercase letters ``A`` through ``Z``, the underscore ``_`` and, except for the first character, the digits ``0`` through ``9``. - -Python 3.0 introduces additional characters from outside the ASCII range (see +Python 3.0 introduced additional characters from outside the ASCII range (see :pep:`3131`). For these characters, the classification uses the version of the Unicode Character Database as included in the :mod:`unicodedata` module. ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] gh-119786: [doc] broken link and typo fix in interpreter_definition.md (#125455)
https://github.com/python/cpython/commit/187580d95c8339a3b6e2b012f98d86101c346cfa commit: 187580d95c8339a3b6e2b012f98d86101c346cfa branch: main author: Mikhail Efimov committer: iritkatriel <[email protected]> date: 2024-10-14T17:24:54Z summary: gh-119786: [doc] broken link and typo fix in interpreter_definition.md (#125455) files: M InternalDocs/README.md M Tools/cases_generator/interpreter_definition.md diff --git a/InternalDocs/README.md b/InternalDocs/README.md index 805e2f97937e1e..0a6ecf899458ed 100644 --- a/InternalDocs/README.md +++ b/InternalDocs/README.md @@ -11,6 +11,8 @@ The core dev team attempts to keep this documentation up to date. If it is not, please report that through the [issue tracker](https://github.com/python/cpython/issues). +Index: +- [Guide to the parser](parser.md) diff --git a/Tools/cases_generator/interpreter_definition.md b/Tools/cases_generator/interpreter_definition.md index ba09931c541646..6cf36f343d5fa7 100644 --- a/Tools/cases_generator/interpreter_definition.md +++ b/Tools/cases_generator/interpreter_definition.md @@ -74,7 +74,7 @@ We update it as the need arises. ### Syntax Each op definition has a kind, a name, a stack and instruction stream effect, -and a piece of C code describing its semantics:: +and a piece of C code describing its semantics: ``` file: @@ -245,7 +245,8 @@ The same is true for all members of a pseudo instruction ## Examples -(Another source of examples can be found in the [tests](test_generator.py).) +(Another source of examples can be found in the +[tests](https://github.com/python/cpython/blob/main/Lib/test/test_generated_cases.py).) Some examples: ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
[Python-checkins] gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#12… (#125476)
https://github.com/python/cpython/commit/e99650b80ace3893c2a80b3f2a4aca99cb305191
commit: e99650b80ace3893c2a80b3f2a4aca99cb305191
branch: main
author: Kirill Podoprigora
committer: kumaraditya303
date: 2024-10-14T17:59:13Z
summary:
gh-125472: Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles
(#12… (#125476)
Revert "gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#124959)"
This reverts commit d5dbbf4372cd3dbf3eead1cc70ddc4261c061fd9.
files:
D Misc/NEWS.d/next/Library/2024-10-04-08-46-00.gh-issue-124958.rea9-x.rst
M Lib/asyncio/futures.py
M Lib/asyncio/taskgroups.py
M Lib/test/test_asyncio/test_futures.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
index c95fce035cd548..5f6fa2348726cf 100644
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -190,7 +190,8 @@ def result(self):
the future is done and has an exception set, this exception is raised.
"""
if self._state == _CANCELLED:
-raise self._make_cancelled_error()
+exc = self._make_cancelled_error()
+raise exc
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Result is not ready.')
self.__log_traceback = False
@@ -207,7 +208,8 @@ def exception(self):
InvalidStateError.
"""
if self._state == _CANCELLED:
-raise self._make_cancelled_error()
+exc = self._make_cancelled_error()
+raise exc
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Exception is not set.')
self.__log_traceback = False
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 9fa772ca9d02cc..f2ee9648c43876 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -66,20 +66,6 @@ async def __aenter__(self):
return self
async def __aexit__(self, et, exc, tb):
-tb = None
-try:
-return await self._aexit(et, exc)
-finally:
-# Exceptions are heavy objects that can have object
-# cycles (bad for GC); let's not keep a reference to
-# a bunch of them. It would be nicer to use a try/finally
-# in __aexit__ directly but that introduced some diff noise
-self._parent_task = None
-self._errors = None
-self._base_error = None
-exc = None
-
-async def _aexit(self, et, exc):
self._exiting = True
if (exc is not None and
@@ -136,10 +122,7 @@ async def _aexit(self, et, exc):
assert not self._tasks
if self._base_error is not None:
-try:
-raise self._base_error
-finally:
-exc = None
+raise self._base_error
if self._parent_cancel_requested:
# If this flag is set we *must* call uncancel().
@@ -150,14 +133,8 @@ async def _aexit(self, et, exc):
# Propagate CancelledError if there is one, except if there
# are other errors -- those have priority.
-try:
-if propagate_cancellation_error is not None and not self._errors:
-try:
-raise propagate_cancellation_error
-finally:
-exc = None
-finally:
-propagate_cancellation_error = None
+if propagate_cancellation_error is not None and not self._errors:
+raise propagate_cancellation_error
if et is not None and not issubclass(et, exceptions.CancelledError):
self._errors.append(exc)
@@ -169,14 +146,14 @@ async def _aexit(self, et, exc):
if self._parent_task.cancelling():
self._parent_task.uncancel()
self._parent_task.cancel()
+# Exceptions are heavy objects that can have object
+# cycles (bad for GC); let's not keep a reference to
+# a bunch of them.
try:
-raise BaseExceptionGroup(
-'unhandled errors in a TaskGroup',
-self._errors,
-) from None
+me = BaseExceptionGroup('unhandled errors in a TaskGroup',
self._errors)
+raise me from None
finally:
-exc = None
-
+self._errors = None
def create_task(self, coro, *, name=None, context=None):
"""Create a new task in this group and return it.
diff --git a/Lib/test/test_asyncio/test_futures.py
b/Lib/test/test_asyncio/test_futures.py
index c566b28adb2408..458b70451a306a 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -659,28 +659,6 @@ def __del__(self):
fut = self._new_future(loop=self.loop)
fut.set_result(Evil())
-def test_future_cancelled_result_refcycles(self):
-f = self._new_future(loop=self.lo
[Python-checkins] [3.13] gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL (#124999) (#125475)
https://github.com/python/cpython/commit/d54dbd62cc9dae9ddee7a1179fb26ccdd4e409dc
commit: d54dbd62cc9dae9ddee7a1179fb26ccdd4e409dc
branch: 3.13
author: Nice Zombies
committer: ambv
date: 2024-10-14T20:00:45+02:00
summary:
[3.13] gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL
(#124999) (#125475)
gh-124960: Fixed `barry_as_FLUFL` future flag does not work in new REPL
(#124999)
Co-authored-by: Wulian
Co-authored-by: Nice Zombies
Co-authored-by: Łukasz Langa
(cherry picked from commit 6a08a753b702ac63c9b6ac58dd204d1fe9662e9d)
files:
A Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
M Lib/_pyrepl/console.py
M Lib/codeop.py
M Lib/test/test_pyrepl/test_interact.py
diff --git a/Lib/_pyrepl/console.py b/Lib/_pyrepl/console.py
index 3e72a56807f6fb..03266c4dfc2dd8 100644
--- a/Lib/_pyrepl/console.py
+++ b/Lib/_pyrepl/console.py
@@ -174,7 +174,13 @@ def _excepthook(self, typ, value, tb):
def runsource(self, source, filename="", symbol="single"):
try:
-tree = ast.parse(source)
+tree = self.compile.compiler(
+source,
+filename,
+"exec",
+ast.PyCF_ONLY_AST,
+incomplete_input=False,
+)
except (SyntaxError, OverflowError, ValueError):
self.showsyntaxerror(filename, source=source)
return False
@@ -185,7 +191,7 @@ def runsource(self, source, filename="",
symbol="single"):
the_symbol = symbol if stmt is last_stmt else "exec"
item = wrapper([stmt])
try:
-code = self.compile.compiler(item, filename, the_symbol,
dont_inherit=True)
+code = self.compile.compiler(item, filename, the_symbol)
except SyntaxError as e:
if e.args[0] == "'await' outside function":
python = os.path.basename(sys.executable)
diff --git a/Lib/codeop.py b/Lib/codeop.py
index a0276b52d484e3..adf000ba29f88c 100644
--- a/Lib/codeop.py
+++ b/Lib/codeop.py
@@ -44,6 +44,7 @@
# Caveat emptor: These flags are undocumented on purpose and depending
# on their effect outside the standard library is **unsupported**.
PyCF_DONT_IMPLY_DEDENT = 0x200
+PyCF_ONLY_AST = 0x400
PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
def _maybe_compile(compiler, source, filename, symbol):
@@ -109,12 +110,14 @@ class Compile:
def __init__(self):
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
-def __call__(self, source, filename, symbol, **kwargs):
-flags = self.flags
+def __call__(self, source, filename, symbol, flags=0, **kwargs):
+flags |= self.flags
if kwargs.get('incomplete_input', True) is False:
flags &= ~PyCF_DONT_IMPLY_DEDENT
flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT
codeob = compile(source, filename, symbol, flags, True)
+if flags & PyCF_ONLY_AST:
+return codeob # this is an ast.Module in this case
for feature in _features:
if codeob.co_flags & feature.compiler_flag:
self.flags |= feature.compiler_flag
diff --git a/Lib/test/test_pyrepl/test_interact.py
b/Lib/test/test_pyrepl/test_interact.py
index e71ab419570a86..b746674b9ff889 100644
--- a/Lib/test/test_pyrepl/test_interact.py
+++ b/Lib/test/test_pyrepl/test_interact.py
@@ -119,13 +119,38 @@ def
test_runsource_shows_syntax_error_for_failed_compilation(self):
def test_no_active_future(self):
console = InteractiveColoredConsole()
-source = "x: int = 1; print(__annotations__)"
+source = dedent("""\
+x: int = 1
+print(__annotations__)
+""")
f = io.StringIO()
with contextlib.redirect_stdout(f):
result = console.runsource(source)
self.assertFalse(result)
self.assertEqual(f.getvalue(), "{'x': }\n")
+def test_future_annotations(self):
+console = InteractiveColoredConsole()
+source = dedent("""\
+from __future__ import annotations
+def g(x: int): ...
+print(g.__annotations__)
+""")
+f = io.StringIO()
+with contextlib.redirect_stdout(f):
+result = console.runsource(source)
+self.assertFalse(result)
+self.assertEqual(f.getvalue(), "{'x': 'int'}\n")
+
+def test_future_barry_as_flufl(self):
+console = InteractiveColoredConsole()
+f = io.StringIO()
+with contextlib.redirect_stdout(f):
+result = console.runsource("from __future__ import
barry_as_FLUFL\n")
+result = console.runsource("""print("black" <> 'blue')\n""")
+self.assertFalse(result)
+self.assertEqual(f.getvalue(), "True\n")
+
class TestMoreLines(unittest.TestCase):
def test_invalid_syntax_single_line(self):
diff --git
a/Misc/NEWS.d/next/Library/2024-10-05-15-49-53.gh-issue-124960.Bol9hT.rst
b/Misc/NEWS.d/next/
[Python-checkins] gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#124959)
https://github.com/python/cpython/commit/d5dbbf4372cd3dbf3eead1cc70ddc4261c061fd9
commit: d5dbbf4372cd3dbf3eead1cc70ddc4261c061fd9
branch: main
author: Thomas Grainger
committer: 1st1
date: 2024-10-14T08:19:56-07:00
summary:
gh-124958: fix asyncio.TaskGroup and _PyFuture refcycles (#124959)
files:
A Misc/NEWS.d/next/Library/2024-10-04-08-46-00.gh-issue-124958.rea9-x.rst
M Lib/asyncio/futures.py
M Lib/asyncio/taskgroups.py
M Lib/test/test_asyncio/test_futures.py
M Lib/test/test_asyncio/test_taskgroups.py
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
index 5f6fa2348726cf..c95fce035cd548 100644
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -190,8 +190,7 @@ def result(self):
the future is done and has an exception set, this exception is raised.
"""
if self._state == _CANCELLED:
-exc = self._make_cancelled_error()
-raise exc
+raise self._make_cancelled_error()
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Result is not ready.')
self.__log_traceback = False
@@ -208,8 +207,7 @@ def exception(self):
InvalidStateError.
"""
if self._state == _CANCELLED:
-exc = self._make_cancelled_error()
-raise exc
+raise self._make_cancelled_error()
if self._state != _FINISHED:
raise exceptions.InvalidStateError('Exception is not set.')
self.__log_traceback = False
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index f2ee9648c43876..9fa772ca9d02cc 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -66,6 +66,20 @@ async def __aenter__(self):
return self
async def __aexit__(self, et, exc, tb):
+tb = None
+try:
+return await self._aexit(et, exc)
+finally:
+# Exceptions are heavy objects that can have object
+# cycles (bad for GC); let's not keep a reference to
+# a bunch of them. It would be nicer to use a try/finally
+# in __aexit__ directly but that introduced some diff noise
+self._parent_task = None
+self._errors = None
+self._base_error = None
+exc = None
+
+async def _aexit(self, et, exc):
self._exiting = True
if (exc is not None and
@@ -122,7 +136,10 @@ async def __aexit__(self, et, exc, tb):
assert not self._tasks
if self._base_error is not None:
-raise self._base_error
+try:
+raise self._base_error
+finally:
+exc = None
if self._parent_cancel_requested:
# If this flag is set we *must* call uncancel().
@@ -133,8 +150,14 @@ async def __aexit__(self, et, exc, tb):
# Propagate CancelledError if there is one, except if there
# are other errors -- those have priority.
-if propagate_cancellation_error is not None and not self._errors:
-raise propagate_cancellation_error
+try:
+if propagate_cancellation_error is not None and not self._errors:
+try:
+raise propagate_cancellation_error
+finally:
+exc = None
+finally:
+propagate_cancellation_error = None
if et is not None and not issubclass(et, exceptions.CancelledError):
self._errors.append(exc)
@@ -146,14 +169,14 @@ async def __aexit__(self, et, exc, tb):
if self._parent_task.cancelling():
self._parent_task.uncancel()
self._parent_task.cancel()
-# Exceptions are heavy objects that can have object
-# cycles (bad for GC); let's not keep a reference to
-# a bunch of them.
try:
-me = BaseExceptionGroup('unhandled errors in a TaskGroup',
self._errors)
-raise me from None
+raise BaseExceptionGroup(
+'unhandled errors in a TaskGroup',
+self._errors,
+) from None
finally:
-self._errors = None
+exc = None
+
def create_task(self, coro, *, name=None, context=None):
"""Create a new task in this group and return it.
diff --git a/Lib/test/test_asyncio/test_futures.py
b/Lib/test/test_asyncio/test_futures.py
index 458b70451a306a..c566b28adb2408 100644
--- a/Lib/test/test_asyncio/test_futures.py
+++ b/Lib/test/test_asyncio/test_futures.py
@@ -659,6 +659,28 @@ def __del__(self):
fut = self._new_future(loop=self.loop)
fut.set_result(Evil())
+def test_future_cancelled_result_refcycles(self):
+f = self._new_future(loop=self.loop)
+f.cancel()
+exc = None
+try:
+f.result()
+except asyncio.CancelledError as e:
+exc = e
+
[Python-checkins] gh-125461: Remove Python 2 from identifiers in doc (GH-125462)
https://github.com/python/cpython/commit/5dac0dceda9097d46a0b5a6ad7c927e002c6c7a5 commit: 5dac0dceda9097d46a0b5a6ad7c927e002c6c7a5 branch: main author: Paul Hoffman committer: willingc date: 2024-10-14T15:26:57Z summary: gh-125461: Remove Python 2 from identifiers in doc (GH-125462) Remove Python 2 from identifiers in doc files: M Doc/reference/lexical_analysis.rst diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index ae5408ee386bbd..f7167032ad7df9 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -284,11 +284,10 @@ UAX-31, with elaboration and changes as defined below; see also :pep:`3131` for further details. Within the ASCII range (U+0001..U+007F), the valid characters for identifiers -are the same as in Python 2.x: the uppercase and lowercase letters ``A`` through +include the uppercase and lowercase letters ``A`` through ``Z``, the underscore ``_`` and, except for the first character, the digits ``0`` through ``9``. - -Python 3.0 introduces additional characters from outside the ASCII range (see +Python 3.0 introduced additional characters from outside the ASCII range (see :pep:`3131`). For these characters, the classification uses the version of the Unicode Character Database as included in the :mod:`unicodedata` module. ___ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
