diff -Nru python3.10-3.10.7/configure python3.10-3.10.12/configure --- python3.10-3.10.7/configure 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/configure 2023-06-06 22:30:33.000000000 +0000 @@ -5929,7 +5929,7 @@ CC="$CC -pg" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int main() { return 0; } +int main(void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : @@ -7752,7 +7752,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -7808,7 +7808,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -7858,7 +7858,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -7908,7 +7908,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -10447,7 +10447,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int main() +int main(void) { char s[16]; int i, *p1, *p2; @@ -11024,6 +11024,7 @@ /* end confdefs.h. */ #include +#include #include void * start_routine (void *arg) { exit (0); } @@ -11325,7 +11326,7 @@ void *foo(void *parm) { return NULL; } - main() { + int main(void) { pthread_attr_t attr; pthread_t id; if (pthread_attr_init(&attr)) return (-1); @@ -12687,7 +12688,7 @@ #include #include -int main(int argc, char*argv[]) +int main(int argc, char *argv[]) { if(chflags(argv[0], 0) != 0) return 1; @@ -12736,7 +12737,7 @@ #include #include -int main(int argc, char*argv[]) +int main(int argc, char *argv[]) { if(lchflags(argv[0], 0) != 0) return 1; @@ -13653,7 +13654,7 @@ #include #include -int main() +int main(void) { int passive, gaierr, inet4 = 0, inet6 = 0; struct addrinfo hints, *ai, *aitop; @@ -14880,7 +14881,7 @@ #include #include -int main() { +int main(void) { volatile double x, y, z; /* 1./(1-2**-53) -> 1+2**-52 (correct), 1.0 (double rounding) */ x = 0.99999999999999989; /* 1-2**-53 */ @@ -15730,7 +15731,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int main() +int main(void) { return (((-1)>>3 == -1) ? 0 : 1); } @@ -16178,7 +16179,7 @@ #include #include -int main() +int main(void) { int val1 = nice(1); if (val1 != -1 && val1 == nice(2)) @@ -16221,7 +16222,7 @@ #include #include -int main() +int main(void) { struct pollfd poll_struct = { 42, POLLIN|POLLPRI|POLLOUT, 0 }; int poll_test; @@ -16279,7 +16280,7 @@ extern char *tzname[]; #endif -int main() +int main(void) { /* Note that we need to ensure that not only does tzset(3) do 'something' with localtime, but it works as documented @@ -17040,9 +17041,10 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#include #include -#include -int main() { +#include +int main(void) { size_t len = -1; const char *str = "text"; len = mbstowcs(NULL, str, 0); @@ -17219,7 +17221,7 @@ #include #include void foo(void *p, void *q) { memmove(p, q, 19); } -int main() { +int main(void) { char a[32] = "123456789000000000"; foo(&a[9], a); if (strcmp(a, "123456789123456789000000000") != 0) @@ -17274,7 +17276,7 @@ ); return r; } - int main() { + int main(void) { int p = 8; if ((foo(&p) ? : p) != 6) return 1; @@ -17313,7 +17315,7 @@ #include atomic_int int_var; atomic_uintptr_t uintptr_var; - int main() { + int main(void) { atomic_store_explicit(&int_var, 5, memory_order_relaxed); atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); @@ -17347,7 +17349,7 @@ int val; - int main() { + int main(void) { __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); return 0; @@ -17406,7 +17408,7 @@ #include - int main() { + int main(void) { struct dirent entry; return entry.d_type == DT_UNKNOWN; } @@ -17436,11 +17438,12 @@ /* end confdefs.h. */ + #include #include #include #include - int main() { + int main(void) { char buffer[1]; const size_t buflen = sizeof(buffer); const int flags = GRND_NONBLOCK; @@ -17475,9 +17478,10 @@ /* end confdefs.h. */ + #include #include - int main() { + int main(void) { char buffer[1]; const size_t buflen = sizeof(buffer); const int flags = 0; diff -Nru python3.10-3.10.7/configure.ac python3.10-3.10.12/configure.ac --- python3.10-3.10.7/configure.ac 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/configure.ac 2023-06-06 22:30:33.000000000 +0000 @@ -1099,7 +1099,7 @@ if test "x$enable_profiling" = xyes; then ac_save_cc="$CC" CC="$CC -pg" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], [], [enable_profiling=no]) CC="$ac_save_cc" @@ -2057,7 +2057,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -2092,7 +2092,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -2121,7 +2121,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -2150,7 +2150,7 @@ void* routine(void* p){return NULL;} -int main(){ +int main(void){ pthread_t p; if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; @@ -2991,7 +2991,7 @@ AC_MSG_CHECKING(aligned memory access is required) AC_CACHE_VAL(ac_cv_aligned_required, [AC_RUN_IFELSE([AC_LANG_SOURCE([[ -int main() +int main(void) { char s[16]; int i, *p1, *p2; @@ -3279,6 +3279,7 @@ AC_MSG_CHECKING([for pthread_create in -lpthread]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include +#include #include void * start_routine (void *arg) { exit (0); }]], [[ @@ -3344,7 +3345,7 @@ void *foo(void *parm) { return NULL; } - main() { + int main(void) { pthread_attr_t attr; pthread_t id; if (pthread_attr_init(&attr)) return (-1); @@ -3912,7 +3913,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include -int main(int argc, char*argv[]) +int main(int argc, char *argv[]) { if(chflags(argv[0], 0) != 0) return 1; @@ -3934,7 +3935,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include -int main(int argc, char*argv[]) +int main(int argc, char *argv[]) { if(lchflags(argv[0], 0) != 0) return 1; @@ -4135,7 +4136,7 @@ #include #include -int main() +int main(void) { int passive, gaierr, inet4 = 0, inet6 = 0; struct addrinfo hints, *ai, *aitop; @@ -4593,7 +4594,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include -int main() { +int main(void) { volatile double x, y, z; /* 1./(1-2**-53) -> 1+2**-52 (correct), 1.0 (double rounding) */ x = 0.99999999999999989; /* 1-2**-53 */ @@ -4910,7 +4911,7 @@ AC_MSG_CHECKING(whether right shift extends the sign bit) AC_CACHE_VAL(ac_cv_rshift_extends_sign, [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ -int main() +int main(void) { return (((-1)>>3 == -1) ? 0 : 1); } @@ -5069,7 +5070,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include -int main() +int main(void) { int val1 = nice(1); if (val1 != -1 && val1 == nice(2)) @@ -5093,7 +5094,7 @@ #include #include -int main() +int main(void) { struct pollfd poll_struct = { 42, POLLIN|POLLPRI|POLLOUT, 0 }; int poll_test; @@ -5131,7 +5132,7 @@ extern char *tzname[]; #endif -int main() +int main(void) { /* Note that we need to ensure that not only does tzset(3) do 'something' with localtime, but it works as documented @@ -5487,9 +5488,10 @@ AC_MSG_CHECKING(for broken mbstowcs) AC_CACHE_VAL(ac_cv_broken_mbstowcs, AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include #include -#include -int main() { +#include +int main(void) { size_t len = -1; const char *str = "text"; len = mbstowcs(NULL, str, 0); @@ -5600,7 +5602,7 @@ #include #include void foo(void *p, void *q) { memmove(p, q, 19); } -int main() { +int main(void) { char a[32] = "123456789000000000"; foo(&a[9], a); if (strcmp(a, "123456789123456789000000000") != 0) @@ -5641,7 +5643,7 @@ ); return r; } - int main() { + int main(void) { int p = 8; if ((foo(&p) ? : p) != 6) return 1; @@ -5669,7 +5671,7 @@ #include atomic_int int_var; atomic_uintptr_t uintptr_var; - int main() { + int main(void) { atomic_store_explicit(&int_var, 5, memory_order_relaxed); atomic_store_explicit(&uintptr_var, 0, memory_order_relaxed); int loaded_value = atomic_load_explicit(&int_var, memory_order_seq_cst); @@ -5691,7 +5693,7 @@ [ AC_LANG_SOURCE([[ int val; - int main() { + int main(void) { __atomic_store_n(&val, 1, __ATOMIC_SEQ_CST); (void)__atomic_load_n(&val, __ATOMIC_SEQ_CST); return 0; @@ -5727,7 +5729,7 @@ AC_LANG_SOURCE([[ #include - int main() { + int main(void) { struct dirent entry; return entry.d_type == DT_UNKNOWN; } @@ -5745,11 +5747,12 @@ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ + #include #include #include #include - int main() { + int main(void) { char buffer[1]; const size_t buflen = sizeof(buffer); const int flags = GRND_NONBLOCK; @@ -5772,9 +5775,10 @@ AC_LINK_IFELSE( [ AC_LANG_SOURCE([[ + #include #include - int main() { + int main(void) { char buffer[1]; const size_t buflen = sizeof(buffer); const int flags = 0; diff -Nru python3.10-3.10.7/debian/changelog python3.10-3.10.12/debian/changelog --- python3.10-3.10.7/debian/changelog 2022-09-08 14:34:29.000000000 +0000 +++ python3.10-3.10.12/debian/changelog 2023-06-09 08:30:31.000000000 +0000 @@ -1,3 +1,80 @@ +python3.10 (3.10.12-1~22.10) kinetic-proposed; urgency=medium + + * SRU: LP: #1995504: Backport the 3.10.12 release to 22.10. + * Revert: + - autopkgtests: Support python3-setuptools >= 64, which does PEP-660 + editable installs. + + -- Matthias Klose Fri, 09 Jun 2023 10:30:31 +0200 + +python3.10 (3.10.12-1) unstable; urgency=medium + + * Python 3.10.12 release. + + -- Matthias Klose Wed, 07 Jun 2023 12:09:46 +0200 + +python3.10 (3.10.11-1) unstable; urgency=medium + + * Python 3.10.11 release. + + -- Matthias Klose Wed, 12 Apr 2023 07:50:02 +0200 + +python3.10 (3.10.10-2) unstable; urgency=medium + + * Fix removing Debian build flags from _sysconfigdata. + * Fix error message for 'python3 -m venv dir`, when python3-venv + is not installed. Closes: #1026268. + + -- Matthias Klose Fri, 24 Feb 2023 12:37:34 +0100 + +python3.10 (3.10.10-1) unstable; urgency=medium + + * Python 3.10.10 release. + * Bump standards version. + + -- Matthias Klose Thu, 23 Feb 2023 08:54:04 +0100 + +python3.10 (3.10.9-1) unstable; urgency=medium + + * Python 3.10.9 release. + + -- Matthias Klose Wed, 07 Dec 2022 14:47:07 +0100 + +python3.10 (3.10.8-3) unstable; urgency=medium + + * Fix valgrind detection. + + -- Matthias Klose Fri, 04 Nov 2022 10:21:25 +0100 + +python3.10 (3.10.8-2) unstable; urgency=medium + + * Fix GDB auto-load files. Closes: #1017913. + * Add support for systemd-binfmt. Closes: #1012377. + * Address privilege escalation via multiprocessing forkserver start method: + - debian/patches/CVE-2022-42919.patch: don't use Linux abstract sockets + in Lib/multiprocessing/connection.py. + - CVE-2022-42919 + * libpython3.10-dev: Install Python.asdl and python.gram. Closes: #1022951. + * Configure the python3-dbg interpreter --with-valgrind. Closes: #1006315. + * Bump standards version. + * Update symbols files. + + -- Matthias Klose Thu, 03 Nov 2022 16:17:13 +0100 + +python3.10 (3.10.8-1) unstable; urgency=medium + + * Python 3.10.8 release. + + -- Matthias Klose Mon, 24 Oct 2022 12:07:16 +0200 + +python3.10 (3.10.7-2) unstable; urgency=medium + + [ Stefano Rivera ] + * autopkgtests: Support python3-setuptools >= 64, which does PEP-660 + editable installs. + + -- Matthias Klose Sat, 01 Oct 2022 06:31:04 +0200 + python3.10 (3.10.7-1) unstable; urgency=medium * Python 3.10.7 release. diff -Nru python3.10-3.10.7/debian/control python3.10-3.10.12/debian/control --- python3.10-3.10.7/debian/control 2022-06-01 16:31:53.000000000 +0000 +++ python3.10-3.10.12/debian/control 2023-02-23 07:55:28.000000000 +0000 @@ -16,9 +16,10 @@ libgpm2 [linux-any], media-types | mime-support, netbase, bzip2, time, python3:any, python3.10:any , net-tools, xvfb , xauth , - systemtap-sdt-dev + systemtap-sdt-dev, + valgrind-if-available, Build-Depends-Indep: python3-sphinx, python3-docs-theme, texinfo -Standards-Version: 4.6.0 +Standards-Version: 4.6.2 Vcs-Browser: https://salsa.debian.org/cpython-team/python3/tree/python3.10 Vcs-Git: https://salsa.debian.org/cpython-team/python3.git -b python3.10 XS-Testsuite: autopkgtest diff -Nru python3.10-3.10.7/debian/control.in python3.10-3.10.12/debian/control.in --- python3.10-3.10.7/debian/control.in 2022-06-01 16:31:42.000000000 +0000 +++ python3.10-3.10.12/debian/control.in 2023-02-23 07:54:57.000000000 +0000 @@ -16,9 +16,10 @@ libgpm2 [linux-any], media-types | mime-support, netbase, bzip2, time, python3@bd_qual@, @PVER@@bd_qual@ , net-tools, xvfb , xauth , - systemtap-sdt-dev + systemtap-sdt-dev, + valgrind-if-available, Build-Depends-Indep: python3-sphinx, python3-docs-theme, texinfo -Standards-Version: 4.6.0 +Standards-Version: 4.6.2 Vcs-Browser: https://salsa.debian.org/cpython-team/python3/tree/python3.10 Vcs-Git: https://salsa.debian.org/cpython-team/python3.git -b python3.10 XS-Testsuite: autopkgtest diff -Nru python3.10-3.10.7/debian/libpython.symbols.in python3.10-3.10.12/debian/libpython.symbols.in --- python3.10-3.10.7/debian/libpython.symbols.in 2021-12-07 13:27:05.000000000 +0000 +++ python3.10-3.10.12/debian/libpython.symbols.in 2022-11-03 15:25:35.000000000 +0000 @@ -1249,6 +1249,8 @@ _PyImport_FindExtensionObject@Base @SVER@ _PyImport_FixupBuiltin@Base @SVER@ _PyImport_FixupExtensionObject@Base @SVER@ + _PyImport_GetModuleAttr@Base @SVER@ + _PyImport_GetModuleAttrString@Base @SVER@ _PyImport_GetModuleId@Base @SVER@ _PyImport_IsInitialized@Base @SVER@ _PyImport_ReleaseLock@Base @SVER@ diff -Nru python3.10-3.10.7/debian/mkbinfmtconf.py python3.10-3.10.12/debian/mkbinfmtconf.py --- python3.10-3.10.7/debian/mkbinfmtconf.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/debian/mkbinfmtconf.py 2022-11-03 12:37:04.000000000 +0000 @@ -0,0 +1,9 @@ +# mkbinfmtconf.py +import importlib.util, sys, string, os.path + +magic = "".join(["\\x%.2x" % c for c in importlib.util.MAGIC_NUMBER]) + +name = sys.argv[1] + +sys.stdout.write(f":{name}:M::{magic}::/usr/bin/{name}:") +sys.stdout.write('\n') diff -Nru python3.10-3.10.7/debian/patches/CVE-2015-20107.patch python3.10-3.10.12/debian/patches/CVE-2015-20107.patch --- python3.10-3.10.7/debian/patches/CVE-2015-20107.patch 2022-06-29 12:14:09.000000000 +0000 +++ python3.10-3.10.12/debian/patches/CVE-2015-20107.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -From c3e7f139b440d7424986204e9f3fc2275aea3377 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Wed, 27 Apr 2022 18:17:33 +0200 -Subject: [PATCH 1/4] gh-68966: Make mailcap refuse to match unsafe - filenames/types/params - ---- - Doc/library/mailcap.rst | 12 ++++ - Lib/mailcap.py | 26 +++++++++- - Lib/test/test_mailcap.py | 8 ++- - Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst | 4 + - 4 files changed, 46 insertions(+), 4 deletions(-) - -Index: python3.10-3.10.4/Doc/library/mailcap.rst -=================================================================== ---- python3.10-3.10.4.orig/Doc/library/mailcap.rst -+++ python3.10-3.10.4/Doc/library/mailcap.rst -@@ -54,6 +54,18 @@ standard. However, mailcap files are su - use) to determine whether or not the mailcap line applies. :func:`findmatch` - will automatically check such conditions and skip the entry if the check fails. - -+ .. versionchanged:: 3.11 -+ -+ To prevent security issues with shell metacharacters (symbols that have -+ special effects in a shell command line), ``findmatch`` will refuse -+ to inject ASCII characters other than alphanumerics and ``@+=:,./-_`` -+ into the returned command line. -+ -+ If a disallowed character appears in *filename*, ``findmatch`` will always -+ return ``(None, None)`` as if no entry was found. -+ If such a character appears elsewhere (a value in *plist* or in *MIMEtype*), -+ ``findmatch`` will ignore all mailcap entries which use that value. -+ A :mod:`warning ` will be raised in either case. - - .. function:: getcaps() - -Index: python3.10-3.10.4/Lib/mailcap.py -=================================================================== ---- python3.10-3.10.4.orig/Lib/mailcap.py -+++ python3.10-3.10.4/Lib/mailcap.py -@@ -2,6 +2,7 @@ - - import os - import warnings -+import re - - __all__ = ["getcaps","findmatch"] - -@@ -13,6 +14,11 @@ def lineno_sort_key(entry): - else: - return 1, 0 - -+_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search -+ -+class UnsafeMailcapInput(Warning): -+ """Warning raised when refusing unsafe input""" -+ - - # Part 1: top-level interface. - -@@ -165,15 +171,22 @@ def findmatch(caps, MIMEtype, key='view' - entry to use. - - """ -+ if _find_unsafe(filename): -+ msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None, None - entries = lookup(caps, MIMEtype, key) - # XXX This code should somehow check for the needsterminal flag. - for e in entries: - if 'test' in e: - test = subst(e['test'], filename, plist) -+ if test is None: -+ continue - if test and os.system(test) != 0: - continue - command = subst(e[key], MIMEtype, filename, plist) -- return command, e -+ if command is not None: -+ return command, e - return None, None - - def lookup(caps, MIMEtype, key=None): -@@ -206,6 +219,10 @@ def subst(field, MIMEtype, filename, pli - elif c == 's': - res = res + filename - elif c == 't': -+ if _find_unsafe(MIMEtype): -+ msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None - res = res + MIMEtype - elif c == '{': - start = i -@@ -213,7 +230,12 @@ def subst(field, MIMEtype, filename, pli - i = i+1 - name = field[start:i] - i = i+1 -- res = res + findparam(name, plist) -+ param = findparam(name, plist) -+ if _find_unsafe(param): -+ msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None -+ res = res + param - # XXX To do: - # %n == number of parts if type is multipart/* - # %F == list of alternating type and filename for parts -Index: python3.10-3.10.4/Lib/test/test_mailcap.py -=================================================================== ---- python3.10-3.10.4.orig/Lib/test/test_mailcap.py -+++ python3.10-3.10.4/Lib/test/test_mailcap.py -@@ -123,7 +123,8 @@ class HelperFunctionTest(unittest.TestCa - (["", "audio/*", "foo.txt"], ""), - (["echo foo", "audio/*", "foo.txt"], "echo foo"), - (["echo %s", "audio/*", "foo.txt"], "echo foo.txt"), -- (["echo %t", "audio/*", "foo.txt"], "echo audio/*"), -+ (["echo %t", "audio/*", "foo.txt"], None), -+ (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"), - (["echo \\%t", "audio/*", "foo.txt"], "echo %t"), - (["echo foo", "audio/*", "foo.txt", plist], "echo foo"), - (["echo %{total}", "audio/*", "foo.txt", plist], "echo 3") -@@ -207,7 +208,10 @@ class FindmatchTest(unittest.TestCase): - ('"An audio fragment"', audio_basic_entry)), - ([c, "audio/*"], - {"filename": fname}, -- ("/usr/local/bin/showaudio audio/*", audio_entry)), -+ (None, None)), -+ ([c, "audio/wav"], -+ {"filename": fname}, -+ ("/usr/local/bin/showaudio audio/wav", audio_entry)), - ([c, "message/external-body"], - {"plist": plist}, - ("showexternal /dev/null default john python.org /tmp foo bar", message_entry)) -Index: python3.10-3.10.4/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst -=================================================================== ---- /dev/null -+++ python3.10-3.10.4/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst -@@ -0,0 +1,4 @@ -+The deprecated mailcap module now refuses to inject unsafe text (filenames, -+MIME types, parameters) into shell commands. Instead of using such text, it -+will warn and act as if a match was not found (or for test commands, as if -+the test failed). diff -Nru python3.10-3.10.7/debian/patches/ensurepip-disabled.diff python3.10-3.10.12/debian/patches/ensurepip-disabled.diff --- python3.10-3.10.7/debian/patches/ensurepip-disabled.diff 2022-01-16 15:55:46.000000000 +0000 +++ python3.10-3.10.12/debian/patches/ensurepip-disabled.diff 2023-02-24 11:41:40.000000000 +0000 @@ -6,7 +6,7 @@ --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py -@@ -8,6 +8,34 @@ +@@ -8,6 +8,34 @@ import tempfile from importlib import resources @@ -41,7 +41,7 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('setuptools', 'pip') -@@ -137,6 +165,11 @@ +@@ -147,6 +175,11 @@ def _bootstrap(*, root=None, upgrade=Fal Note that calling this function will alter both sys.path and os.environ. """ @@ -55,19 +55,15 @@ --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py -@@ -309,7 +309,31 @@ - # intended for the global Python environment - cmd = [context.env_exec_cmd, '-Im', 'ensurepip', '--upgrade', - '--default-pip'] -- subprocess.check_output(cmd, stderr=subprocess.STDOUT) -+ # Debian 2015-09-18 barry@debian.org: -venv is a separate -+ # binary package which might not be installed. In that case, the -+ # following command will produce an unhelpful error. Let's make it -+ # more user friendly. +@@ -325,8 +325,26 @@ class EnvBuilder: + + def _setup_pip(self, context): + """Installs or upgrades pip in a virtual environment""" +- self._call_new_python(context, '-m', 'ensurepip', '--upgrade', +- '--default-pip', stderr=subprocess.STDOUT) + try: -+ subprocess.check_output( -+ cmd, stderr=subprocess.STDOUT, -+ universal_newlines=True) ++ self._call_new_python(context, '-m', 'ensurepip', '--upgrade', ++ '--default-pip', stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + stdlib = sysconfig.get_path('stdlib') + if not os.path.exists(f'{stdlib}/ensurepip/__main__.py'): @@ -82,7 +78,7 @@ +package, recreate your virtual environment. + +Failing command: {} -+""".format(sysconfig.get_python_version(), cmd)) ++""".format(sysconfig.get_python_version(), context.env_exec_cmd)) + sys.exit(1) + raise diff -Nru python3.10-3.10.7/debian/patches/series python3.10-3.10.12/debian/patches/series --- python3.10-3.10.7/debian/patches/series 2022-07-19 11:14:53.000000000 +0000 +++ python3.10-3.10.12/debian/patches/series 2022-12-07 13:52:45.000000000 +0000 @@ -40,4 +40,3 @@ reproducible-pyc.diff fix-ia64.diff gh-78214.diff -CVE-2015-20107.patch diff -Nru python3.10-3.10.7/debian/rules python3.10-3.10.12/debian/rules --- python3.10-3.10.7/debian/rules 2022-07-18 14:00:42.000000000 +0000 +++ python3.10-3.10.12/debian/rules 2023-02-24 11:38:57.000000000 +0000 @@ -95,6 +95,10 @@ # dbmliborder = gdbm:bdb #endif +ifneq (,$(filter valgrind, $(shell dpkg-query --show -f '$${Depends}\n' valgrind-if-available))) + valgrind_configure_args = --with-valgrind +endif + VER=3.10 SVER=3.10.0 NVER=3.11 @@ -239,15 +243,14 @@ endif sysconfig_substflags = \ - -e 's,gcc-8,gcc,;s,g++-8,g++,' \ $(if $(with_lto),$(foreach i,-flto=auto -flto -fuse-linker-plugin -ffat-lto-objects,-e 's/$(i)//g')) \ -e '/^OPT/s,-O3,-O2,' \ -e 's/-O3/-O2/g' \ -e 's/-fprofile-use *-fprofile-correction//g' \ -e 's/-fstack-protector /-fstack-protector-strong /g' \ - -e 's/-specs=[^ ]*//g' \ - -e 's/-fdebug-prefix-map=[^ ]*//g' \ - -e 's/-ffile-prefix-map=[^ ]*//g' \ + -e "s/-specs=[^ ']*//g" \ + -e "s/-fdebug-prefix-map=[^ ']*//g" \ + -e "s/-ffile-prefix-map=[^ ']*//g" \ -e 's/-Wl,-z,relro//g' \ -e 's,^RUNSHARED *=.*,RUNSHARED=,' \ -e '/BLDLIBRARY/s/-L\. //' @@ -504,6 +507,7 @@ $(config_site) \ ../configure \ $(common_configure_args) \ + $(valgrind_configure_args) \ --with-pydebug $(call __post_configure,$(buildd_debug)) @@ -519,6 +523,7 @@ ../configure \ $(common_configure_args) \ --enable-shared \ + $(valgrind_configure_args) \ --with-pydebug $(call __post_configure,$(buildd_shdebug)) @@ -1067,6 +1072,10 @@ cp -p $(buildd_shared)/libpython$(VER)-pic.a \ $(d_ldev)/usr/lib/python$(VER)/config-$(VER)-$(DEB_HOST_MULTIARCH)/ + mkdir -p $(d_ldev)/usr/src/$(PVER)/{Grammar,Parser} + cp -p Grammar/python.gram $(d_ldev)/usr/src/$(PVER)/Grammar/. + cp -p Parser/Python.asdl $(d_ldev)/usr/src/$(PVER)/Parser/. + # FIXME # : # symlinks for the "old" include directory name # ln -sf python$(VER)m $(d_ldev)/usr/include/python$(VER) @@ -1236,11 +1245,15 @@ : # generate binfmt file mkdir -p $(d_min)/usr/share/binfmts + mkdir -p $(d_min)/usr/lib/binfmt.d ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) $(buildd_static)/python debian/mkbinfmt.py $(PVER) \ > $(d_min)/usr/share/binfmts/$(PVER) + $(buildd_static)/python debian/mkbinfmtconf.py $(PVER) \ + > $(d_min)/usr/lib/binfmt.d/$(PVER).conf else $(PVER) debian/mkbinfmt.py $(PVER) > $(d_min)/usr/share/binfmts/$(PVER) + $(PVER) debian/mkbinfmtconf.py $(PVER) > $(d_min)/usr/lib/binfmt.d/$(PVER).conf endif : # desktop entry @@ -1514,15 +1527,14 @@ | xargs -n 1 $(DEB_HOST_GNU_TYPE)-objcopy -p --remove-section=.gnu.lto_.* dh_strip -a -N$(p_dbg) -N$(p_ldbg) -Xdebug -Xdbg --dbg-package=$(p_dbg) mkdir -p $(d_dbg)/usr/share/gdb/auto-load/usr/bin - cp Tools/gdb/libpython.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)m-gdb.py - ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-gdb.py - ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)dm-gdb.py - ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-dbg-gdb.py + cp Tools/gdb/libpython.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-gdb.py + ln -sf $(PVER)-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)d-gdb.py + ln -sf $(PVER)-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-dbg-gdb.py mkdir -p $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH) - ln -sf ../../bin/$(PVER)m-gdb.py \ - $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER)m.so.1.0-gdb.py - ln -sf ../../bin/$(PVER)m-gdb.py \ - $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER)dm.so.1.0-gdb.py + ln -sf ../../bin/$(PVER)-gdb.py \ + $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER).so.1.0-gdb.py + ln -sf ../../bin/$(PVER)-gdb.py \ + $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER)d.so.1.0-gdb.py dh_link -a dh_compress -a -X.py dh_fixperms -a diff -Nru python3.10-3.10.7/Doc/about.rst python3.10-3.10.12/Doc/about.rst --- python3.10-3.10.7/Doc/about.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/about.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,7 +7,7 @@ document processor specifically written for the Python documentation. .. _reStructuredText: https://docutils.sourceforge.io/rst.html -.. _Sphinx: http://sphinx-doc.org/ +.. _Sphinx: https://www.sphinx-doc.org/ .. In the online version of these documents, you can submit comments and suggest changes directly on the documentation pages. diff -Nru python3.10-3.10.7/Doc/bugs.rst python3.10-3.10.12/Doc/bugs.rst --- python3.10-3.10.7/Doc/bugs.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/bugs.rst 2023-06-06 22:30:33.000000000 +0000 @@ -19,6 +19,9 @@ please submit a bug report on the :ref:`tracker `. If you have a suggestion on how to fix it, include that as well. +You can also open a discussion item on our +`Documentation Discourse forum `_. + If you're short on time, you can also email documentation bug reports to docs@python.org (behavioral bugs can be sent to python-list@python.org). 'docs@' is a mailing list run by volunteers; your request will be noticed, @@ -67,7 +70,7 @@ The submission form has two fields, "Title" and "Comment". For the "Title" field, enter a *very* short description of the problem; -less than ten words is good. +fewer than ten words is good. In the "Comment" field, describe the problem in detail, including what you expected to happen and what did happen. Be sure to include whether any diff -Nru python3.10-3.10.7/Doc/c-api/arg.rst python3.10-3.10.12/Doc/c-api/arg.rst --- python3.10-3.10.7/Doc/c-api/arg.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/arg.rst 2023-06-06 22:30:33.000000000 +0000 @@ -34,24 +34,39 @@ You don't have to provide raw storage for the returned unicode or bytes area. -In general, when a format sets a pointer to a buffer, the buffer is -managed by the corresponding Python object, and the buffer shares -the lifetime of this object. You won't have to release any memory yourself. -The only exceptions are ``es``, ``es#``, ``et`` and ``et#``. - -However, when a :c:type:`Py_buffer` structure gets filled, the underlying -buffer is locked so that the caller can subsequently use the buffer even -inside a :c:type:`Py_BEGIN_ALLOW_THREADS` block without the risk of mutable data -being resized or destroyed. As a result, **you have to call** -:c:func:`PyBuffer_Release` after you have finished processing the data (or -in any early abort case). - Unless otherwise stated, buffers are not NUL-terminated. -Some formats require a read-only :term:`bytes-like object`, and set a -pointer instead of a buffer structure. They work by checking that -the object's :c:member:`PyBufferProcs.bf_releasebuffer` field is ``NULL``, -which disallows mutable objects such as :class:`bytearray`. +There are three ways strings and buffers can be converted to C: + +* Formats such as ``y*`` and ``s*`` fill a :c:type:`Py_buffer` structure. + This locks the underlying buffer so that the caller can subsequently use + the buffer even inside a :c:type:`Py_BEGIN_ALLOW_THREADS` + block without the risk of mutable data being resized or destroyed. + As a result, **you have to call** :c:func:`PyBuffer_Release` after you have + finished processing the data (or in any early abort case). + +* The ``es``, ``es#``, ``et`` and ``et#`` formats allocate the result buffer. + **You have to call** :c:func:`PyMem_Free` after you have finished + processing the data (or in any early abort case). + +* .. _c-arg-borrowed-buffer: + + Other formats take a :class:`str` or a read-only :term:`bytes-like object`, + such as :class:`bytes`, and provide a ``const char *`` pointer to + its buffer. + In this case the buffer is "borrowed": it is managed by the corresponding + Python object, and shares the lifetime of this object. + You won't have to release any memory yourself. + + To ensure that the underlying buffer may be safely borrowed, the object's + :c:member:`PyBufferProcs.bf_releasebuffer` field must be ``NULL``. + This disallows common mutable objects such as :class:`bytearray`, + but also some read-only objects such as :class:`memoryview` of + :class:`bytes`. + + Besides this ``bf_releasebuffer`` requirement, there is no check to verify + whether the input object is immutable (e.g. whether it would honor a request + for a writable buffer, or whether another thread can mutate the data). .. note:: @@ -89,7 +104,7 @@ Unicode objects are converted to C strings using ``'utf-8'`` encoding. ``s#`` (:class:`str`, read-only :term:`bytes-like object`) [const char \*, :c:type:`Py_ssize_t`] - Like ``s*``, except that it doesn't accept mutable objects. + Like ``s*``, except that it provides a :ref:`borrowed buffer `. The result is stored into two C variables, the first one a pointer to a C string, the second one its length. The string may contain embedded null bytes. Unicode objects are converted @@ -108,8 +123,9 @@ pointer is set to ``NULL``. ``y`` (read-only :term:`bytes-like object`) [const char \*] - This format converts a bytes-like object to a C pointer to a character - string; it does not accept Unicode objects. The bytes buffer must not + This format converts a bytes-like object to a C pointer to a + :ref:`borrowed ` character string; + it does not accept Unicode objects. The bytes buffer must not contain embedded null bytes; if it does, a :exc:`ValueError` exception is raised. @@ -129,12 +145,12 @@ ``S`` (:class:`bytes`) [PyBytesObject \*] Requires that the Python object is a :class:`bytes` object, without attempting any conversion. Raises :exc:`TypeError` if the object is not - a bytes object. The C variable may also be declared as :c:type:`PyObject*`. + a bytes object. The C variable may also be declared as :c:expr:`PyObject*`. ``Y`` (:class:`bytearray`) [PyByteArrayObject \*] Requires that the Python object is a :class:`bytearray` object, without attempting any conversion. Raises :exc:`TypeError` if the object is not - a :class:`bytearray` object. The C variable may also be declared as :c:type:`PyObject*`. + a :class:`bytearray` object. The C variable may also be declared as :c:expr:`PyObject*`. ``u`` (:class:`str`) [const Py_UNICODE \*] Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of @@ -181,7 +197,7 @@ ``U`` (:class:`str`) [PyObject \*] Requires that the Python object is a Unicode object, without attempting any conversion. Raises :exc:`TypeError` if the object is not a Unicode - object. The C variable may also be declared as :c:type:`PyObject*`. + object. The C variable may also be declared as :c:expr:`PyObject*`. ``w*`` (read-write :term:`bytes-like object`) [Py_buffer] This format accepts any object which implements the read-write buffer @@ -194,10 +210,10 @@ It only works for encoded data without embedded NUL bytes. This format requires two arguments. The first is only used as input, and - must be a :c:type:`const char*` which points to the name of an encoding as a + must be a :c:expr:`const char*` which points to the name of an encoding as a NUL-terminated string, or ``NULL``, in which case ``'utf-8'`` encoding is used. An exception is raised if the named encoding is not known to Python. The - second argument must be a :c:type:`char**`; the value of the pointer it + second argument must be a :c:expr:`char**`; the value of the pointer it references will be set to a buffer with the contents of the argument text. The text will be encoded in the encoding specified by the first argument. @@ -217,10 +233,10 @@ characters. It requires three arguments. The first is only used as input, and must be a - :c:type:`const char*` which points to the name of an encoding as a + :c:expr:`const char*` which points to the name of an encoding as a NUL-terminated string, or ``NULL``, in which case ``'utf-8'`` encoding is used. An exception is raised if the named encoding is not known to Python. The - second argument must be a :c:type:`char**`; the value of the pointer it + second argument must be a :c:expr:`char**`; the value of the pointer it references will be set to a buffer with the contents of the argument text. The text will be encoded in the encoding specified by the first argument. The third argument must be a pointer to an integer; the referenced integer @@ -252,38 +268,38 @@ ``b`` (:class:`int`) [unsigned char] Convert a nonnegative Python integer to an unsigned tiny int, stored in a C - :c:type:`unsigned char`. + :c:expr:`unsigned char`. ``B`` (:class:`int`) [unsigned char] Convert a Python integer to a tiny int without overflow checking, stored in a C - :c:type:`unsigned char`. + :c:expr:`unsigned char`. ``h`` (:class:`int`) [short int] - Convert a Python integer to a C :c:type:`short int`. + Convert a Python integer to a C :c:expr:`short int`. ``H`` (:class:`int`) [unsigned short int] - Convert a Python integer to a C :c:type:`unsigned short int`, without overflow + Convert a Python integer to a C :c:expr:`unsigned short int`, without overflow checking. ``i`` (:class:`int`) [int] - Convert a Python integer to a plain C :c:type:`int`. + Convert a Python integer to a plain C :c:expr:`int`. ``I`` (:class:`int`) [unsigned int] - Convert a Python integer to a C :c:type:`unsigned int`, without overflow + Convert a Python integer to a C :c:expr:`unsigned int`, without overflow checking. ``l`` (:class:`int`) [long int] - Convert a Python integer to a C :c:type:`long int`. + Convert a Python integer to a C :c:expr:`long int`. ``k`` (:class:`int`) [unsigned long] - Convert a Python integer to a C :c:type:`unsigned long` without + Convert a Python integer to a C :c:expr:`unsigned long` without overflow checking. ``L`` (:class:`int`) [long long] - Convert a Python integer to a C :c:type:`long long`. + Convert a Python integer to a C :c:expr:`long long`. ``K`` (:class:`int`) [unsigned long long] - Convert a Python integer to a C :c:type:`unsigned long long` + Convert a Python integer to a C :c:expr:`unsigned long long` without overflow checking. ``n`` (:class:`int`) [:c:type:`Py_ssize_t`] @@ -291,20 +307,20 @@ ``c`` (:class:`bytes` or :class:`bytearray` of length 1) [char] Convert a Python byte, represented as a :class:`bytes` or - :class:`bytearray` object of length 1, to a C :c:type:`char`. + :class:`bytearray` object of length 1, to a C :c:expr:`char`. .. versionchanged:: 3.3 Allow :class:`bytearray` objects. ``C`` (:class:`str` of length 1) [int] Convert a Python character, represented as a :class:`str` object of - length 1, to a C :c:type:`int`. + length 1, to a C :c:expr:`int`. ``f`` (:class:`float`) [float] - Convert a Python floating point number to a C :c:type:`float`. + Convert a Python floating point number to a C :c:expr:`float`. ``d`` (:class:`float`) [double] - Convert a Python floating point number to a C :c:type:`double`. + Convert a Python floating point number to a C :c:expr:`double`. ``D`` (:class:`complex`) [Py_complex] Convert a Python complex number to a C :c:type:`Py_complex` structure. @@ -320,7 +336,7 @@ ``O!`` (object) [*typeobject*, PyObject \*] Store a Python object in a C object pointer. This is similar to ``O``, but takes two C arguments: the first is the address of a Python type object, the - second is the address of the C variable (of type :c:type:`PyObject*`) into which + second is the address of the C variable (of type :c:expr:`PyObject*`) into which the object pointer is stored. If the Python object does not have the required type, :exc:`TypeError` is raised. @@ -329,13 +345,13 @@ ``O&`` (object) [*converter*, *anything*] Convert a Python object to a C variable through a *converter* function. This takes two arguments: the first is a function, the second is the address of a C - variable (of arbitrary type), converted to :c:type:`void *`. The *converter* + variable (of arbitrary type), converted to :c:expr:`void *`. The *converter* function in turn is called as follows:: status = converter(object, address); where *object* is the Python object to be converted and *address* is the - :c:type:`void*` argument that was passed to the :c:func:`PyArg_Parse\*` function. + :c:expr:`void*` argument that was passed to the ``PyArg_Parse*`` function. The returned *status* should be ``1`` for a successful conversion and ``0`` if the conversion has failed. When the conversion fails, the *converter* function should raise an exception and leave the content of *address* unmodified. @@ -409,9 +425,9 @@ For the conversion to succeed, the *arg* object must match the format and the format must be exhausted. On success, the -:c:func:`PyArg_Parse\*` functions return true, otherwise they return +``PyArg_Parse*`` functions return true, otherwise they return false and raise an appropriate exception. When the -:c:func:`PyArg_Parse\*` functions fail due to conversion failure in one +``PyArg_Parse*`` functions fail due to conversion failure in one of the format units, the variables at the addresses corresponding to that and the following format units are left untouched. @@ -481,7 +497,7 @@ *args*; it must actually be a tuple. The length of the tuple must be at least *min* and no more than *max*; *min* and *max* may be equal. Additional arguments must be passed to the function, each of which should be a pointer to a - :c:type:`PyObject*` variable; these will be filled in with the values from + :c:expr:`PyObject*` variable; these will be filled in with the values from *args*; they will contain :term:`borrowed references `. The variables which correspond to optional parameters not given by *args* will not be filled in; these should @@ -518,7 +534,7 @@ .. c:function:: PyObject* Py_BuildValue(const char *format, ...) Create a new value based on a format string similar to those accepted by the - :c:func:`PyArg_Parse\*` family of functions and a sequence of values. Returns + ``PyArg_Parse*`` family of functions and a sequence of values. Returns the value or ``NULL`` in the case of an error; an exception will be raised if ``NULL`` is returned. @@ -568,7 +584,7 @@ Same as ``s#``. ``u`` (:class:`str`) [const wchar_t \*] - Convert a null-terminated :c:type:`wchar_t` buffer of Unicode (UTF-16 or UCS-4) + Convert a null-terminated :c:expr:`wchar_t` buffer of Unicode (UTF-16 or UCS-4) data to a Python Unicode object. If the Unicode buffer pointer is ``NULL``, ``None`` is returned. @@ -584,51 +600,51 @@ Same as ``s#``. ``i`` (:class:`int`) [int] - Convert a plain C :c:type:`int` to a Python integer object. + Convert a plain C :c:expr:`int` to a Python integer object. ``b`` (:class:`int`) [char] - Convert a plain C :c:type:`char` to a Python integer object. + Convert a plain C :c:expr:`char` to a Python integer object. ``h`` (:class:`int`) [short int] - Convert a plain C :c:type:`short int` to a Python integer object. + Convert a plain C :c:expr:`short int` to a Python integer object. ``l`` (:class:`int`) [long int] - Convert a C :c:type:`long int` to a Python integer object. + Convert a C :c:expr:`long int` to a Python integer object. ``B`` (:class:`int`) [unsigned char] - Convert a C :c:type:`unsigned char` to a Python integer object. + Convert a C :c:expr:`unsigned char` to a Python integer object. ``H`` (:class:`int`) [unsigned short int] - Convert a C :c:type:`unsigned short int` to a Python integer object. + Convert a C :c:expr:`unsigned short int` to a Python integer object. ``I`` (:class:`int`) [unsigned int] - Convert a C :c:type:`unsigned int` to a Python integer object. + Convert a C :c:expr:`unsigned int` to a Python integer object. ``k`` (:class:`int`) [unsigned long] - Convert a C :c:type:`unsigned long` to a Python integer object. + Convert a C :c:expr:`unsigned long` to a Python integer object. ``L`` (:class:`int`) [long long] - Convert a C :c:type:`long long` to a Python integer object. + Convert a C :c:expr:`long long` to a Python integer object. ``K`` (:class:`int`) [unsigned long long] - Convert a C :c:type:`unsigned long long` to a Python integer object. + Convert a C :c:expr:`unsigned long long` to a Python integer object. ``n`` (:class:`int`) [:c:type:`Py_ssize_t`] Convert a C :c:type:`Py_ssize_t` to a Python integer. ``c`` (:class:`bytes` of length 1) [char] - Convert a C :c:type:`int` representing a byte to a Python :class:`bytes` object of + Convert a C :c:expr:`int` representing a byte to a Python :class:`bytes` object of length 1. ``C`` (:class:`str` of length 1) [int] - Convert a C :c:type:`int` representing a character to Python :class:`str` + Convert a C :c:expr:`int` representing a character to Python :class:`str` object of length 1. ``d`` (:class:`float`) [double] - Convert a C :c:type:`double` to a Python floating point number. + Convert a C :c:expr:`double` to a Python floating point number. ``f`` (:class:`float`) [float] - Convert a C :c:type:`float` to a Python floating point number. + Convert a C :c:expr:`float` to a Python floating point number. ``D`` (:class:`complex`) [Py_complex \*] Convert a C :c:type:`Py_complex` structure to a Python complex number. @@ -651,7 +667,7 @@ ``O&`` (object) [*converter*, *anything*] Convert *anything* to a Python object through a *converter* function. The - function is called with *anything* (which should be compatible with :c:type:`void*`) + function is called with *anything* (which should be compatible with :c:expr:`void*`) as its argument and should return a "new" Python object, or ``NULL`` if an error occurred. diff -Nru python3.10-3.10.7/Doc/c-api/buffer.rst python3.10-3.10.12/Doc/c-api/buffer.rst --- python3.10-3.10.7/Doc/c-api/buffer.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/buffer.rst 2023-06-06 22:30:33.000000000 +0000 @@ -99,7 +99,7 @@ For :term:`contiguous` arrays, the value points to the beginning of the memory block. - .. c:member:: void *obj + .. c:member:: PyObject *obj A new reference to the exporting object. The reference is owned by the consumer and automatically decremented and set to ``NULL`` by diff -Nru python3.10-3.10.7/Doc/c-api/call.rst python3.10-3.10.12/Doc/c-api/call.rst --- python3.10-3.10.7/Doc/c-api/call.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/call.rst 2023-06-06 22:30:33.000000000 +0000 @@ -275,7 +275,7 @@ This is the equivalent of the Python expression: ``callable(*args)``. - Note that if you only pass :c:type:`PyObject *` args, + Note that if you only pass :c:expr:`PyObject *` args, :c:func:`PyObject_CallFunctionObjArgs` is a faster alternative. .. versionchanged:: 3.4 @@ -296,7 +296,7 @@ This is the equivalent of the Python expression: ``obj.name(arg1, arg2, ...)``. - Note that if you only pass :c:type:`PyObject *` args, + Note that if you only pass :c:expr:`PyObject *` args, :c:func:`PyObject_CallMethodObjArgs` is a faster alternative. .. versionchanged:: 3.4 @@ -306,7 +306,7 @@ .. c:function:: PyObject* PyObject_CallFunctionObjArgs(PyObject *callable, ...) Call a callable Python object *callable*, with a variable number of - :c:type:`PyObject *` arguments. The arguments are provided as a variable number + :c:expr:`PyObject *` arguments. The arguments are provided as a variable number of parameters followed by *NULL*. Return the result of the call on success, or raise an exception and return @@ -320,7 +320,7 @@ Call a method of the Python object *obj*, where the name of the method is given as a Python string object in *name*. It is called with a variable number of - :c:type:`PyObject *` arguments. The arguments are provided as a variable number + :c:expr:`PyObject *` arguments. The arguments are provided as a variable number of parameters followed by *NULL*. Return the result of the call on success, or raise an exception and return diff -Nru python3.10-3.10.7/Doc/c-api/capsule.rst python3.10-3.10.12/Doc/c-api/capsule.rst --- python3.10-3.10.7/Doc/c-api/capsule.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/capsule.rst 2023-06-06 22:30:33.000000000 +0000 @@ -15,7 +15,7 @@ .. c:type:: PyCapsule This subtype of :c:type:`PyObject` represents an opaque value, useful for C - extension modules who need to pass an opaque value (as a :c:type:`void*` + extension modules who need to pass an opaque value (as a :c:expr:`void*` pointer) through Python code to other C code. It is often used to make a C function pointer defined in one module available to other modules, so the regular import mechanism can be used to access C APIs defined in dynamically diff -Nru python3.10-3.10.7/Doc/c-api/complex.rst python3.10-3.10.12/Doc/c-api/complex.rst --- python3.10-3.10.7/Doc/c-api/complex.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/complex.rst 2023-06-06 22:30:33.000000000 +0000 @@ -115,12 +115,12 @@ .. c:function:: double PyComplex_RealAsDouble(PyObject *op) - Return the real part of *op* as a C :c:type:`double`. + Return the real part of *op* as a C :c:expr:`double`. .. c:function:: double PyComplex_ImagAsDouble(PyObject *op) - Return the imaginary part of *op* as a C :c:type:`double`. + Return the imaginary part of *op* as a C :c:expr:`double`. .. c:function:: Py_complex PyComplex_AsCComplex(PyObject *op) diff -Nru python3.10-3.10.7/Doc/c-api/conversion.rst python3.10-3.10.12/Doc/c-api/conversion.rst --- python3.10-3.10.7/Doc/c-api/conversion.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/conversion.rst 2023-06-06 22:30:33.000000000 +0000 @@ -28,7 +28,8 @@ The wrappers ensure that ``str[size-1]`` is always ``'\0'`` upon return. They never write more than *size* bytes (including the trailing ``'\0'``) into str. Both functions require that ``str != NULL``, ``size > 0``, ``format != NULL`` -and ``size < INT_MAX``. +and ``size < INT_MAX``. Note that this means there is no equivalent to the C99 +``n = snprintf(NULL, 0, ...)`` which would determine the necessary buffer size. The return value (*rv*) for these functions should be interpreted as follows: @@ -49,7 +50,7 @@ .. c:function:: double PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) - Convert a string ``s`` to a :c:type:`double`, raising a Python + Convert a string ``s`` to a :c:expr:`double`, raising a Python exception on failure. The set of accepted strings corresponds to the set of strings accepted by Python's :func:`float` constructor, except that ``s`` must not have leading or trailing whitespace. @@ -83,7 +84,7 @@ .. c:function:: char* PyOS_double_to_string(double val, char format_code, int precision, int flags, int *ptype) - Convert a :c:type:`double` *val* to a string using supplied + Convert a :c:expr:`double` *val* to a string using supplied *format_code*, *precision*, and *flags*. *format_code* must be one of ``'e'``, ``'E'``, ``'f'``, ``'F'``, diff -Nru python3.10-3.10.7/Doc/c-api/dict.rst python3.10-3.10.12/Doc/c-api/dict.rst --- python3.10-3.10.7/Doc/c-api/dict.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/dict.rst 2023-06-06 22:30:33.000000000 +0000 @@ -73,14 +73,14 @@ .. index:: single: PyUnicode_FromString() Insert *val* into the dictionary *p* using *key* as a key. *key* should - be a :c:type:`const char*`. The key object is created using + be a :c:expr:`const char*`. The key object is created using ``PyUnicode_FromString(key)``. Return ``0`` on success or ``-1`` on failure. This function *does not* steal a reference to *val*. .. c:function:: int PyDict_DelItem(PyObject *p, PyObject *key) - Remove the entry in dictionary *p* with key *key*. *key* must be hashable; + Remove the entry in dictionary *p* with key *key*. *key* must be :term:`hashable`; if it isn't, :exc:`TypeError` is raised. If *key* is not in the dictionary, :exc:`KeyError` is raised. Return ``0`` on success or ``-1`` on failure. @@ -118,7 +118,7 @@ .. c:function:: PyObject* PyDict_GetItemString(PyObject *p, const char *key) This is the same as :c:func:`PyDict_GetItem`, but *key* is specified as a - :c:type:`const char*`, rather than a :c:type:`PyObject*`. + :c:expr:`const char*`, rather than a :c:expr:`PyObject*`. Note that exceptions which occur while calling :meth:`__hash__` and :meth:`__eq__` methods and creating a temporary string object @@ -167,7 +167,7 @@ prior to the first call to this function to start the iteration; the function returns true for each pair in the dictionary, and false once all pairs have been reported. The parameters *pkey* and *pvalue* should either - point to :c:type:`PyObject*` variables that will be filled in with each key + point to :c:expr:`PyObject*` variables that will be filled in with each key and value, respectively, or may be ``NULL``. Any references returned through them are borrowed. *ppos* should not be altered during iteration. Its value represents offsets within the internal dictionary structure, and diff -Nru python3.10-3.10.7/Doc/c-api/exceptions.rst python3.10-3.10.12/Doc/c-api/exceptions.rst --- python3.10-3.10.7/Doc/c-api/exceptions.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/exceptions.rst 2023-06-06 22:30:33.000000000 +0000 @@ -14,7 +14,7 @@ C API functions don't clear this on success, but will set it to indicate the cause of the error on failure. Most C API functions also return an error indicator, usually ``NULL`` if they are supposed to return a pointer, or ``-1`` -if they return an integer (exception: the :c:func:`PyArg_\*` functions +if they return an integer (exception: the ``PyArg_*`` functions return ``1`` for success and ``0`` for failure). Concretely, the error indicator consists of three object pointers: the @@ -189,7 +189,7 @@ .. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr) This is a convenience function to raise :exc:`WindowsError`. If called with - *ierr* of :c:data:`0`, the error code returned by a call to :c:func:`GetLastError` + *ierr* of ``0``, the error code returned by a call to :c:func:`GetLastError` is used instead. It calls the Win32 function :c:func:`FormatMessage` to retrieve the Windows description of error code given by *ierr* or :c:func:`GetLastError`, then it constructs a tuple object whose first item is the *ierr* value and whose @@ -370,7 +370,7 @@ .. c:function:: PyObject* PyErr_Occurred() Test whether the error indicator is set. If set, return the exception *type* - (the first argument to the last call to one of the :c:func:`PyErr_Set\*` + (the first argument to the last call to one of the ``PyErr_Set*`` functions or to :c:func:`PyErr_Restore`). If not set, return ``NULL``. You do not own a reference to the return value, so you do not need to :c:func:`Py_DECREF` it. @@ -828,7 +828,7 @@ All standard Python exceptions are available as global variables whose names are ``PyExc_`` followed by the Python exception name. These have the type -:c:type:`PyObject*`; they are all class objects. For completeness, here are all +:c:expr:`PyObject*`; they are all class objects. For completeness, here are all the variables: .. index:: @@ -1048,7 +1048,7 @@ All standard Python warning categories are available as global variables whose names are ``PyExc_`` followed by the Python exception name. These have the type -:c:type:`PyObject*`; they are all class objects. For completeness, here are all +:c:expr:`PyObject*`; they are all class objects. For completeness, here are all the variables: .. index:: diff -Nru python3.10-3.10.7/Doc/c-api/file.rst python3.10-3.10.12/Doc/c-api/file.rst --- python3.10-3.10.7/Doc/c-api/file.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/file.rst 2023-06-06 22:30:33.000000000 +0000 @@ -8,7 +8,7 @@ .. index:: object: file These APIs are a minimal emulation of the Python 2 C API for built-in file -objects, which used to rely on the buffered I/O (:c:type:`FILE*`) support +objects, which used to rely on the buffered I/O (:c:expr:`FILE*`) support from the C standard library. In Python 3, files and streams use the new :mod:`io` module, which defines several layers over the low-level unbuffered I/O of the operating system. The functions described below are @@ -38,7 +38,7 @@ .. c:function:: int PyObject_AsFileDescriptor(PyObject *p) - Return the file descriptor associated with *p* as an :c:type:`int`. If the + Return the file descriptor associated with *p* as an :c:expr:`int`. If the object is an integer, its value is returned. If not, the object's :meth:`~io.IOBase.fileno` method is called if it exists; the method must return an integer, which is returned as the file descriptor @@ -65,7 +65,7 @@ Overrides the normal behavior of :func:`io.open_code` to pass its parameter through the provided handler. - The handler is a function of type :c:type:`PyObject *(\*)(PyObject *path, + The handler is a function of type :c:expr:`PyObject *(\*)(PyObject *path, void *userData)`, where *path* is guaranteed to be :c:type:`PyUnicodeObject`. The *userData* pointer is passed into the hook function. Since hook diff -Nru python3.10-3.10.7/Doc/c-api/float.rst python3.10-3.10.12/Doc/c-api/float.rst --- python3.10-3.10.7/Doc/c-api/float.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/float.rst 2023-06-06 22:30:33.000000000 +0000 @@ -44,7 +44,7 @@ .. c:function:: double PyFloat_AsDouble(PyObject *pyfloat) - Return a C :c:type:`double` representation of the contents of *pyfloat*. If + Return a C :c:expr:`double` representation of the contents of *pyfloat*. If *pyfloat* is not a Python floating point object but has a :meth:`__float__` method, this method will first be called to convert *pyfloat* into a float. If ``__float__()`` is not defined then it falls back to :meth:`__index__`. @@ -57,7 +57,7 @@ .. c:function:: double PyFloat_AS_DOUBLE(PyObject *pyfloat) - Return a C :c:type:`double` representation of the contents of *pyfloat*, but + Return a C :c:expr:`double` representation of the contents of *pyfloat*, but without error checking. @@ -70,9 +70,9 @@ .. c:function:: double PyFloat_GetMax() - Return the maximum representable finite float *DBL_MAX* as C :c:type:`double`. + Return the maximum representable finite float *DBL_MAX* as C :c:expr:`double`. .. c:function:: double PyFloat_GetMin() - Return the minimum normalized positive float *DBL_MIN* as C :c:type:`double`. + Return the minimum normalized positive float *DBL_MIN* as C :c:expr:`double`. diff -Nru python3.10-3.10.7/Doc/c-api/import.rst python3.10-3.10.12/Doc/c-api/import.rst --- python3.10-3.10.7/Doc/c-api/import.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/import.rst 2023-06-06 22:30:33.000000000 +0000 @@ -243,7 +243,7 @@ UTF-8 encoded string instead of a Unicode object. -.. c:type:: struct _frozen +.. c:struct:: _frozen .. index:: single: freeze utility @@ -261,7 +261,7 @@ .. c:var:: const struct _frozen* PyImport_FrozenModules - This pointer is initialized to point to an array of :c:type:`struct _frozen` + This pointer is initialized to point to an array of :c:struct:`_frozen` records, terminated by one whose members are all ``NULL`` or zero. When a frozen module is imported, it is searched in this table. Third-party code could play tricks with this to provide a dynamically created collection of frozen modules. @@ -277,7 +277,7 @@ :c:func:`Py_Initialize`. -.. c:type:: struct _inittab +.. c:struct:: _inittab Structure describing a single entry in the list of built-in modules. Each of these structures gives the name and initialization function for a module built diff -Nru python3.10-3.10.7/Doc/c-api/init_config.rst python3.10-3.10.12/Doc/c-api/init_config.rst --- python3.10-3.10.7/Doc/c-api/init_config.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/init_config.rst 2023-06-06 22:30:33.000000000 +0000 @@ -254,7 +254,7 @@ .. c:member:: int configure_locale - Set the LC_CTYPE locale to the user preferred locale? + Set the LC_CTYPE locale to the user preferred locale. If equals to 0, set :c:member:`~PyPreConfig.coerce_c_locale` and :c:member:`~PyPreConfig.coerce_c_locale_warn` members to 0. diff -Nru python3.10-3.10.7/Doc/c-api/init.rst python3.10-3.10.12/Doc/c-api/init.rst --- python3.10-3.10.7/Doc/c-api/init.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/init.rst 2023-06-06 22:30:33.000000000 +0000 @@ -365,7 +365,7 @@ interpreter will change the contents of this storage. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:type:`wchar_*` string. + :c:expr:`wchar_*` string. .. c:function:: wchar* Py_GetProgramName() @@ -391,7 +391,7 @@ program name is ``'/usr/local/bin/python'``, the prefix is ``'/usr/local'``. The returned string points into static storage; the caller should not modify its value. This corresponds to the :makevar:`prefix` variable in the top-level - :file:`Makefile` and the ``--prefix`` argument to the :program:`configure` + :file:`Makefile` and the :option:`--prefix` argument to the :program:`configure` script at build time. The value is available to Python code as ``sys.prefix``. It is only useful on Unix. See also the next function. @@ -509,7 +509,7 @@ if required after calling :c:func:`Py_Initialize`. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:type:`wchar_*` string. + :c:expr:`wchar_*` string. The path argument is copied internally, so the caller may free it after the call completes. @@ -615,7 +615,7 @@ directory (``"."``). Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:type:`wchar_*` string. + :c:expr:`wchar_*` string. .. note:: It is recommended that applications embedding the Python interpreter @@ -642,7 +642,7 @@ :option:`-I`. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:type:`wchar_*` string. + :c:expr:`wchar_*` string. .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. @@ -659,10 +659,10 @@ this storage. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:type:`wchar_*` string. + :c:expr:`wchar_*` string. -.. c:function:: w_char* Py_GetPythonHome() +.. c:function:: wchar_t* Py_GetPythonHome() Return the default "home", that is, the value set by a previous call to :c:func:`Py_SetPythonHome`, or the value of the :envvar:`PYTHONHOME` @@ -800,11 +800,11 @@ /* Release the thread. No Python API allowed beyond this point. */ PyGILState_Release(gstate); -Note that the :c:func:`PyGILState_\*` functions assume there is only one global +Note that the ``PyGILState_*`` functions assume there is only one global interpreter (created automatically by :c:func:`Py_Initialize`). Python supports the creation of additional interpreters (using :c:func:`Py_NewInterpreter`), but mixing multiple interpreters and the -:c:func:`PyGILState_\*` API is unsupported. +``PyGILState_*`` API is unsupported. .. _fork-and-threads: @@ -867,7 +867,7 @@ .. c:type:: PyThreadState This data structure represents the state of a single thread. The only public - data member is :attr:`interp` (:c:type:`PyInterpreterState *`), which points to + data member is :attr:`interp` (:c:expr:`PyInterpreterState *`), which points to this thread's interpreter state. @@ -1221,8 +1221,8 @@ exception (if any) for the thread is cleared. This raises no exceptions. .. versionchanged:: 3.7 - The type of the *id* parameter changed from :c:type:`long` to - :c:type:`unsigned long`. + The type of the *id* parameter changed from :c:expr:`long` to + :c:expr:`unsigned long`. .. c:function:: void PyEval_AcquireThread(PyThreadState *tstate) @@ -1408,7 +1408,7 @@ dictionary of loaded modules. It is equally important to avoid sharing objects from which the above are reachable. -Also note that combining this functionality with :c:func:`PyGILState_\*` APIs +Also note that combining this functionality with ``PyGILState_*`` APIs is delicate, because these APIs assume a bijection between Python thread states and OS-level threads, an assumption broken by the presence of sub-interpreters. It is highly recommended that you don't switch sub-interpreters between a pair @@ -1656,7 +1656,7 @@ (TLS) which wraps the underlying native TLS implementation to support the Python-level thread local storage API (:class:`threading.local`). The CPython C level APIs are similar to those offered by pthreads and Windows: -use a thread key and functions to associate a :c:type:`void*` value per +use a thread key and functions to associate a :c:expr:`void*` value per thread. The GIL does *not* need to be held when calling these functions; they supply @@ -1667,8 +1667,8 @@ .. note:: None of these API functions handle memory management on behalf of the - :c:type:`void*` values. You need to allocate and deallocate them yourself. - If the :c:type:`void*` values happen to be :c:type:`PyObject*`, these + :c:expr:`void*` values. You need to allocate and deallocate them yourself. + If the :c:expr:`void*` values happen to be :c:expr:`PyObject*`, these functions don't do refcount operations on them either. .. _thread-specific-storage-api: @@ -1678,7 +1678,7 @@ TSS API is introduced to supersede the use of the existing TLS API within the CPython interpreter. This API uses a new type :c:type:`Py_tss_t` instead of -:c:type:`int` to represent thread keys. +:c:expr:`int` to represent thread keys. .. versionadded:: 3.7 @@ -1722,7 +1722,7 @@ Free the given *key* allocated by :c:func:`PyThread_tss_alloc`, after first calling :c:func:`PyThread_tss_delete` to ensure any associated thread locals have been unassigned. This is a no-op if the *key* - argument is `NULL`. + argument is ``NULL``. .. note:: A freed key becomes a dangling pointer. You should reset the key to @@ -1764,14 +1764,14 @@ .. c:function:: int PyThread_tss_set(Py_tss_t *key, void *value) - Return a zero value to indicate successfully associating a :c:type:`void*` + Return a zero value to indicate successfully associating a :c:expr:`void*` value with a TSS key in the current thread. Each thread has a distinct - mapping of the key to a :c:type:`void*` value. + mapping of the key to a :c:expr:`void*` value. .. c:function:: void* PyThread_tss_get(Py_tss_t *key) - Return the :c:type:`void*` value associated with a TSS key in the current + Return the :c:expr:`void*` value associated with a TSS key in the current thread. This returns ``NULL`` if no value is associated with the key in the current thread. diff -Nru python3.10-3.10.7/Doc/c-api/intro.rst python3.10-3.10.12/Doc/c-api/intro.rst --- python3.10-3.10.7/Doc/c-api/intro.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/intro.rst 2023-06-06 22:30:33.000000000 +0000 @@ -78,19 +78,19 @@ The header files are typically installed with Python. On Unix, these are located in the directories :file:`{prefix}/include/pythonversion/` and -:file:`{exec_prefix}/include/pythonversion/`, where :envvar:`prefix` and -:envvar:`exec_prefix` are defined by the corresponding parameters to Python's +:file:`{exec_prefix}/include/pythonversion/`, where :option:`prefix <--prefix>` and +:option:`exec_prefix <--exec-prefix>` are defined by the corresponding parameters to Python's :program:`configure` script and *version* is ``'%d.%d' % sys.version_info[:2]``. On Windows, the headers are installed -in :file:`{prefix}/include`, where :envvar:`prefix` is the installation +in :file:`{prefix}/include`, where ``prefix`` is the installation directory specified to the installer. To include the headers, place both directories (if different) on your compiler's search path for includes. Do *not* place the parent directories on the search path and then use ``#include ``; this will break on multi-platform builds since the platform independent headers under -:envvar:`prefix` include the platform specific headers from -:envvar:`exec_prefix`. +:option:`prefix <--prefix>` include the platform specific headers from +:option:`exec_prefix <--exec-prefix>`. C++ users should note that although the API is defined entirely using C, the header files properly declare the entry points to be ``extern "C"``. As a result, @@ -229,13 +229,13 @@ .. index:: object: type Most Python/C API functions have one or more arguments as well as a return value -of type :c:type:`PyObject*`. This type is a pointer to an opaque data type +of type :c:expr:`PyObject*`. This type is a pointer to an opaque data type representing an arbitrary Python object. Since all Python object types are treated the same way by the Python language in most situations (e.g., assignments, scope rules, and argument passing), it is only fitting that they should be represented by a single C type. Almost all Python objects live on the heap: you never declare an automatic or static variable of type -:c:type:`PyObject`, only pointer variables of type :c:type:`PyObject*` can be +:c:type:`PyObject`, only pointer variables of type :c:expr:`PyObject*` can be declared. The sole exception are the type objects; since these must never be deallocated, they are typically static :c:type:`PyTypeObject` objects. @@ -495,8 +495,8 @@ ----- There are few other data types that play a significant role in the Python/C -API; most are simple C types such as :c:type:`int`, :c:type:`long`, -:c:type:`double` and :c:type:`char*`. A few structure types are used to +API; most are simple C types such as :c:expr:`int`, :c:expr:`long`, +:c:expr:`double` and :c:expr:`char*`. A few structure types are used to describe static tables used to list the functions exported by a module or the data attributes of a new object type, and another is used to describe the value of a complex number. These will be discussed together with the functions that diff -Nru python3.10-3.10.7/Doc/c-api/long.rst python3.10-3.10.12/Doc/c-api/long.rst --- python3.10-3.10.7/Doc/c-api/long.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/long.rst 2023-06-06 22:30:33.000000000 +0000 @@ -47,7 +47,7 @@ .. c:function:: PyObject* PyLong_FromUnsignedLong(unsigned long v) - Return a new :c:type:`PyLongObject` object from a C :c:type:`unsigned long`, or + Return a new :c:type:`PyLongObject` object from a C :c:expr:`unsigned long`, or ``NULL`` on failure. @@ -65,13 +65,13 @@ .. c:function:: PyObject* PyLong_FromLongLong(long long v) - Return a new :c:type:`PyLongObject` object from a C :c:type:`long long`, or ``NULL`` + Return a new :c:type:`PyLongObject` object from a C :c:expr:`long long`, or ``NULL`` on failure. .. c:function:: PyObject* PyLong_FromUnsignedLongLong(unsigned long long v) - Return a new :c:type:`PyLongObject` object from a C :c:type:`unsigned long long`, + Return a new :c:type:`PyLongObject` object from a C :c:expr:`unsigned long long`, or ``NULL`` on failure. @@ -93,6 +93,10 @@ underscores after a base specifier and between digits are ignored. If there are no digits, :exc:`ValueError` will be raised. + .. seealso:: Python methods :meth:`int.to_bytes` and :meth:`int.from_bytes` + to convert a :c:type:`PyLongObject` to/from an array of bytes in base + ``256``. You can call those from C using :c:func:`PyObject_CallMethod`. + .. c:function:: PyObject* PyLong_FromUnicodeObject(PyObject *u, int base) @@ -115,12 +119,12 @@ single: LONG_MAX single: OverflowError (built-in exception) - Return a C :c:type:`long` representation of *obj*. If *obj* is not an + Return a C :c:expr:`long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *obj* is out of range for a - :c:type:`long`. + :c:expr:`long`. Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. @@ -133,7 +137,7 @@ .. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) - Return a C :c:type:`long` representation of *obj*. If *obj* is not an + Return a C :c:expr:`long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. @@ -156,12 +160,12 @@ .. index:: single: OverflowError (built-in exception) - Return a C :c:type:`long long` representation of *obj*. If *obj* is not an + Return a C :c:expr:`long long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *obj* is out of range for a - :c:type:`long long`. + :c:expr:`long long`. Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. @@ -174,7 +178,7 @@ .. c:function:: long long PyLong_AsLongLongAndOverflow(PyObject *obj, int *overflow) - Return a C :c:type:`long long` representation of *obj*. If *obj* is not an + Return a C :c:expr:`long long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. @@ -215,11 +219,11 @@ single: ULONG_MAX single: OverflowError (built-in exception) - Return a C :c:type:`unsigned long` representation of *pylong*. *pylong* + Return a C :c:expr:`unsigned long` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a - :c:type:`unsigned long`. + :c:expr:`unsigned long`. Returns ``(unsigned long)-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. @@ -246,11 +250,11 @@ .. index:: single: OverflowError (built-in exception) - Return a C :c:type:`unsigned long long` representation of *pylong*. *pylong* + Return a C :c:expr:`unsigned long long` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for an - :c:type:`unsigned long long`. + :c:expr:`unsigned long long`. Returns ``(unsigned long long)-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. @@ -261,11 +265,11 @@ .. c:function:: unsigned long PyLong_AsUnsignedLongMask(PyObject *obj) - Return a C :c:type:`unsigned long` representation of *obj*. If *obj* is not + Return a C :c:expr:`unsigned long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. - If the value of *obj* is out of range for an :c:type:`unsigned long`, + If the value of *obj* is out of range for an :c:expr:`unsigned long`, return the reduction of that value modulo ``ULONG_MAX + 1``. Returns ``(unsigned long)-1`` on error. Use :c:func:`PyErr_Occurred` to @@ -280,12 +284,12 @@ .. c:function:: unsigned long long PyLong_AsUnsignedLongLongMask(PyObject *obj) - Return a C :c:type:`unsigned long long` representation of *obj*. If *obj* + Return a C :c:expr:`unsigned long long` representation of *obj*. If *obj* is not an instance of :c:type:`PyLongObject`, first call its :meth:`__index__` method (if present) to convert it to a :c:type:`PyLongObject`. - If the value of *obj* is out of range for an :c:type:`unsigned long long`, + If the value of *obj* is out of range for an :c:expr:`unsigned long long`, return the reduction of that value modulo ``ULLONG_MAX + 1``. Returns ``(unsigned long long)-1`` on error. Use :c:func:`PyErr_Occurred` @@ -300,20 +304,20 @@ .. c:function:: double PyLong_AsDouble(PyObject *pylong) - Return a C :c:type:`double` representation of *pylong*. *pylong* must be + Return a C :c:expr:`double` representation of *pylong*. *pylong* must be an instance of :c:type:`PyLongObject`. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a - :c:type:`double`. + :c:expr:`double`. Returns ``-1.0`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: void* PyLong_AsVoidPtr(PyObject *pylong) - Convert a Python integer *pylong* to a C :c:type:`void` pointer. + Convert a Python integer *pylong* to a C :c:expr:`void` pointer. If *pylong* cannot be converted, an :exc:`OverflowError` will be raised. This - is only assured to produce a usable :c:type:`void` pointer for values created + is only assured to produce a usable :c:expr:`void` pointer for values created with :c:func:`PyLong_FromVoidPtr`. Returns ``NULL`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. diff -Nru python3.10-3.10.7/Doc/c-api/marshal.rst python3.10-3.10.12/Doc/c-api/marshal.rst --- python3.10-3.10.7/Doc/c-api/marshal.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/marshal.rst 2023-06-06 22:30:33.000000000 +0000 @@ -21,16 +21,20 @@ .. c:function:: void PyMarshal_WriteLongToFile(long value, FILE *file, int version) - Marshal a :c:type:`long` integer, *value*, to *file*. This will only write + Marshal a :c:expr:`long` integer, *value*, to *file*. This will only write the least-significant 32 bits of *value*; regardless of the size of the - native :c:type:`long` type. *version* indicates the file format. + native :c:expr:`long` type. *version* indicates the file format. + This function can fail, in which case it sets the error indicator. + Use :c:func:`PyErr_Occurred` to check for that. .. c:function:: void PyMarshal_WriteObjectToFile(PyObject *value, FILE *file, int version) Marshal a Python object, *value*, to *file*. *version* indicates the file format. + This function can fail, in which case it sets the error indicator. + Use :c:func:`PyErr_Occurred` to check for that. .. c:function:: PyObject* PyMarshal_WriteObjectToString(PyObject *value, int version) @@ -43,9 +47,9 @@ .. c:function:: long PyMarshal_ReadLongFromFile(FILE *file) - Return a C :c:type:`long` from the data stream in a :c:type:`FILE*` opened + Return a C :c:expr:`long` from the data stream in a :c:expr:`FILE*` opened for reading. Only a 32-bit value can be read in using this function, - regardless of the native size of :c:type:`long`. + regardless of the native size of :c:expr:`long`. On error, sets the appropriate exception (:exc:`EOFError`) and returns ``-1``. @@ -53,9 +57,9 @@ .. c:function:: int PyMarshal_ReadShortFromFile(FILE *file) - Return a C :c:type:`short` from the data stream in a :c:type:`FILE*` opened + Return a C :c:expr:`short` from the data stream in a :c:expr:`FILE*` opened for reading. Only a 16-bit value can be read in using this function, - regardless of the native size of :c:type:`short`. + regardless of the native size of :c:expr:`short`. On error, sets the appropriate exception (:exc:`EOFError`) and returns ``-1``. @@ -63,7 +67,7 @@ .. c:function:: PyObject* PyMarshal_ReadObjectFromFile(FILE *file) - Return a Python object from the data stream in a :c:type:`FILE*` opened for + Return a Python object from the data stream in a :c:expr:`FILE*` opened for reading. On error, sets the appropriate exception (:exc:`EOFError`, :exc:`ValueError` @@ -72,7 +76,7 @@ .. c:function:: PyObject* PyMarshal_ReadLastObjectFromFile(FILE *file) - Return a Python object from the data stream in a :c:type:`FILE*` opened for + Return a Python object from the data stream in a :c:expr:`FILE*` opened for reading. Unlike :c:func:`PyMarshal_ReadObjectFromFile`, this function assumes that no further objects will be read from the file, allowing it to aggressively load file data into memory so that the de-serialization can diff -Nru python3.10-3.10.7/Doc/c-api/memory.rst python3.10-3.10.12/Doc/c-api/memory.rst --- python3.10-3.10.7/Doc/c-api/memory.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/memory.rst 2023-06-06 22:30:33.000000000 +0000 @@ -95,6 +95,8 @@ Allocator Domains ================= +.. _allocator-domains: + All allocating functions belong to one of three different "domains" (see also :c:type:`PyMemAllocatorDomain`). These domains represent different allocation strategies and are optimized for different purposes. The specific details on @@ -141,7 +143,7 @@ .. c:function:: void* PyMem_RawMalloc(size_t n) - Allocates *n* bytes and returns a pointer of type :c:type:`void*` to the + Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. Requesting zero bytes returns a distinct non-``NULL`` pointer if possible, as @@ -152,7 +154,7 @@ .. c:function:: void* PyMem_RawCalloc(size_t nelem, size_t elsize) Allocates *nelem* elements each whose size in bytes is *elsize* and returns - a pointer of type :c:type:`void*` to the allocated memory, or ``NULL`` if the + a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. Requesting zero elements or elements of size zero bytes returns a distinct @@ -212,7 +214,7 @@ .. c:function:: void* PyMem_Malloc(size_t n) - Allocates *n* bytes and returns a pointer of type :c:type:`void*` to the + Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. Requesting zero bytes returns a distinct non-``NULL`` pointer if possible, as @@ -223,7 +225,7 @@ .. c:function:: void* PyMem_Calloc(size_t nelem, size_t elsize) Allocates *nelem* elements each whose size in bytes is *elsize* and returns - a pointer of type :c:type:`void*` to the allocated memory, or ``NULL`` if the + a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. Requesting zero elements or elements of size zero bytes returns a distinct @@ -265,14 +267,14 @@ .. c:function:: TYPE* PyMem_New(TYPE, size_t n) Same as :c:func:`PyMem_Malloc`, but allocates ``(n * sizeof(TYPE))`` bytes of - memory. Returns a pointer cast to :c:type:`TYPE*`. The memory will not have + memory. Returns a pointer cast to :c:expr:`TYPE*`. The memory will not have been initialized in any way. .. c:function:: TYPE* PyMem_Resize(void *p, TYPE, size_t n) Same as :c:func:`PyMem_Realloc`, but the memory block is resized to ``(n * - sizeof(TYPE))`` bytes. Returns a pointer cast to :c:type:`TYPE*`. On return, + sizeof(TYPE))`` bytes. Returns a pointer cast to :c:expr:`TYPE*`. On return, *p* will be a pointer to the new memory area, or ``NULL`` in the event of failure. @@ -320,7 +322,7 @@ .. c:function:: void* PyObject_Malloc(size_t n) - Allocates *n* bytes and returns a pointer of type :c:type:`void*` to the + Allocates *n* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. Requesting zero bytes returns a distinct non-``NULL`` pointer if possible, as @@ -331,7 +333,7 @@ .. c:function:: void* PyObject_Calloc(size_t nelem, size_t elsize) Allocates *nelem* elements each whose size in bytes is *elsize* and returns - a pointer of type :c:type:`void*` to the allocated memory, or ``NULL`` if the + a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. Requesting zero elements or elements of size zero bytes returns a distinct @@ -477,6 +479,25 @@ debug hooks on top on the new allocator. + .. warning:: + + :c:func:`PyMem_SetAllocator` does have the following contract: + + * It can be called after :c:func:`Py_PreInitialize` and before + :c:func:`Py_InitializeFromConfig` to install a custom memory + allocator. There are no restrictions over the installed allocator + other than the ones imposed by the domain (for instance, the Raw + Domain allows the allocator to be called without the GIL held). See + :ref:`the section on allocator domains ` for more + information. + + * If called after Python has finish initializing (after + :c:func:`Py_InitializeFromConfig` has been called) the allocator + **must** wrap the existing allocator. Substituting the current + allocator for some other arbitrary one is **not supported**. + + + .. c:function:: void PyMem_SetupDebugHooks(void) Setup :ref:`debug hooks in the Python memory allocators ` diff -Nru python3.10-3.10.7/Doc/c-api/memoryview.rst python3.10-3.10.12/Doc/c-api/memoryview.rst --- python3.10-3.10.7/Doc/c-api/memoryview.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/memoryview.rst 2023-06-06 22:30:33.000000000 +0000 @@ -55,7 +55,7 @@ *mview* **must** be a memoryview instance; this macro doesn't check its type, you must do it yourself or you will risk crashes. -.. c:function:: Py_buffer *PyMemoryView_GET_BASE(PyObject *mview) +.. c:function:: PyObject *PyMemoryView_GET_BASE(PyObject *mview) Return either a pointer to the exporting object that the memoryview is based on or ``NULL`` if the memoryview has been created by one of the functions diff -Nru python3.10-3.10.7/Doc/c-api/module.rst python3.10-3.10.12/Doc/c-api/module.rst --- python3.10-3.10.7/Doc/c-api/module.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/module.rst 2023-06-06 22:30:33.000000000 +0000 @@ -64,8 +64,8 @@ If *module* is not a module object (or a subtype of a module object), :exc:`SystemError` is raised and ``NULL`` is returned. - It is recommended extensions use other :c:func:`PyModule_\*` and - :c:func:`PyObject_\*` functions rather than directly manipulate a module's + It is recommended extensions use other ``PyModule_*`` and + ``PyObject_*`` functions rather than directly manipulate a module's :attr:`~object.__dict__`. @@ -388,7 +388,7 @@ .. c:function:: PyObject * PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec) - Create a new module object, given the definition in *module* and the + Create a new module object, given the definition in *def* and the ModuleSpec *spec*. This behaves like :c:func:`PyModule_FromDefAndSpec2` with *module_api_version* set to :const:`PYTHON_API_VERSION`. @@ -396,7 +396,7 @@ .. c:function:: PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version) - Create a new module object, given the definition in *module* and the + Create a new module object, given the definition in *def* and the ModuleSpec *spec*, assuming the API version *module_api_version*. If that version does not match the version of the running interpreter, a :exc:`RuntimeWarning` is emitted. diff -Nru python3.10-3.10.7/Doc/c-api/object.rst python3.10-3.10.12/Doc/c-api/object.rst --- python3.10-3.10.7/Doc/c-api/object.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/object.rst 2023-06-06 22:30:33.000000000 +0000 @@ -161,6 +161,15 @@ If *o1* and *o2* are the same object, :c:func:`PyObject_RichCompareBool` will always return ``1`` for :const:`Py_EQ` and ``0`` for :const:`Py_NE`. +.. c:function:: PyObject* PyObject_Format(PyObject *obj, PyObject *format_spec) + + Format *obj* using *format_spec*. This is equivalent to the Python + expression ``format(obj, format_spec)``. + + *format_spec* may be ``NULL``. In this case the call is equivalent + to ``format(obj)``. + Returns the formatted string on success, ``NULL`` on failure. + .. c:function:: PyObject* PyObject_Repr(PyObject *o) .. index:: builtin: repr @@ -263,7 +272,7 @@ .. c:function:: Py_hash_t PyObject_HashNotImplemented(PyObject *o) - Set a :exc:`TypeError` indicating that ``type(o)`` is not hashable and return ``-1``. + Set a :exc:`TypeError` indicating that ``type(o)`` is not :term:`hashable` and return ``-1``. This function receives special treatment when stored in a ``tp_hash`` slot, allowing a type to explicitly indicate to the interpreter that it is not hashable. @@ -292,7 +301,7 @@ is equivalent to the Python expression ``type(o)``. This function increments the reference count of the return value. There's really no reason to use this function instead of the :c:func:`Py_TYPE()` function, which returns a - pointer of type :c:type:`PyTypeObject*`, except when the incremented reference + pointer of type :c:expr:`PyTypeObject*`, except when the incremented reference count is needed. diff -Nru python3.10-3.10.7/Doc/c-api/structures.rst python3.10-3.10.12/Doc/c-api/structures.rst --- python3.10-3.10.7/Doc/c-api/structures.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/structures.rst 2023-06-06 22:30:33.000000000 +0000 @@ -27,7 +27,7 @@ object. In a normal "release" build, it contains only the object's reference count and a pointer to the corresponding type object. Nothing is actually declared to be a :c:type:`PyObject`, but every pointer - to a Python object can be cast to a :c:type:`PyObject*`. Access to the + to a Python object can be cast to a :c:expr:`PyObject*`. Access to the members must be done by using the macros :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. @@ -99,7 +99,7 @@ Return a :term:`borrowed reference`. - The :c:func:`Py_SET_TYPE` function must be used to set an object type. + Use the :c:func:`Py_SET_TYPE` function to set an object type. .. c:function:: int Py_IS_TYPE(PyObject *o, PyTypeObject *type) @@ -137,7 +137,7 @@ Get the size of the Python object *o*. - The :c:func:`Py_SET_SIZE` function must be used to set an object size. + Use the :c:func:`Py_SET_SIZE` function to set an object size. .. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size) @@ -172,7 +172,7 @@ .. c:type:: PyCFunction Type of the functions used to implement most Python callables in C. - Functions of this type take two :c:type:`PyObject*` parameters and return + Functions of this type take two :c:expr:`PyObject*` parameters and return one such value. If the return value is ``NULL``, an exception shall have been set. If not ``NULL``, the return value is interpreted as the return value of the function as exposed in Python. The function must return a new @@ -235,29 +235,30 @@ Structure used to describe a method of an extension type. This structure has four fields: - +------------------+---------------+-------------------------------+ - | Field | C Type | Meaning | - +==================+===============+===============================+ - | :attr:`ml_name` | const char \* | name of the method | - +------------------+---------------+-------------------------------+ - | :attr:`ml_meth` | PyCFunction | pointer to the C | - | | | implementation | - +------------------+---------------+-------------------------------+ - | :attr:`ml_flags` | int | flag bits indicating how the | - | | | call should be constructed | - +------------------+---------------+-------------------------------+ - | :attr:`ml_doc` | const char \* | points to the contents of the | - | | | docstring | - +------------------+---------------+-------------------------------+ + .. c:member:: const char* ml_name + + name of the method + + .. c:member:: PyCFunction ml_meth + + pointer to the C implementation + + .. c:member:: int ml_flags + + flags bits indicating how the call should be constructed + + .. c:member:: const char* ml_doc + + points to the contents of the docstring -The :attr:`ml_meth` is a C function pointer. The functions may be of different -types, but they always return :c:type:`PyObject*`. If the function is not of +The :c:member:`ml_meth` is a C function pointer. The functions may be of different +types, but they always return :c:expr:`PyObject*`. If the function is not of the :c:type:`PyCFunction`, the compiler will require a cast in the method table. Even though :c:type:`PyCFunction` defines the first parameter as -:c:type:`PyObject*`, it is common that the method implementation uses the +:c:expr:`PyObject*`, it is common that the method implementation uses the specific C type of the *self* object. -The :attr:`ml_flags` field is a bitfield which can include the following flags. +The :c:member:`ml_flags` field is a bitfield which can include the following flags. The individual flags indicate either a calling convention or a binding convention. @@ -266,7 +267,7 @@ .. data:: METH_VARARGS This is the typical calling convention, where the methods have the type - :c:type:`PyCFunction`. The function expects two :c:type:`PyObject*` values. + :c:type:`PyCFunction`. The function expects two :c:expr:`PyObject*` values. The first one is the *self* object for methods; for module functions, it is the module object. The second parameter (often called *args*) is a tuple object representing all arguments. This parameter is typically processed @@ -287,7 +288,7 @@ Fast calling convention supporting only positional arguments. The methods have the type :c:type:`_PyCFunctionFast`. The first parameter is *self*, the second parameter is a C array - of :c:type:`PyObject*` values indicating the arguments and the third + of :c:expr:`PyObject*` values indicating the arguments and the third parameter is the number of arguments (the length of the array). .. versionadded:: 3.7 @@ -303,7 +304,7 @@ with methods of type :c:type:`_PyCFunctionFastWithKeywords`. Keyword arguments are passed the same way as in the :ref:`vectorcall protocol `: - there is an additional fourth :c:type:`PyObject*` parameter + there is an additional fourth :c:expr:`PyObject*` parameter which is a tuple representing the names of the keyword arguments (which are guaranteed to be strings) or possibly ``NULL`` if there are no keywords. The values of the keyword @@ -339,7 +340,7 @@ Methods with a single object argument can be listed with the :const:`METH_O` flag, instead of invoking :c:func:`PyArg_ParseTuple` with a ``"O"`` argument. They have the type :c:type:`PyCFunction`, with the *self* parameter, and a - :c:type:`PyObject*` parameter representing the single argument. + :c:expr:`PyObject*` parameter representing the single argument. These two constants are not used to indicate the calling convention but the @@ -505,7 +506,7 @@ | | | getter and setter | +-------------+------------------+-----------------------------------+ - The ``get`` function takes one :c:type:`PyObject*` parameter (the + The ``get`` function takes one :c:expr:`PyObject*` parameter (the instance) and a function pointer (the associated ``closure``):: typedef PyObject *(*getter)(PyObject *, void *); @@ -513,7 +514,7 @@ It should return a new reference on success or ``NULL`` with a set exception on failure. - ``set`` functions take two :c:type:`PyObject*` parameters (the instance and + ``set`` functions take two :c:expr:`PyObject*` parameters (the instance and the value to be set) and a function pointer (the associated ``closure``):: typedef int (*setter)(PyObject *, PyObject *, void *); diff -Nru python3.10-3.10.7/Doc/c-api/sys.rst python3.10-3.10.12/Doc/c-api/sys.rst --- python3.10-3.10.7/Doc/c-api/sys.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/sys.rst 2023-06-06 22:30:33.000000000 +0000 @@ -105,7 +105,7 @@ Return the current signal handler for signal *i*. This is a thin wrapper around either :c:func:`sigaction` or :c:func:`signal`. Do not call those functions - directly! :c:type:`PyOS_sighandler_t` is a typedef alias for :c:type:`void + directly! :c:type:`PyOS_sighandler_t` is a typedef alias for :c:expr:`void (\*)(int)`. @@ -114,7 +114,7 @@ Set the signal handler for signal *i* to be *h*; return the old signal handler. This is a thin wrapper around either :c:func:`sigaction` or :c:func:`signal`. Do not call those functions directly! :c:type:`PyOS_sighandler_t` is a typedef - alias for :c:type:`void (\*)(int)`. + alias for :c:expr:`void (\*)(int)`. .. c:function:: wchar_t* Py_DecodeLocale(const char* arg, size_t *size) @@ -352,7 +352,7 @@ silently abort the operation by raising an error subclassed from :class:`Exception` (other errors will not be silenced). - The hook function is of type :c:type:`int (*)(const char *event, PyObject + The hook function is of type :c:expr:`int (*)(const char *event, PyObject *args, void *userData)`, where *args* is guaranteed to be a :c:type:`PyTupleObject`. The hook function is always called with the GIL held by the Python interpreter that raised the event. diff -Nru python3.10-3.10.7/Doc/c-api/tuple.rst python3.10-3.10.12/Doc/c-api/tuple.rst --- python3.10-3.10.7/Doc/c-api/tuple.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/tuple.rst 2023-06-06 22:30:33.000000000 +0000 @@ -161,7 +161,7 @@ .. c:type:: PyStructSequence_Field Describes a field of a struct sequence. As a struct sequence is modeled as a - tuple, all fields are typed as :c:type:`PyObject*`. The index in the + tuple, all fields are typed as :c:expr:`PyObject*`. The index in the :attr:`fields` array of the :c:type:`PyStructSequence_Desc` determines which field of the struct sequence is described. diff -Nru python3.10-3.10.7/Doc/c-api/typehints.rst python3.10-3.10.12/Doc/c-api/typehints.rst --- python3.10-3.10.7/Doc/c-api/typehints.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/typehints.rst 2023-06-06 22:30:33.000000000 +0000 @@ -15,8 +15,8 @@ Equivalent to calling the Python class :class:`types.GenericAlias`. The *origin* and *args* arguments set the ``GenericAlias``\ 's ``__origin__`` and ``__args__`` attributes respectively. - *origin* should be a :c:type:`PyTypeObject*`, and *args* can be a - :c:type:`PyTupleObject*` or any ``PyObject*``. If *args* passed is + *origin* should be a :c:expr:`PyTypeObject*`, and *args* can be a + :c:expr:`PyTupleObject*` or any ``PyObject*``. If *args* passed is not a tuple, a 1-tuple is automatically constructed and ``__args__`` is set to ``(args,)``. Minimal checking is done for the arguments, so the function will succeed even diff -Nru python3.10-3.10.7/Doc/c-api/typeobj.rst python3.10-3.10.12/Doc/c-api/typeobj.rst --- python3.10-3.10.7/Doc/c-api/typeobj.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/typeobj.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,8 +7,8 @@ Perhaps one of the most important structures of the Python object system is the structure that defines a new type: the :c:type:`PyTypeObject` structure. Type -objects can be handled using any of the :c:func:`PyObject_\*` or -:c:func:`PyType_\*` functions, but do not offer much that's interesting to most +objects can be handled using any of the ``PyObject_*`` or +``PyType_*`` functions, but do not offer much that's interesting to most Python applications. These objects are fundamental to how objects behave, so they are very important to the interpreter itself and to any extension module that implements new types. @@ -149,10 +149,16 @@ +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+ .. [#slots] - A slot name in parentheses indicates it is (effectively) deprecated. - Names in angle brackets should be treated as read-only. - Names in square brackets are for internal use only. - "" (as a prefix) means the field is required (must be non-``NULL``). + + **()**: A slot name in parentheses indicates it is (effectively) deprecated. + + **<>**: Names in angle brackets should be initially set to ``NULL`` and + treated as read-only. + + **[]**: Names in square brackets are for internal use only. + + **** (as a prefix) means the field is required (must be non-``NULL``). + .. [#cols] Columns: **"O"**: set on :c:type:`PyBaseObject_Type` @@ -444,6 +450,7 @@ | | | | | | :c:type:`PyObject` * | | | | :c:type:`Py_ssize_t` | | +| | :c:type:`PyObject` * | | +-----------------------------+-----------------------------+----------------------+ | :c:type:`objobjproc` | .. line-block:: | int | | | | | @@ -1212,6 +1219,17 @@ **Inheritance:** This flag is not inherited. + However, subclasses will not be instantiable unless they provide a + non-NULL :c:member:`~PyTypeObject.tp_new` (which is only possible + via the C API). + + .. note:: + + To disallow instantiating a class directly but allow instantiating + its subclasses (e.g. for an :term:`abstract base class`), + do not use this flag. + Instead, make :c:member:`~PyTypeObject.tp_new` only succeed for + subclasses. .. versionadded:: 3.10 @@ -1483,8 +1501,8 @@ If the instances of this type are weakly referenceable, this field is greater than zero and contains the offset in the instance structure of the weak reference list head (ignoring the GC header, if present); this offset is used by - :c:func:`PyObject_ClearWeakRefs` and the :c:func:`PyWeakref_\*` functions. The - instance structure needs to include a field of type :c:type:`PyObject*` which is + :c:func:`PyObject_ClearWeakRefs` and the ``PyWeakref_*`` functions. The + instance structure needs to include a field of type :c:expr:`PyObject*` which is initialized to ``NULL``. Do not confuse this field with :c:member:`~PyTypeObject.tp_weaklist`; that is the list head for @@ -1898,8 +1916,19 @@ Tuple of base types. - This is set for types created by a class statement. It should be ``NULL`` for - statically defined types. + This field should be set to ``NULL`` and treated as read-only. + Python will fill it in when the type is :c:func:`initialized `. + + For dynamically created classes, the ``Py_tp_bases`` + :c:type:`slot ` can be used instead of the *bases* argument + of :c:func:`PyType_FromSpecWithBases`. + The argument form is preferred. + + .. warning:: + + Multiple inheritance does not work well for statically defined types. + If you set ``tp_bases`` to a tuple, Python will not raise an error, + but some slots will only be inherited from the first base. **Inheritance:** @@ -1911,6 +1940,8 @@ Tuple containing the expanded set of base types, starting with the type itself and ending with :class:`object`, in Method Resolution Order. + This field should be set to ``NULL`` and treated as read-only. + Python will fill it in when the type is :c:func:`initialized `. **Inheritance:** @@ -2327,13 +2358,13 @@ steps: (1) Check if the request can be met. If not, raise :c:data:`PyExc_BufferError`, - set :c:data:`view->obj` to ``NULL`` and return ``-1``. + set :c:expr:`view->obj` to ``NULL`` and return ``-1``. (2) Fill in the requested fields. (3) Increment an internal counter for the number of exports. - (4) Set :c:data:`view->obj` to *exporter* and increment :c:data:`view->obj`. + (4) Set :c:expr:`view->obj` to *exporter* and increment :c:expr:`view->obj`. (5) Return ``0``. @@ -2341,10 +2372,10 @@ schemes can be used: * Re-export: Each member of the tree acts as the exporting object and - sets :c:data:`view->obj` to a new reference to itself. + sets :c:expr:`view->obj` to a new reference to itself. * Redirect: The buffer request is redirected to the root object of the - tree. Here, :c:data:`view->obj` will be a new reference to the root + tree. Here, :c:expr:`view->obj` will be a new reference to the root object. The individual fields of *view* are described in section @@ -2386,7 +2417,7 @@ *view* argument. - This function MUST NOT decrement :c:data:`view->obj`, since that is + This function MUST NOT decrement :c:expr:`view->obj`, since that is done automatically in :c:func:`PyBuffer_Release` (this scheme is useful for breaking reference cycles). @@ -2565,7 +2596,7 @@ .. c:type:: PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t) -.. c:type:: int (*ssizeobjargproc)(PyObject *, Py_ssize_t) +.. c:type:: int (*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *) .. c:type:: int (*objobjproc)(PyObject *, PyObject *) diff -Nru python3.10-3.10.7/Doc/c-api/type.rst python3.10-3.10.12/Doc/c-api/type.rst --- python3.10-3.10.7/Doc/c-api/type.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/type.rst 2023-06-06 22:30:33.000000000 +0000 @@ -40,7 +40,7 @@ .. c:function:: unsigned long PyType_GetFlags(PyTypeObject* type) Return the :c:member:`~PyTypeObject.tp_flags` member of *type*. This function is primarily - meant for use with `Py_LIMITED_API`; the individual flag bits are + meant for use with ``Py_LIMITED_API``; the individual flag bits are guaranteed to be stable across Python releases, but access to :c:member:`~PyTypeObject.tp_flags` itself is not part of the limited API. diff -Nru python3.10-3.10.7/Doc/c-api/unicode.rst python3.10-3.10.12/Doc/c-api/unicode.rst --- python3.10-3.10.7/Doc/c-api/unicode.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/unicode.rst 2023-06-06 22:30:33.000000000 +0000 @@ -17,8 +17,8 @@ for strings where all code points are below 128, 256, or 65536; otherwise, code points must be below 1114112 (which is the full Unicode range). -:c:type:`Py_UNICODE*` and UTF-8 representations are created on demand and cached -in the Unicode object. The :c:type:`Py_UNICODE*` representation is deprecated +:c:expr:`Py_UNICODE*` and UTF-8 representations are created on demand and cached +in the Unicode object. The :c:expr:`Py_UNICODE*` representation is deprecated and inefficient. Due to the transition between the old APIs and the new APIs, Unicode objects @@ -30,7 +30,7 @@ * "legacy" Unicode objects have been created through one of the deprecated APIs (typically :c:func:`PyUnicode_FromUnicode`) and only bear the - :c:type:`Py_UNICODE*` representation; you will have to call + :c:expr:`Py_UNICODE*` representation; you will have to call :c:func:`PyUnicode_READY` on them before calling any other API. .. note:: @@ -58,7 +58,7 @@ .. c:type:: Py_UNICODE - This is a typedef of :c:type:`wchar_t`, which is a 16-bit type or 32-bit type + This is a typedef of :c:expr:`wchar_t`, which is a 16-bit type or 32-bit type depending on the platform. .. versionchanged:: 3.3 @@ -235,7 +235,7 @@ returned buffer is always terminated with an extra null code point. It may also contain embedded null code points, which would cause the string to be truncated when used in most C functions. The ``AS_DATA`` form - casts the pointer to :c:type:`const char *`. The *o* argument has to be + casts the pointer to :c:expr:`const char *`. The *o* argument has to be a Unicode object (not checked). .. versionchanged:: 3.3 @@ -707,7 +707,7 @@ Return a read-only pointer to the Unicode object's internal :c:type:`Py_UNICODE` buffer, or ``NULL`` on error. This will create the - :c:type:`Py_UNICODE*` representation of the object if it is not yet + :c:expr:`Py_UNICODE*` representation of the object if it is not yet available. The buffer is always terminated with an extra null code point. Note that the resulting :c:type:`Py_UNICODE` string may also contain embedded null code points, which would cause the string to be truncated when @@ -734,7 +734,7 @@ Like :c:func:`PyUnicode_AsUnicode`, but also saves the :c:func:`Py_UNICODE` array length (excluding the extra null terminator) in *size*. - Note that the resulting :c:type:`Py_UNICODE*` string + Note that the resulting :c:expr:`Py_UNICODE*` string may contain embedded null code points, which would cause the string to be truncated when used in most C functions. @@ -853,7 +853,7 @@ ParseTuple converter: encode :class:`str` objects -- obtained directly or through the :class:`os.PathLike` interface -- to :class:`bytes` using :c:func:`PyUnicode_EncodeFSDefault`; :class:`bytes` objects are output as-is. - *result* must be a :c:type:`PyBytesObject*` which must be released when it is + *result* must be a :c:expr:`PyBytesObject*` which must be released when it is no longer used. .. versionadded:: 3.1 @@ -870,7 +870,7 @@ ParseTuple converter: decode :class:`bytes` objects -- obtained either directly or indirectly through the :class:`os.PathLike` interface -- to :class:`str` using :c:func:`PyUnicode_DecodeFSDefaultAndSize`; :class:`str` - objects are output as-is. *result* must be a :c:type:`PyUnicodeObject*` which + objects are output as-is. *result* must be a :c:expr:`PyUnicodeObject*` which must be released when it is no longer used. .. versionadded:: 3.2 @@ -939,11 +939,11 @@ wchar_t Support """"""""""""""" -:c:type:`wchar_t` support for platforms which support it: +:c:expr:`wchar_t` support for platforms which support it: .. c:function:: PyObject* PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size) - Create a Unicode object from the :c:type:`wchar_t` buffer *w* of the given *size*. + Create a Unicode object from the :c:expr:`wchar_t` buffer *w* of the given *size*. Passing ``-1`` as the *size* indicates that the function must itself compute the length, using wcslen. Return ``NULL`` on failure. @@ -951,13 +951,13 @@ .. c:function:: Py_ssize_t PyUnicode_AsWideChar(PyObject *unicode, wchar_t *w, Py_ssize_t size) - Copy the Unicode object contents into the :c:type:`wchar_t` buffer *w*. At most - *size* :c:type:`wchar_t` characters are copied (excluding a possibly trailing - null termination character). Return the number of :c:type:`wchar_t` characters - copied or ``-1`` in case of an error. Note that the resulting :c:type:`wchar_t*` + Copy the Unicode object contents into the :c:expr:`wchar_t` buffer *w*. At most + *size* :c:expr:`wchar_t` characters are copied (excluding a possibly trailing + null termination character). Return the number of :c:expr:`wchar_t` characters + copied or ``-1`` in case of an error. Note that the resulting :c:expr:`wchar_t*` string may or may not be null-terminated. It is the responsibility of the caller - to make sure that the :c:type:`wchar_t*` string is null-terminated in case this is - required by the application. Also, note that the :c:type:`wchar_t*` string + to make sure that the :c:expr:`wchar_t*` string is null-terminated in case this is + required by the application. Also, note that the :c:expr:`wchar_t*` string might contain null characters, which would cause the string to be truncated when used with most C functions. @@ -967,9 +967,9 @@ Convert the Unicode object to a wide character string. The output string always ends with a null character. If *size* is not ``NULL``, write the number of wide characters (excluding the trailing null termination character) into - *\*size*. Note that the resulting :c:type:`wchar_t` string might contain + *\*size*. Note that the resulting :c:expr:`wchar_t` string might contain null characters, which would cause the string to be truncated when used with - most C functions. If *size* is ``NULL`` and the :c:type:`wchar_t*` string + most C functions. If *size* is ``NULL`` and the :c:expr:`wchar_t*` string contains null characters a :exc:`ValueError` is raised. Returns a buffer allocated by :c:func:`PyMem_Alloc` (use @@ -980,7 +980,7 @@ .. versionadded:: 3.2 .. versionchanged:: 3.7 - Raises a :exc:`ValueError` if *size* is ``NULL`` and the :c:type:`wchar_t*` + Raises a :exc:`ValueError` if *size* is ``NULL`` and the :c:expr:`wchar_t*` string contains null characters. diff -Nru python3.10-3.10.7/Doc/c-api/veryhigh.rst python3.10-3.10.12/Doc/c-api/veryhigh.rst --- python3.10-3.10.7/Doc/c-api/veryhigh.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/veryhigh.rst 2023-06-06 22:30:33.000000000 +0000 @@ -16,11 +16,11 @@ :const:`Py_file_input`, and :const:`Py_single_input`. These are described following the functions which accept them as parameters. -Note also that several of these functions take :c:type:`FILE*` parameters. One -particular issue which needs to be handled carefully is that the :c:type:`FILE` +Note also that several of these functions take :c:expr:`FILE*` parameters. One +particular issue which needs to be handled carefully is that the :c:expr:`FILE` structure for different C libraries can be different and incompatible. Under Windows (at least), it is possible for dynamically linked extensions to actually -use different libraries, so care should be taken that :c:type:`FILE*` parameters +use different libraries, so care should be taken that :c:expr:`FILE*` parameters are only passed to these functions if it is certain that they were created by the same library that the Python runtime is using. @@ -82,7 +82,7 @@ .. c:function:: int PyRun_SimpleString(const char *command) This is a simplified interface to :c:func:`PyRun_SimpleStringFlags` below, - leaving the :c:type:`PyCompilerFlags`\* argument set to ``NULL``. + leaving the :c:struct:`PyCompilerFlags`\* argument set to ``NULL``. .. c:function:: int PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) @@ -344,7 +344,7 @@ interpreter loop. -.. c:type:: struct PyCompilerFlags +.. c:struct:: PyCompilerFlags This is the structure used to hold compiler flags. In cases where code is only being compiled, it is passed as ``int flags``, and in cases where code is being diff -Nru python3.10-3.10.7/Doc/c-api/weakref.rst python3.10-3.10.12/Doc/c-api/weakref.rst --- python3.10-3.10.7/Doc/c-api/weakref.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/c-api/weakref.rst 2023-06-06 22:30:33.000000000 +0000 @@ -68,3 +68,13 @@ Similar to :c:func:`PyWeakref_GetObject`, but implemented as a macro that does no error checking. + + +.. c:function:: void PyObject_ClearWeakRefs(PyObject *object) + + This function is called by the :c:member:`~PyTypeObject.tp_dealloc` handler + to clear weak references. + + This iterates through the weak references for *object* and calls callbacks + for those references which have one. It returns when all callbacks have + been attempted. diff -Nru python3.10-3.10.7/Doc/conf.py python3.10-3.10.12/Doc/conf.py --- python3.10-3.10.7/Doc/conf.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/conf.py 2023-06-06 22:30:33.000000000 +0000 @@ -234,13 +234,3 @@ # Relative filename of the data files refcount_file = 'data/refcounts.dat' stable_abi_file = 'data/stable_abi.dat' - -# Sphinx 2 and Sphinx 3 compatibility -# ----------------------------------- - -# bpo-40204: Allow Sphinx 2 syntax in the C domain -c_allow_pre_v3 = True - -# bpo-40204: Disable warnings on Sphinx 2 syntax of the C domain since the -# documentation is built with -W (warnings treated as errors). -c_warn_on_allowed_pre_v3 = False diff -Nru python3.10-3.10.7/Doc/copyright.rst python3.10-3.10.12/Doc/copyright.rst --- python3.10-3.10.7/Doc/copyright.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/copyright.rst 2023-06-06 22:30:33.000000000 +0000 @@ -4,7 +4,7 @@ Python and this documentation is: -Copyright © 2001-2022 Python Software Foundation. All rights reserved. +Copyright © 2001-2023 Python Software Foundation. All rights reserved. Copyright © 2000 BeOpen.com. All rights reserved. diff -Nru python3.10-3.10.7/Doc/data/refcounts.dat python3.10-3.10.12/Doc/data/refcounts.dat --- python3.10-3.10.7/Doc/data/refcounts.dat 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/data/refcounts.dat 2023-06-06 22:30:33.000000000 +0000 @@ -1010,10 +1010,10 @@ PyImport_Import:PyObject*:name:0: PyImport_ImportFrozenModule:int::: -PyImport_ImportFrozenModule:const char*::: +PyImport_ImportFrozenModule:const char*:name:: PyImport_ImportFrozenModuleObject:int::: -PyImport_ImportFrozenModuleObject:PyObject*::+1: +PyImport_ImportFrozenModuleObject:PyObject*:name:+1: PyImport_ImportModule:PyObject*::+1: PyImport_ImportModule:const char*:name:: diff -Nru python3.10-3.10.7/Doc/extending/embedding.rst python3.10-3.10.12/Doc/extending/embedding.rst --- python3.10-3.10.7/Doc/extending/embedding.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/extending/embedding.rst 2023-06-06 22:30:33.000000000 +0000 @@ -298,16 +298,16 @@ .. code-block:: shell-session - $ /opt/bin/python3.4-config --cflags - -I/opt/include/python3.4m -I/opt/include/python3.4m -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes + $ /opt/bin/python3.11-config --cflags + -I/opt/include/python3.11 -I/opt/include/python3.11 -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -* ``pythonX.Y-config --ldflags`` will give you the recommended flags when - linking: +* ``pythonX.Y-config --ldflags --embed`` will give you the recommended flags + when linking: .. code-block:: shell-session - $ /opt/bin/python3.4-config --ldflags - -L/opt/lib/python3.4/config-3.4m -lpthread -ldl -lutil -lm -lpython3.4m -Xlinker -export-dynamic + $ /opt/bin/python3.11-config --ldflags --embed + -L/opt/lib/python3.11/config-3.11-x86_64-linux-gnu -L/opt/lib -lpython3.11 -lpthread -ldl -lutil -lm .. note:: To avoid confusion between several Python installations (and especially diff -Nru python3.10-3.10.7/Doc/extending/extending.rst python3.10-3.10.12/Doc/extending/extending.rst --- python3.10-3.10.7/Doc/extending/extending.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/extending/extending.rst 2023-06-06 22:30:33.000000000 +0000 @@ -157,16 +157,16 @@ When a function *f* that calls another function *g* detects that the latter fails, *f* should itself return an error value (usually ``NULL`` or ``-1``). It -should *not* call one of the :c:func:`PyErr_\*` functions --- one has already +should *not* call one of the ``PyErr_*`` functions --- one has already been called by *g*. *f*'s caller is then supposed to also return an error -indication to *its* caller, again *without* calling :c:func:`PyErr_\*`, and so on +indication to *its* caller, again *without* calling ``PyErr_*``, and so on --- the most detailed cause of the error was already reported by the function that first detected it. Once the error reaches the Python interpreter's main loop, this aborts the currently executing Python code and tries to find an exception handler specified by the Python programmer. (There are situations where a module can actually give a more detailed error -message by calling another :c:func:`PyErr_\*` function, and in such cases it is +message by calling another ``PyErr_*`` function, and in such cases it is fine to do so. As a general rule, however, this is not necessary, and can cause information about the cause of the error to be lost: most operations can fail for a variety of reasons.) @@ -298,7 +298,7 @@ on the heap in Python!) If you have a C function that returns no useful argument (a function returning -:c:type:`void`), the corresponding Python function must return ``None``. You +:c:expr:`void`), the corresponding Python function must return ``None``. You need this idiom to do so (which is implemented by the :c:macro:`Py_RETURN_NONE` macro):: @@ -1171,7 +1171,7 @@ Python provides a special mechanism to pass C-level information (pointers) from one extension module to another one: Capsules. A Capsule is a Python data type -which stores a pointer (:c:type:`void \*`). Capsules can only be created and +which stores a pointer (:c:expr:`void \*`). Capsules can only be created and accessed via their C API, but they can be passed around like any other Python object. In particular, they can be assigned to a name in an extension module's namespace. Other extension modules can then import this module, retrieve the @@ -1185,7 +1185,7 @@ Whichever method you choose, it's important to name your Capsules properly. The function :c:func:`PyCapsule_New` takes a name parameter -(:c:type:`const char \*`); you're permitted to pass in a ``NULL`` name, but +(:c:expr:`const char \*`); you're permitted to pass in a ``NULL`` name, but we strongly encourage you to specify a name. Properly named Capsules provide a degree of runtime type-safety; there is no feasible way to tell one unnamed Capsule from another. @@ -1203,7 +1203,7 @@ The following example demonstrates an approach that puts most of the burden on the writer of the exporting module, which is appropriate for commonly used library modules. It stores all C API pointers (just one in the example!) in an -array of :c:type:`void` pointers which becomes the value of a Capsule. The header +array of :c:expr:`void` pointers which becomes the value of a Capsule. The header file corresponding to the module provides a macro that takes care of importing the module and retrieving its C API pointers; client modules only have to call this macro before accessing the C API. diff -Nru python3.10-3.10.7/Doc/extending/newtypes.rst python3.10-3.10.12/Doc/extending/newtypes.rst --- python3.10-3.10.7/Doc/extending/newtypes.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/extending/newtypes.rst 2023-06-06 22:30:33.000000000 +0000 @@ -207,8 +207,8 @@ Python supports two pairs of attribute handlers; a type that supports attributes only needs to implement the functions for one pair. The difference is that one -pair takes the name of the attribute as a :c:type:`char\*`, while the other -accepts a :c:type:`PyObject\*`. Each type can use whichever pair makes more +pair takes the name of the attribute as a :c:expr:`char\*`, while the other +accepts a :c:expr:`PyObject*`. Each type can use whichever pair makes more sense for the implementation's convenience. :: getattrfunc tp_getattr; /* char * version */ @@ -219,7 +219,7 @@ If accessing attributes of an object is always a simple operation (this will be explained shortly), there are generic implementations which can be used to -provide the :c:type:`PyObject\*` version of the attribute management functions. +provide the :c:expr:`PyObject*` version of the attribute management functions. The actual need for type-specific attribute handlers almost completely disappeared starting with Python 2.2, though there are many examples which have not been updated to use some of the new generic mechanism that is available. @@ -339,9 +339,9 @@ Type-specific Attribute Management ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For simplicity, only the :c:type:`char\*` version will be demonstrated here; the -type of the name parameter is the only difference between the :c:type:`char\*` -and :c:type:`PyObject\*` flavors of the interface. This example effectively does +For simplicity, only the :c:expr:`char\*` version will be demonstrated here; the +type of the name parameter is the only difference between the :c:expr:`char\*` +and :c:expr:`PyObject*` flavors of the interface. This example effectively does the same thing as the generic example above, but does not use the generic support added in Python 2.2. It explains how the handler functions are called, so that if you do need to extend their functionality, you'll understand @@ -572,7 +572,7 @@ For an object to be weakly referencable, the extension type must do two things: -#. Include a :c:type:`PyObject\*` field in the C object structure dedicated to +#. Include a :c:expr:`PyObject*` field in the C object structure dedicated to the weak reference mechanism. The object's constructor should leave it ``NULL`` (which is automatic when using the default :c:member:`~PyTypeObject.tp_alloc`). diff -Nru python3.10-3.10.7/Doc/extending/newtypes_tutorial.rst python3.10-3.10.12/Doc/extending/newtypes_tutorial.rst --- python3.10-3.10.7/Doc/extending/newtypes_tutorial.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/extending/newtypes_tutorial.rst 2023-06-06 22:30:33.000000000 +0000 @@ -24,7 +24,7 @@ ========== The :term:`CPython` runtime sees all Python objects as variables of type -:c:type:`PyObject\*`, which serves as a "base type" for all Python objects. +:c:expr:`PyObject*`, which serves as a "base type" for all Python objects. The :c:type:`PyObject` structure itself only contains the object's :term:`reference count` and a pointer to the object's "type object". This is where the action is; the type object determines which (C) functions diff -Nru python3.10-3.10.7/Doc/faq/design.rst python3.10-3.10.12/Doc/faq/design.rst --- python3.10-3.10.7/Doc/faq/design.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/design.rst 2023-06-06 22:30:33.000000000 +0000 @@ -155,7 +155,7 @@ Starting in Python 3.8, you can! -Assignment expressions using the walrus operator `:=` assign a variable in an +Assignment expressions using the walrus operator ``:=`` assign a variable in an expression:: while chunk := fp.read(200): diff -Nru python3.10-3.10.7/Doc/faq/extending.rst python3.10-3.10.12/Doc/faq/extending.rst --- python3.10-3.10.7/Doc/faq/extending.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/extending.rst 2023-06-06 22:30:33.000000000 +0000 @@ -51,7 +51,7 @@ currently exists, you can try wrapping the library's data types and functions with a tool such as `SWIG `_. `SIP `__, `CXX -`_ `Boost +`_ `Boost `_, or `Weave `_ are also alternatives for wrapping C++ libraries. diff -Nru python3.10-3.10.7/Doc/faq/general.rst python3.10-3.10.12/Doc/faq/general.rst --- python3.10-3.10.7/Doc/faq/general.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/general.rst 2023-06-06 22:30:33.000000000 +0000 @@ -125,11 +125,15 @@ How does the Python version numbering scheme work? -------------------------------------------------- -Python versions are numbered A.B.C or A.B. A is the major version number -- it -is only incremented for really major changes in the language. B is the minor -version number, incremented for less earth-shattering changes. C is the -micro-level -- it is incremented for each bugfix release. See :pep:`6` for more -information about bugfix releases. +Python versions are numbered "A.B.C" or "A.B": + +* *A* is the major version number -- it is only incremented for really major + changes in the language. +* *B* is the minor version number -- it is incremented for less earth-shattering + changes. +* *C* is the micro version number -- it is incremented for each bugfix release. + +See :pep:`6` for more information about bugfix releases. Not all releases are bugfix releases. In the run-up to a new major release, a series of development releases are made, denoted as alpha, beta, or release @@ -139,12 +143,14 @@ modules, and release candidates are frozen, making no changes except as needed to fix critical bugs. -Alpha, beta and release candidate versions have an additional suffix. The -suffix for an alpha version is "aN" for some small number N, the suffix for a -beta version is "bN" for some small number N, and the suffix for a release -candidate version is "rcN" for some small number N. In other words, all versions -labeled 2.0aN precede the versions labeled 2.0bN, which precede versions labeled -2.0rcN, and *those* precede 2.0. +Alpha, beta and release candidate versions have an additional suffix: + +* The suffix for an alpha version is "aN" for some small number *N*. +* The suffix for a beta version is "bN" for some small number *N*. +* The suffix for a release candidate version is "rcN" for some small number *N*. + +In other words, all versions labeled *2.0aN* precede the versions labeled +*2.0bN*, which precede versions labeled *2.0rcN*, and *those* precede 2.0. You may also find version numbers with a "+" suffix, e.g. "2.2+". These are unreleased versions, built directly from the CPython development repository. In @@ -182,7 +188,7 @@ also available at https://docs.python.org/3/download.html. The documentation is written in reStructuredText and processed by `the Sphinx -documentation tool `__. The reStructuredText source for +documentation tool `__. The reStructuredText source for the documentation is part of the Python source distribution. @@ -248,8 +254,8 @@ It's probably best to cite your favorite book about Python. -The very first article about Python was written in 1991 and is now quite -outdated. +The `very first article `_ about Python was +written in 1991 and is now quite outdated. Guido van Rossum and Jelke de Boer, "Interactively Testing Remote Servers Using the Python Programming Language", CWI Quarterly, Volume 4, Issue 4 @@ -270,7 +276,7 @@ --------------------------------------------- The Python project's infrastructure is located all over the world and is managed -by the Python Infrastructure Team. Details `here `__. +by the Python Infrastructure Team. Details `here `__. Why is it called Python? @@ -335,7 +341,7 @@ different companies and organizations. High-profile Python projects include `the Mailman mailing list manager -`_ and `the Zope application server +`_ and `the Zope application server `_. Several Linux distributions, most notably `Red Hat `_, have written part or all of their installer and system administration software in Python. Companies that use Python internally @@ -435,7 +441,7 @@ programming. There are also good IDEs for Python. IDLE is a cross-platform IDE for Python -that is written in Python using Tkinter. PythonWin is a Windows-specific IDE. +that is written in Python using Tkinter. Emacs users will be happy to know that there is a very good Python mode for Emacs. All of these programming environments provide syntax highlighting, auto-indenting, and access to the interactive interpreter while coding. Consult diff -Nru python3.10-3.10.7/Doc/faq/gui.rst python3.10-3.10.12/Doc/faq/gui.rst --- python3.10-3.10.7/Doc/faq/gui.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/gui.rst 2023-06-06 22:30:33.000000000 +0000 @@ -49,7 +49,7 @@ To get truly stand-alone applications, the Tcl scripts that form the library have to be integrated into the application as well. One tool supporting that is SAM (stand-alone modules), which is part of the Tix distribution -(http://tix.sourceforge.net/). +(https://tix.sourceforge.net/). Build Tix with SAM enabled, perform the appropriate call to :c:func:`Tclsam_init`, etc. inside Python's diff -Nru python3.10-3.10.7/Doc/faq/library.rst python3.10-3.10.12/Doc/faq/library.rst --- python3.10-3.10.7/Doc/faq/library.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/library.rst 2023-06-06 22:30:33.000000000 +0000 @@ -180,8 +180,8 @@ The :mod:`pydoc` module can create HTML from the doc strings in your Python source code. An alternative for creating API documentation purely from -docstrings is `epydoc `_. `Sphinx -`_ can also include docstring content. +docstrings is `epydoc `_. `Sphinx +`_ can also include docstring content. How do I get a single keypress at a time? @@ -609,7 +609,7 @@ substituted for standard input and output. You will have to use pseudo ttys ("ptys") instead of pipes. Or you can use a Python interface to Don Libes' "expect" library. A Python extension that interfaces to expect is called - "expy" and available from http://expectpy.sourceforge.net. A pure Python + "expy" and available from https://expectpy.sourceforge.net. A pure Python solution that works like expect is `pexpect `_. diff -Nru python3.10-3.10.7/Doc/faq/programming.rst python3.10-3.10.12/Doc/faq/programming.rst --- python3.10-3.10.7/Doc/faq/programming.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/programming.rst 2023-06-06 22:30:33.000000000 +0000 @@ -25,8 +25,9 @@ for pdb as an example. The IDLE interactive development environment, which is part of the standard -Python distribution (normally available as Tools/scripts/idle), includes a -graphical debugger. +Python distribution (normally available as +`Tools/scripts/idle3 `_), +includes a graphical debugger. PythonWin is a Python IDE that includes a GUI debugger based on pdb. The PythonWin debugger colors breakpoints and has quite a few cool features such as @@ -35,7 +36,7 @@ as a part of the `ActivePython `_ distribution. -`Eric `_ is an IDE built on PyQt +`Eric `_ is an IDE built on PyQt and the Scintilla editing component. `trepan3k `_ is a gdb-like debugger. @@ -78,7 +79,8 @@ Python binary to produce a single executable. One is to use the freeze tool, which is included in the Python source tree as -``Tools/freeze``. It converts Python byte code to C arrays; with a C compiler you can +`Tools/freeze `_. +It converts Python byte code to C arrays; with a C compiler you can embed all your modules into a new program, which is then linked with the standard Python modules. @@ -99,7 +101,7 @@ * `PyOxidizer `_ (Cross-platform) * `cx_Freeze `_ (Cross-platform) * `py2app `_ (macOS only) -* `py2exe `_ (Windows only) +* `py2exe `_ (Windows only) Are there coding standards or a style guide for Python programs? ---------------------------------------------------------------- @@ -111,10 +113,12 @@ Core Language ============= +.. _faq-unboundlocalerror: + Why am I getting an UnboundLocalError when the variable has a value? -------------------------------------------------------------------- -It can be a surprise to get the UnboundLocalError in previously working +It can be a surprise to get the :exc:`UnboundLocalError` in previously working code when it is modified by adding an assignment statement somewhere in the body of a function. @@ -123,6 +127,7 @@ >>> x = 10 >>> def bar(): ... print(x) + ... >>> bar() 10 @@ -133,7 +138,7 @@ ... print(x) ... x += 1 -results in an UnboundLocalError: +results in an :exc:`!UnboundLocalError`: >>> foo() Traceback (most recent call last): @@ -155,6 +160,7 @@ ... global x ... print(x) ... x += 1 + ... >>> foobar() 10 @@ -176,6 +182,7 @@ ... x += 1 ... bar() ... print(x) + ... >>> foo() 10 11 @@ -273,7 +280,7 @@ import mod print(config.x) -Note that using a module is also the basis for implementing the Singleton design +Note that using a module is also the basis for implementing the singleton design pattern, for the same reason. @@ -291,9 +298,9 @@ It's good practice if you import modules in the following order: -1. standard library modules -- e.g. ``sys``, ``os``, ``getopt``, ``re`` +1. standard library modules -- e.g. :mod:`sys`, :mod:`os`, :mod:`argparse`, :mod:`re` 2. third-party library modules (anything installed in Python's site-packages - directory) -- e.g. mx.DateTime, ZODB, PIL.Image, etc. + directory) -- e.g. :mod:`!dateutil`, :mod:`!requests`, :mod:`!PIL.Image` 3. locally developed modules It is sometimes necessary to move imports to a function or class to avoid @@ -471,7 +478,7 @@ Some operations (for example ``y.append(10)`` and ``y.sort()``) mutate the object, whereas superficially similar operations (for example ``y = y + [10]`` -and ``sorted(y)``) create a new object. In general in Python (and in all cases +and :func:`sorted(y) `) create a new object. In general in Python (and in all cases in the standard library) a method that mutates an object will return ``None`` to help avoid getting the two types of operations confused. So if you mistakenly write ``y.sort()`` thinking it will give you a sorted copy of ``y``, @@ -644,7 +651,7 @@ How can I find the methods or attributes of an object? ------------------------------------------------------ -For an instance x of a user-defined class, ``dir(x)`` returns an alphabetized +For an instance ``x`` of a user-defined class, :func:`dir(x) ` returns an alphabetized list of the names containing the instance attributes and methods and attributes defined by its class. @@ -669,9 +676,9 @@ <__main__.A object at 0x16D07CC> Arguably the class has a name: even though it is bound to two names and invoked -through the name B the created instance is still reported as an instance of -class A. However, it is impossible to say whether the instance's name is a or -b, since both names are bound to the same value. +through the name ``B`` the created instance is still reported as an instance of +class ``A``. However, it is impossible to say whether the instance's name is ``a`` or +``b``, since both names are bound to the same value. Generally speaking it should not be necessary for your code to "know the names" of particular values. Unless you are deliberately writing introspective @@ -735,7 +742,7 @@ -------------------------------------------------------- Yes. Usually this is done by nesting :keyword:`lambda` within -:keyword:`!lambda`. See the following three examples, due to Ulf Bartelt:: +:keyword:`!lambda`. See the following three examples, slightly adapted from Ulf Bartelt:: from functools import reduce @@ -748,7 +755,7 @@ f(x,f), range(10)))) # Mandelbrot set - print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y, + print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+'\n'+y,map(lambda y, Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM, Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro, i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k<=0)or (x*x+y*y @@ -841,7 +848,7 @@ ---------------------------------------------------------- Trying to lookup an ``int`` literal attribute in the normal manner gives -a syntax error because the period is seen as a decimal point:: +a :exc:`SyntaxError` because the period is seen as a decimal point:: >>> 1.__class__ File "", line 1 @@ -887,7 +894,7 @@ How do I convert a number to a string? -------------------------------------- -To convert, e.g., the number 144 to the string '144', use the built-in type +To convert, e.g., the number ``144`` to the string ``'144'``, use the built-in type constructor :func:`str`. If you want a hexadecimal or octal representation, use the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see the :ref:`f-strings` and :ref:`formatstrings` sections, @@ -1006,11 +1013,11 @@ For simple input parsing, the easiest approach is usually to split the line into whitespace-delimited words using the :meth:`~str.split` method of string objects and then convert decimal strings to numeric values using :func:`int` or -:func:`float`. ``split()`` supports an optional "sep" parameter which is useful +:func:`float`. :meth:`!split()` supports an optional "sep" parameter which is useful if the line uses something other than whitespace as a separator. For more complicated input parsing, regular expressions are more powerful -than C's :c:func:`sscanf` and better suited for the task. +than C's ``sscanf`` and better suited for the task. What does 'UnicodeDecodeError' or 'UnicodeEncodeError' error mean? @@ -1019,6 +1026,46 @@ See the :ref:`unicode-howto`. +.. _faq-programming-raw-string-backslash: + +Can I end a raw string with an odd number of backslashes? +--------------------------------------------------------- + +A raw string ending with an odd number of backslashes will escape the string's quote:: + + >>> r'C:\this\will\not\work\' + File "", line 1 + r'C:\this\will\not\work\' + ^ + SyntaxError: unterminated string literal (detected at line 1) + +There are several workarounds for this. One is to use regular strings and double +the backslashes:: + + >>> 'C:\\this\\will\\work\\' + 'C:\\this\\will\\work\\' + +Another is to concatenate a regular string containing an escaped backslash to the +raw string:: + + >>> r'C:\this\will\work' '\\' + 'C:\\this\\will\\work\\' + +It is also possible to use :func:`os.path.join` to append a backslash on Windows:: + + >>> os.path.join(r'C:\this\will\work', '') + 'C:\\this\\will\\work\\' + +Note that while a backslash will "escape" a quote for the purposes of +determining where the raw string ends, no escaping occurs when interpreting the +value of the raw string. That is, the backslash remains present in the value of +the raw string:: + + >>> r'backslash\'preserved' + "backslash\\'preserved" + +Also see the specification in the :ref:`language reference `. + Performance =========== @@ -1206,15 +1253,16 @@ The ``array`` module also provides methods for creating arrays of fixed types with compact representations, but they are slower to index than lists. Also -note that NumPy and other third party packages define array-like structures with +note that `NumPy `_ +and other third party packages define array-like structures with various characteristics as well. -To get Lisp-style linked lists, you can emulate cons cells using tuples:: +To get Lisp-style linked lists, you can emulate *cons cells* using tuples:: lisp_list = ("like", ("this", ("example", None) ) ) If mutability is desired, you could use lists instead of tuples. Here the -analogue of lisp car is ``lisp_list[0]`` and the analogue of cdr is +analogue of a Lisp *car* is ``lisp_list[0]`` and the analogue of *cdr* is ``lisp_list[1]``. Only do this if you're sure you really need to, because it's usually a lot slower than using Python lists. @@ -1270,7 +1318,7 @@ A = [[None] * w for i in range(h)] Or, you can use an extension that provides a matrix datatype; `NumPy -`_ is the best known. +`_ is the best known. How do I apply a method to a sequence of objects? @@ -1334,11 +1382,12 @@ ['foo', 'item'] To see why this happens, you need to know that (a) if an object implements an -``__iadd__`` magic method, it gets called when the ``+=`` augmented assignment +:meth:`~object.__iadd__` magic method, it gets called when the ``+=`` augmented +assignment is executed, and its return value is what gets used in the assignment statement; -and (b) for lists, ``__iadd__`` is equivalent to calling ``extend`` on the list +and (b) for lists, :meth:`!__iadd__` is equivalent to calling :meth:`~list.extend` on the list and returning the list. That's why we say that for lists, ``+=`` is a -"shorthand" for ``list.extend``:: +"shorthand" for :meth:`!list.extend`:: >>> a_list = [] >>> a_list += [1] @@ -1363,7 +1412,7 @@ ... TypeError: 'tuple' object does not support item assignment -The ``__iadd__`` succeeds, and thus the list is extended, but even though +The :meth:`!__iadd__` succeeds, and thus the list is extended, but even though ``result`` points to the same object that ``a_tuple[0]`` already points to, that final assignment still results in an error, because tuples are immutable. @@ -1440,7 +1489,8 @@ How do I check if an object is an instance of a given class or of a subclass of it? ----------------------------------------------------------------------------------- -Use the built-in function ``isinstance(obj, cls)``. You can check if an object +Use the built-in function :func:`isinstance(obj, cls) `. You can +check if an object is an instance of any of a number of classes by providing a tuple instead of a single class, e.g. ``isinstance(obj, (class1, class2, ...))``, and can also check whether an object is one of Python's built-in types, e.g. @@ -1537,13 +1587,13 @@ argument string to uppercase before calling the underlying ``self._outfile.write()`` method. All other methods are delegated to the underlying ``self._outfile`` object. The delegation is accomplished via the -``__getattr__`` method; consult :ref:`the language reference ` +:meth:`~object.__getattr__` method; consult :ref:`the language reference ` for more information about controlling attribute access. Note that for more general cases delegation can get trickier. When attributes -must be set as well as retrieved, the class must define a :meth:`__setattr__` +must be set as well as retrieved, the class must define a :meth:`~object.__setattr__` method too, and it must do so carefully. The basic implementation of -:meth:`__setattr__` is roughly equivalent to the following:: +:meth:`!__setattr__` is roughly equivalent to the following:: class X: ... @@ -1551,7 +1601,8 @@ self.__dict__[name] = value ... -Most :meth:`__setattr__` implementations must modify ``self.__dict__`` to store +Most :meth:`!__setattr__` implementations must modify +:meth:`self.__dict__ ` to store local state for self without causing an infinite recursion. @@ -1689,17 +1740,17 @@ There are several possible reasons for this. -The del statement does not necessarily call :meth:`__del__` -- it simply +The :keyword:`del` statement does not necessarily call :meth:`~object.__del__` -- it simply decrements the object's reference count, and if this reaches zero -:meth:`__del__` is called. +:meth:`!__del__` is called. If your data structures contain circular links (e.g. a tree where each child has a parent reference and each parent has a list of children) the reference counts will never go back to zero. Once in a while Python runs an algorithm to detect such cycles, but the garbage collector might run some time after the last -reference to your data structure vanishes, so your :meth:`__del__` method may be +reference to your data structure vanishes, so your :meth:`!__del__` method may be called at an inconvenient and random time. This is inconvenient if you're trying -to reproduce a problem. Worse, the order in which object's :meth:`__del__` +to reproduce a problem. Worse, the order in which object's :meth:`!__del__` methods are executed is arbitrary. You can run :func:`gc.collect` to force a collection, but there *are* pathological cases where objects will never be collected. @@ -1707,7 +1758,7 @@ Despite the cycle collector, it's still a good idea to define an explicit ``close()`` method on objects to be called whenever you're done with them. The ``close()`` method can then remove attributes that refer to subobjects. Don't -call :meth:`__del__` directly -- :meth:`__del__` should call ``close()`` and +call :meth:`!__del__` directly -- :meth:`!__del__` should call ``close()`` and ``close()`` should make sure that it can be called more than once for the same object. @@ -1724,7 +1775,7 @@ Normally, calling :func:`sys.exc_clear` will take care of this by clearing the last recorded exception. -Finally, if your :meth:`__del__` method raises an exception, a warning message +Finally, if your :meth:`!__del__` method raises an exception, a warning message is printed to :data:`sys.stderr`. @@ -1852,8 +1903,8 @@ How can a subclass control what data is stored in an immutable instance? ------------------------------------------------------------------------ -When subclassing an immutable type, override the :meth:`__new__` method -instead of the :meth:`__init__` method. The latter only runs *after* an +When subclassing an immutable type, override the :meth:`~object.__new__` method +instead of the :meth:`~object.__init__` method. The latter only runs *after* an instance is created, which is too late to alter data in an immutable instance. @@ -1914,7 +1965,7 @@ instances accumulate, so too will the accumulated method results. They can grow without bound. -The *lru_cache* approach works with methods that have hashable +The *lru_cache* approach works with methods that have :term:`hashable` arguments. It creates a reference to the instance unless special efforts are made to pass in weak references. diff -Nru python3.10-3.10.7/Doc/faq/windows.rst python3.10-3.10.12/Doc/faq/windows.rst --- python3.10-3.10.7/Doc/faq/windows.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/faq/windows.rst 2023-06-06 22:30:33.000000000 +0000 @@ -167,7 +167,7 @@ Embedding the Python interpreter in a Windows app can be summarized as follows: -1. Do _not_ build Python into your .exe file directly. On Windows, Python must +1. Do **not** build Python into your .exe file directly. On Windows, Python must be a DLL to handle importing modules that are themselves DLL's. (This is the first key undocumented fact.) Instead, link to :file:`python{NN}.dll`; it is typically installed in ``C:\Windows\System``. *NN* is the Python version, a @@ -191,7 +191,7 @@ 2. If you use SWIG, it is easy to create a Python "extension module" that will make the app's data and methods available to Python. SWIG will handle just about all the grungy details for you. The result is C code that you link - *into* your .exe file (!) You do _not_ have to create a DLL file, and this + *into* your .exe file (!) You do **not** have to create a DLL file, and this also simplifies linking. 3. SWIG will create an init function (a C function) whose name depends on the @@ -218,10 +218,10 @@ 5. There are two problems with Python's C API which will become apparent if you use a compiler other than MSVC, the compiler used to build pythonNN.dll. - Problem 1: The so-called "Very High Level" functions that take FILE * + Problem 1: The so-called "Very High Level" functions that take ``FILE *`` arguments will not work in a multi-compiler environment because each - compiler's notion of a struct FILE will be different. From an implementation - standpoint these are very _low_ level functions. + compiler's notion of a ``struct FILE`` will be different. From an implementation + standpoint these are very low level functions. Problem 2: SWIG generates the following code when generating wrappers to void functions: @@ -276,3 +276,11 @@ Use the :mod:`msvcrt` module. This is a standard Windows-specific extension module. It defines a function ``kbhit()`` which checks whether a keyboard hit is present, and ``getch()`` which gets one character without echoing it. + +How do I solve the missing api-ms-win-crt-runtime-l1-1-0.dll error? +------------------------------------------------------------------- + +This can occur on Python 3.5 and later when using Windows 8.1 or earlier without all updates having been installed. +First ensure your operating system is supported and is up to date, and if that does not resolve the issue, +visit the `Microsoft support page `_ +for guidance on manually installing the C Runtime update. diff -Nru python3.10-3.10.7/Doc/glossary.rst python3.10-3.10.12/Doc/glossary.rst --- python3.10-3.10.7/Doc/glossary.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/glossary.rst 2023-06-06 22:30:33.000000000 +0000 @@ -136,10 +136,17 @@ :exc:`StopAsyncIteration` exception. Introduced by :pep:`492`. attribute - A value associated with an object which is referenced by name using - dotted expressions. For example, if an object *o* has an attribute + A value associated with an object which is usually referenced by name + using dotted expressions. + For example, if an object *o* has an attribute *a* it would be referenced as *o.a*. + It is possible to give an object an attribute whose name is not an + identifier as defined by :ref:`identifiers`, for example using + :func:`setattr`, if the object allows it. + Such an attribute will not be accessible using a dotted expression, + and would instead need to be retrieved with :func:`getattr`. + awaitable An object that can be used in an :keyword:`await` expression. Can be a :term:`coroutine` or an object with an :meth:`__await__` method. @@ -203,6 +210,16 @@ A list of bytecode instructions can be found in the documentation for :ref:`the dis module `. + callable + A callable is an object that can be called, possibly with a set + of arguments (see :term:`argument`), with the following syntax:: + + callable(argument1, argument2, ...) + + A :term:`function`, and by extension a :term:`method`, is a callable. + An instance of a class that implements the :meth:`~object.__call__` + method is also a callable. + callback A subroutine function which is passed as an argument to be executed at some point in the future. @@ -876,7 +893,7 @@ package A Python :term:`module` which can contain submodules or recursively, - subpackages. Technically, a package is a Python module with an + subpackages. Technically, a package is a Python module with a ``__path__`` attribute. See also :term:`regular package` and :term:`namespace package`. diff -Nru python3.10-3.10.7/Doc/howto/annotations.rst python3.10-3.10.12/Doc/howto/annotations.rst --- python3.10-3.10.7/Doc/howto/annotations.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/annotations.rst 2023-06-06 22:30:33.000000000 +0000 @@ -57,6 +57,12 @@ newer is to call :func:`getattr` with three arguments, for example ``getattr(o, '__annotations__', None)``. + Before Python 3.10, accessing ``__annotations__`` on a class that + defines no annotations but that has a parent class with + annotations would return the parent's ``__annotations__``. + In Python 3.10 and newer, the child class's annotations + will be an empty dict instead. + Accessing The Annotations Dict Of An Object In Python 3.9 And Older =================================================================== diff -Nru python3.10-3.10.7/Doc/howto/argparse.rst python3.10-3.10.12/Doc/howto/argparse.rst --- python3.10-3.10.7/Doc/howto/argparse.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/argparse.rst 2023-06-06 22:30:33.000000000 +0000 @@ -732,9 +732,9 @@ if args.quiet: print(answer) elif args.verbose: - print("{} to the power {} equals {}".format(args.x, args.y, answer)) + print(f"{args.x} to the power {args.y} equals {answer}") else: - print("{}^{} == {}".format(args.x, args.y, answer)) + print(f"{args.x}^{args.y} == {answer}") Note that slight difference in the usage text. Note the ``[-v | -q]``, which tells us that we can either use ``-v`` or ``-q``, diff -Nru python3.10-3.10.7/Doc/howto/clinic.rst python3.10-3.10.12/Doc/howto/clinic.rst --- python3.10-3.10.7/Doc/howto/clinic.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/clinic.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1,5 +1,7 @@ .. highlight:: c +.. _howto-clinic: + ********************** Argument Clinic How-To ********************** diff -Nru python3.10-3.10.7/Doc/howto/descriptor.rst python3.10-3.10.12/Doc/howto/descriptor.rst --- python3.10-3.10.7/Doc/howto/descriptor.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/descriptor.rst 2023-06-06 22:30:33.000000000 +0000 @@ -847,7 +847,7 @@ ORM example ----------- -The following code is simplified skeleton showing how data descriptors could +The following code is a simplified skeleton showing how data descriptors could be used to implement an `object relational mapping `_. @@ -1533,6 +1533,8 @@ def __get__(self, obj, objtype=None): 'Emulate member_get() in Objects/descrobject.c' # Also see PyMember_GetOne() in Python/structmember.c + if obj is None: + return self value = obj._slotvalues[self.offset] if value is null: raise AttributeError(self.name) @@ -1561,13 +1563,13 @@ class Type(type): 'Simulate how the type metaclass adds member objects for slots' - def __new__(mcls, clsname, bases, mapping): + def __new__(mcls, clsname, bases, mapping, **kwargs): 'Emulate type_new() in Objects/typeobject.c' # type_new() calls PyTypeReady() which calls add_methods() slot_names = mapping.get('slot_names', []) for offset, name in enumerate(slot_names): mapping[name] = Member(name, clsname, offset) - return type.__new__(mcls, clsname, bases, mapping) + return type.__new__(mcls, clsname, bases, mapping, **kwargs) The :meth:`object.__new__` method takes care of creating instances that have slots instead of an instance dictionary. Here is a rough simulation in pure @@ -1578,7 +1580,7 @@ class Object: 'Simulate how object.__new__() allocates memory for __slots__' - def __new__(cls, *args): + def __new__(cls, *args, **kwargs): 'Emulate object_new() in Objects/typeobject.c' inst = super().__new__(cls) if hasattr(cls, 'slot_names'): @@ -1591,7 +1593,7 @@ cls = type(self) if hasattr(cls, 'slot_names') and name not in cls.slot_names: raise AttributeError( - f'{type(self).__name__!r} object has no attribute {name!r}' + f'{cls.__name__!r} object has no attribute {name!r}' ) super().__setattr__(name, value) @@ -1600,7 +1602,7 @@ cls = type(self) if hasattr(cls, 'slot_names') and name not in cls.slot_names: raise AttributeError( - f'{type(self).__name__!r} object has no attribute {name!r}' + f'{cls.__name__!r} object has no attribute {name!r}' ) super().__delattr__(name) diff -Nru python3.10-3.10.7/Doc/howto/logging-cookbook.rst python3.10-3.10.12/Doc/howto/logging-cookbook.rst --- python3.10-3.10.7/Doc/howto/logging-cookbook.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/logging-cookbook.rst 2023-06-06 22:30:33.000000000 +0000 @@ -276,6 +276,215 @@ and that you have the permissions to create and update files in it. +.. _custom-level-handling: + +Custom handling of levels +------------------------- + +Sometimes, you might want to do something slightly different from the standard +handling of levels in handlers, where all levels above a threshold get +processed by a handler. To do this, you need to use filters. Let's look at a +scenario where you want to arrange things as follows: + +* Send messages of severity ``INFO`` and ``WARNING`` to ``sys.stdout`` +* Send messages of severity ``ERROR`` and above to ``sys.stderr`` +* Send messages of severity ``DEBUG`` and above to file ``app.log`` + +Suppose you configure logging with the following JSON: + +.. code-block:: json + + { + "version": 1, + "disable_existing_loggers": false, + "formatters": { + "simple": { + "format": "%(levelname)-8s - %(message)s" + } + }, + "handlers": { + "stdout": { + "class": "logging.StreamHandler", + "level": "INFO", + "formatter": "simple", + "stream": "ext://sys.stdout" + }, + "stderr": { + "class": "logging.StreamHandler", + "level": "ERROR", + "formatter": "simple", + "stream": "ext://sys.stderr" + }, + "file": { + "class": "logging.FileHandler", + "formatter": "simple", + "filename": "app.log", + "mode": "w" + } + }, + "root": { + "level": "DEBUG", + "handlers": [ + "stderr", + "stdout", + "file" + ] + } + } + +This configuration does *almost* what we want, except that ``sys.stdout`` would +show messages of severity ``ERROR`` and above as well as ``INFO`` and +``WARNING`` messages. To prevent this, we can set up a filter which excludes +those messages and add it to the relevant handler. This can be configured by +adding a ``filters`` section parallel to ``formatters`` and ``handlers``: + +.. code-block:: json + + { + "filters": { + "warnings_and_below": { + "()" : "__main__.filter_maker", + "level": "WARNING" + } + } + } + +and changing the section on the ``stdout`` handler to add it: + +.. code-block:: json + + { + "stdout": { + "class": "logging.StreamHandler", + "level": "INFO", + "formatter": "simple", + "stream": "ext://sys.stdout", + "filters": ["warnings_and_below"] + } + } + +A filter is just a function, so we can define the ``filter_maker`` (a factory +function) as follows: + +.. code-block:: python + + def filter_maker(level): + level = getattr(logging, level) + + def filter(record): + return record.levelno <= level + + return filter + +This converts the string argument passed in to a numeric level, and returns a +function which only returns ``True`` if the level of the passed in record is +at or below the specified level. Note that in this example I have defined the +``filter_maker`` in a test script ``main.py`` that I run from the command line, +so its module will be ``__main__`` - hence the ``__main__.filter_maker`` in the +filter configuration. You will need to change that if you define it in a +different module. + +With the filter added, we can run ``main.py``, which in full is: + +.. code-block:: python + + import json + import logging + import logging.config + + CONFIG = ''' + { + "version": 1, + "disable_existing_loggers": false, + "formatters": { + "simple": { + "format": "%(levelname)-8s - %(message)s" + } + }, + "filters": { + "warnings_and_below": { + "()" : "__main__.filter_maker", + "level": "WARNING" + } + }, + "handlers": { + "stdout": { + "class": "logging.StreamHandler", + "level": "INFO", + "formatter": "simple", + "stream": "ext://sys.stdout", + "filters": ["warnings_and_below"] + }, + "stderr": { + "class": "logging.StreamHandler", + "level": "ERROR", + "formatter": "simple", + "stream": "ext://sys.stderr" + }, + "file": { + "class": "logging.FileHandler", + "formatter": "simple", + "filename": "app.log", + "mode": "w" + } + }, + "root": { + "level": "DEBUG", + "handlers": [ + "stderr", + "stdout", + "file" + ] + } + } + ''' + + def filter_maker(level): + level = getattr(logging, level) + + def filter(record): + return record.levelno <= level + + return filter + + logging.config.dictConfig(json.loads(CONFIG)) + logging.debug('A DEBUG message') + logging.info('An INFO message') + logging.warning('A WARNING message') + logging.error('An ERROR message') + logging.critical('A CRITICAL message') + +And after running it like this: + +.. code-block:: shell + + python main.py 2>stderr.log >stdout.log + +We can see the results are as expected: + +.. code-block:: shell + + $ more *.log + :::::::::::::: + app.log + :::::::::::::: + DEBUG - A DEBUG message + INFO - An INFO message + WARNING - A WARNING message + ERROR - An ERROR message + CRITICAL - A CRITICAL message + :::::::::::::: + stderr.log + :::::::::::::: + ERROR - An ERROR message + CRITICAL - A CRITICAL message + :::::::::::::: + stdout.log + :::::::::::::: + INFO - An INFO message + WARNING - A WARNING message + + Configuration server example ---------------------------- @@ -332,6 +541,8 @@ print('complete') +.. _blocking-handlers: + Dealing with handlers that block -------------------------------- @@ -397,6 +608,14 @@ MainThread: Look out! +.. note:: Although the earlier discussion wasn't specifically talking about + async code, but rather about slow logging handlers, it should be noted that + when logging from async code, network and even file handlers could lead to + problems (blocking the event loop) because some logging is done from + :mod:`asyncio` internals. It might be best, if any async code is used in an + application, to use the above approach for logging, so that any blocking code + runs only in the ``QueueListener`` thread. + .. versionchanged:: 3.5 Prior to Python 3.5, the :class:`QueueListener` always passed every message received from the queue to every handler it was initialized with. (This was @@ -550,13 +769,71 @@ Running a logging socket listener in production ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To run a logging listener in production, you may need to use a process-management tool -such as `Supervisor `_. `Here -`_ is a Gist which -provides the bare-bones files to run the above functionality using Supervisor: you -will need to change the `/path/to/` parts in the Gist to reflect the actual paths you -want to use. +.. _socket-listener-gist: https://gist.github.com/vsajip/4b227eeec43817465ca835ca66f75e2b + +To run a logging listener in production, you may need to use a +process-management tool such as `Supervisor `_. +`Here is a Gist `__ +which provides the bare-bones files to run the above functionality using +Supervisor. It consists of the following files: + ++-------------------------+----------------------------------------------------+ +| File | Purpose | ++=========================+====================================================+ +| :file:`prepare.sh` | A Bash script to prepare the environment for | +| | testing | ++-------------------------+----------------------------------------------------+ +| :file:`supervisor.conf` | The Supervisor configuration file, which has | +| | entries for the listener and a multi-process web | +| | application | ++-------------------------+----------------------------------------------------+ +| :file:`ensure_app.sh` | A Bash script to ensure that Supervisor is running | +| | with the above configuration | ++-------------------------+----------------------------------------------------+ +| :file:`log_listener.py` | The socket listener program which receives log | +| | events and records them to a file | ++-------------------------+----------------------------------------------------+ +| :file:`main.py` | A simple web application which performs logging | +| | via a socket connected to the listener | ++-------------------------+----------------------------------------------------+ +| :file:`webapp.json` | A JSON configuration file for the web application | ++-------------------------+----------------------------------------------------+ +| :file:`client.py` | A Python script to exercise the web application | ++-------------------------+----------------------------------------------------+ + +The web application uses `Gunicorn `_, which is a +popular web application server that starts multiple worker processes to handle +requests. This example setup shows how the workers can write to the same log file +without conflicting with one another --- they all go through the socket listener. + +To test these files, do the following in a POSIX environment: + +#. Download `the Gist `__ + as a ZIP archive using the :guilabel:`Download ZIP` button. + +#. Unzip the above files from the archive into a scratch directory. + +#. In the scratch directory, run ``bash prepare.sh`` to get things ready. + This creates a :file:`run` subdirectory to contain Supervisor-related and + log files, and a :file:`venv` subdirectory to contain a virtual environment + into which ``bottle``, ``gunicorn`` and ``supervisor`` are installed. + +#. Run ``bash ensure_app.sh`` to ensure that Supervisor is running with + the above configuration. + +#. Run ``venv/bin/python client.py`` to exercise the web application, + which will lead to records being written to the log. + +#. Inspect the log files in the :file:`run` subdirectory. You should see the + most recent log lines in files matching the pattern :file:`app.log*`. They won't be in + any particular order, since they have been handled concurrently by different + worker processes in a non-deterministic way. + +#. You can shut down the listener and the web application by running + ``venv/bin/supervisorctl -c supervisor.conf shutdown``. +You may need to tweak the configuration files in the unlikely event that the +configured ports clash with something else in your test environment. .. _context-info: @@ -858,7 +1135,7 @@ 'context can be used to ' 'populate logs') aa = ap.add_argument - aa('--count', '-c', default=100, help='How many requests to simulate') + aa('--count', '-c', type=int, default=100, help='How many requests to simulate') options = ap.parse_args() # Create the dummy webapps and put them in a list which we can use to select @@ -1709,26 +1986,47 @@ -------------------------------------------------------------- An example of how you can define a namer and rotator is given in the following -snippet, which shows zlib-based compression of the log file:: +runnable script, which shows gzip compression of the log file:: + + import gzip + import logging + import logging.handlers + import os + import shutil def namer(name): return name + ".gz" def rotator(source, dest): - with open(source, "rb") as sf: - data = sf.read() - compressed = zlib.compress(data, 9) - with open(dest, "wb") as df: - df.write(compressed) + with open(source, 'rb') as f_in: + with gzip.open(dest, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) os.remove(source) - rh = logging.handlers.RotatingFileHandler(...) + + rh = logging.handlers.RotatingFileHandler('rotated.log', maxBytes=128, backupCount=5) rh.rotator = rotator rh.namer = namer -These are not "true" .gz files, as they are bare compressed data, with no -"container" such as you’d find in an actual gzip file. This snippet is just -for illustration purposes. + root = logging.getLogger() + root.setLevel(logging.INFO) + root.addHandler(rh) + f = logging.Formatter('%(asctime)s %(message)s') + rh.setFormatter(f) + for i in range(1000): + root.info(f'Message no. {i + 1}') + +After running this, you will see six new files, five of which are compressed: + +.. code-block:: shell-session + + $ ls rotated.log* + rotated.log rotated.log.2.gz rotated.log.4.gz + rotated.log.1.gz rotated.log.3.gz rotated.log.5.gz + $ zcat rotated.log.1.gz + 2023-01-20 02:28:17,767 Message no. 996 + 2023-01-20 02:28:17,767 Message no. 997 + 2023-01-20 02:28:17,767 Message no. 998 A more elaborate multiprocessing example ---------------------------------------- @@ -2244,7 +2542,7 @@ contextual information to be added to the log). So you cannot directly make logging calls using :meth:`str.format` or :class:`string.Template` syntax, because internally the logging package uses %-formatting to merge the format -string and the variable arguments. There would no changing this while preserving +string and the variable arguments. There would be no changing this while preserving backward compatibility, since all logging calls which are out there in existing code will be using %-format strings. @@ -2766,7 +3064,7 @@ -------------------------------------------------- Sometimes you want to format times using UTC, which can be done using a class -such as `UTCFormatter`, shown below:: +such as ``UTCFormatter``, shown below:: import logging import time @@ -3420,6 +3718,147 @@ i = 1 logger.debug('Message %d', i, extra=extra) +How to treat a logger like an output stream +------------------------------------------- + +Sometimes, you need to interface to a third-party API which expects a file-like +object to write to, but you want to direct the API's output to a logger. You +can do this using a class which wraps a logger with a file-like API. +Here's a short script illustrating such a class: + +.. code-block:: python + + import logging + + class LoggerWriter: + def __init__(self, logger, level): + self.logger = logger + self.level = level + + def write(self, message): + if message != '\n': # avoid printing bare newlines, if you like + self.logger.log(self.level, message) + + def flush(self): + # doesn't actually do anything, but might be expected of a file-like + # object - so optional depending on your situation + pass + + def close(self): + # doesn't actually do anything, but might be expected of a file-like + # object - so optional depending on your situation. You might want + # to set a flag so that later calls to write raise an exception + pass + + def main(): + logging.basicConfig(level=logging.DEBUG) + logger = logging.getLogger('demo') + info_fp = LoggerWriter(logger, logging.INFO) + debug_fp = LoggerWriter(logger, logging.DEBUG) + print('An INFO message', file=info_fp) + print('A DEBUG message', file=debug_fp) + + if __name__ == "__main__": + main() + +When this script is run, it prints + +.. code-block:: text + + INFO:demo:An INFO message + DEBUG:demo:A DEBUG message + +You could also use ``LoggerWriter`` to redirect ``sys.stdout`` and +``sys.stderr`` by doing something like this: + +.. code-block:: python + + import sys + + sys.stdout = LoggerWriter(logger, logging.INFO) + sys.stderr = LoggerWriter(logger, logging.WARNING) + +You should do this *after* configuring logging for your needs. In the above +example, the :func:`~logging.basicConfig` call does this (using the +``sys.stderr`` value *before* it is overwritten by a ``LoggerWriter`` +instance). Then, you'd get this kind of result: + +.. code-block:: pycon + + >>> print('Foo') + INFO:demo:Foo + >>> print('Bar', file=sys.stderr) + WARNING:demo:Bar + >>> + +Of course, these above examples show output according to the format used by +:func:`~logging.basicConfig`, but you can use a different formatter when you +configure logging. + +Note that with the above scheme, you are somewhat at the mercy of buffering and +the sequence of write calls which you are intercepting. For example, with the +definition of ``LoggerWriter`` above, if you have the snippet + +.. code-block:: python + + sys.stderr = LoggerWriter(logger, logging.WARNING) + 1 / 0 + +then running the script results in + +.. code-block:: text + + WARNING:demo:Traceback (most recent call last): + + WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 53, in + + WARNING:demo: + WARNING:demo:main() + WARNING:demo: File "/home/runner/cookbook-loggerwriter/test.py", line 49, in main + + WARNING:demo: + WARNING:demo:1 / 0 + WARNING:demo:ZeroDivisionError + WARNING:demo:: + WARNING:demo:division by zero + +As you can see, this output isn't ideal. That's because the underlying code +which writes to ``sys.stderr`` makes mutiple writes, each of which results in a +separate logged line (for example, the last three lines above). To get around +this problem, you need to buffer things and only output log lines when newlines +are seen. Let's use a slghtly better implementation of ``LoggerWriter``: + +.. code-block:: python + + class BufferingLoggerWriter(LoggerWriter): + def __init__(self, logger, level): + super().__init__(logger, level) + self.buffer = '' + + def write(self, message): + if '\n' not in message: + self.buffer += message + else: + parts = message.split('\n') + if self.buffer: + s = self.buffer + parts.pop(0) + self.logger.log(self.level, s) + self.buffer = parts.pop() + for part in parts: + self.logger.log(self.level, part) + +This just buffers up stuff until a newline is seen, and then logs complete +lines. With this approach, you get better output: + +.. code-block:: text + + WARNING:demo:Traceback (most recent call last): + WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 55, in + WARNING:demo: main() + WARNING:demo: File "/home/runner/cookbook-loggerwriter/main.py", line 52, in main + WARNING:demo: 1/0 + WARNING:demo:ZeroDivisionError: division by zero + .. patterns-to-avoid: diff -Nru python3.10-3.10.7/Doc/howto/logging.rst python3.10-3.10.12/Doc/howto/logging.rst --- python3.10-3.10.7/Doc/howto/logging.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/logging.rst 2023-06-06 22:30:33.000000000 +0000 @@ -552,14 +552,14 @@ %Y-%m-%d %H:%M:%S -with the milliseconds tacked on at the end. The ``style`` is one of `%`, '{' -or '$'. If one of these is not specified, then '%' will be used. +with the milliseconds tacked on at the end. The ``style`` is one of ``'%'``, +``'{'``, or ``'$'``. If one of these is not specified, then ``'%'`` will be used. -If the ``style`` is '%', the message format string uses +If the ``style`` is ``'%'``, the message format string uses ``%()s`` styled string substitution; the possible keys are -documented in :ref:`logrecord-attributes`. If the style is '{', the message +documented in :ref:`logrecord-attributes`. If the style is ``'{'``, the message format string is assumed to be compatible with :meth:`str.format` (using -keyword arguments), while if the style is '$' then the message format string +keyword arguments), while if the style is ``'$'`` then the message format string should conform to what is expected by :meth:`string.Template.substitute`. .. versionchanged:: 3.2 diff -Nru python3.10-3.10.7/Doc/howto/unicode.rst python3.10-3.10.12/Doc/howto/unicode.rst --- python3.10-3.10.7/Doc/howto/unicode.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/howto/unicode.rst 2023-06-06 22:30:33.000000000 +0000 @@ -517,7 +517,7 @@ Some good alternative discussions of Python's Unicode support are: -* `Processing Text Files in Python 3 `_, by Nick Coghlan. +* `Processing Text Files in Python 3 `_, by Nick Coghlan. * `Pragmatic Unicode `_, a PyCon 2012 presentation by Ned Batchelder. The :class:`str` type is described in the Python library reference at diff -Nru python3.10-3.10.7/Doc/includes/email-read-alternative.py python3.10-3.10.12/Doc/includes/email-read-alternative.py --- python3.10-3.10.7/Doc/includes/email-read-alternative.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/includes/email-read-alternative.py 2023-06-06 22:30:33.000000000 +0000 @@ -8,8 +8,15 @@ from email import policy from email.parser import BytesParser -# An imaginary module that would make this work and be safe. -from imaginary import magic_html_parser + +def magic_html_parser(html_text, partfiles): + """Return safety-sanitized html linked to partfiles. + + Rewrite the href="cid:...." attributes to point to the filenames in partfiles. + Though not trivial, this should be possible using html.parser. + """ + raise NotImplementedError("Add the magic needed") + # In a real program you'd get the filename from the arguments. with open('outgoing.msg', 'rb') as fp: @@ -62,9 +69,6 @@ print("Don't know how to display {}".format(richest.get_content_type())) sys.exit() with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: - # The magic_html_parser has to rewrite the href="cid:...." attributes to - # point to the filenames in partfiles. It also has to do a safety-sanitize - # of the html. It could be written using html.parser. f.write(magic_html_parser(body.get_content(), partfiles)) webbrowser.open(f.name) os.remove(f.name) diff -Nru python3.10-3.10.7/Doc/includes/tzinfo_examples.py python3.10-3.10.12/Doc/includes/tzinfo_examples.py --- python3.10-3.10.7/Doc/includes/tzinfo_examples.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/includes/tzinfo_examples.py 2023-06-06 22:30:33.000000000 +0000 @@ -71,7 +71,7 @@ # DST start and end times. For a complete and up-to-date set of DST rules # and timezone definitions, visit the Olson Database (or try pytz): # http://www.twinsun.com/tz/tz-link.htm -# http://sourceforge.net/projects/pytz/ (might not be up-to-date) +# https://sourceforge.net/projects/pytz/ (might not be up-to-date) # # In the US, since 2007, DST starts at 2am (standard time) on the second # Sunday in March, which is the first Sunday on or after Mar 8. diff -Nru python3.10-3.10.7/Doc/install/index.rst python3.10-3.10.12/Doc/install/index.rst --- python3.10-3.10.7/Doc/install/index.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/install/index.rst 2023-06-06 22:30:33.000000000 +0000 @@ -761,7 +761,7 @@ +--------------+-------------------------------------------------+-------+ On all platforms, the "personal" file can be temporarily disabled by -passing the `--no-user-cfg` option. +passing the ``--no-user-cfg`` option. Notes: diff -Nru python3.10-3.10.7/Doc/library/abc.rst python3.10-3.10.12/Doc/library/abc.rst --- python3.10-3.10.7/Doc/library/abc.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/abc.rst 2023-06-06 22:30:33.000000000 +0000 @@ -21,7 +21,7 @@ ABCs; these can, of course, be further derived. In addition, the :mod:`collections.abc` submodule has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, if it is -hashable or if it is a mapping. +:term:`hashable` or if it is a mapping. This module provides the metaclass :class:`ABCMeta` for defining ABCs and diff -Nru python3.10-3.10.7/Doc/library/argparse.rst python3.10-3.10.12/Doc/library/argparse.rst --- python3.10-3.10.7/Doc/library/argparse.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/argparse.rst 2023-06-06 22:30:33.000000000 +0000 @@ -154,9 +154,10 @@ * usage_ - The string describing the program usage (default: generated from arguments added to parser) - * description_ - Text to display before the argument help (default: none) + * description_ - Text to display before the argument help + (by default, no text) - * epilog_ - Text to display after the argument help (default: none) + * epilog_ - Text to display after the argument help (by default, no text) * parents_ - A list of :class:`ArgumentParser` objects whose arguments should also be included @@ -701,7 +702,7 @@ * type_ - The type to which the command-line argument should be converted. - * choices_ - A container of the allowable values for the argument. + * choices_ - A sequence of the allowable values for the argument. * required_ - Whether or not the command-line option may be omitted (optionals only). @@ -1123,7 +1124,7 @@ ^^^^^^^ Some command-line arguments should be selected from a restricted set of values. -These can be handled by passing a container object as the *choices* keyword +These can be handled by passing a sequence object as the *choices* keyword argument to :meth:`~ArgumentParser.add_argument`. When the command line is parsed, argument values will be checked, and an error message will be displayed if the argument was not one of the acceptable values:: @@ -1137,9 +1138,9 @@ game.py: error: argument move: invalid choice: 'fire' (choose from 'rock', 'paper', 'scissors') -Note that inclusion in the *choices* container is checked after any type_ +Note that inclusion in the *choices* sequence is checked after any type_ conversions have been performed, so the type of the objects in the *choices* -container should match the type_ specified:: +sequence should match the type_ specified:: >>> parser = argparse.ArgumentParser(prog='doors.py') >>> parser.add_argument('door', type=int, choices=range(1, 4)) @@ -1149,8 +1150,8 @@ usage: doors.py [-h] {1,2,3} doors.py: error: argument door: invalid choice: 4 (choose from 1, 2, 3) -Any container can be passed as the *choices* value, so :class:`list` objects, -:class:`set` objects, and custom containers are all supported. +Any sequence can be passed as the *choices* value, so :class:`list` objects, +:class:`tuple` objects, and custom sequences are all supported. Use of :class:`enum.Enum` is not recommended because it is difficult to control its appearance in usage, help, and error messages. @@ -1770,7 +1771,7 @@ ... >>> # create the top-level parser >>> parser = argparse.ArgumentParser() - >>> subparsers = parser.add_subparsers() + >>> subparsers = parser.add_subparsers(required=True) >>> >>> # create the parser for the "foo" command >>> parser_foo = subparsers.add_parser('foo') @@ -1831,8 +1832,8 @@ Namespace(out=<_io.TextIOWrapper name='file.txt' mode='w' encoding='UTF-8'>, raw=<_io.FileIO name='raw.dat' mode='wb'>) FileType objects understand the pseudo-argument ``'-'`` and automatically - convert this into ``sys.stdin`` for readable :class:`FileType` objects and - ``sys.stdout`` for writable :class:`FileType` objects:: + convert this into :data:`sys.stdin` for readable :class:`FileType` objects and + :data:`sys.stdout` for writable :class:`FileType` objects:: >>> parser = argparse.ArgumentParser() >>> parser.add_argument('infile', type=argparse.FileType('r')) diff -Nru python3.10-3.10.7/Doc/library/array.rst python3.10-3.10.12/Doc/library/array.rst --- python3.10-3.10.7/Doc/library/array.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/array.rst 2023-06-06 22:30:33.000000000 +0000 @@ -60,7 +60,15 @@ The actual representation of values is determined by the machine architecture (strictly speaking, by the C implementation). The actual size can be accessed -through the :attr:`itemsize` attribute. +through the :attr:`array.itemsize` attribute. + +The module defines the following item: + + +.. data:: typecodes + + A string with all available type codes. + The module defines the following type: @@ -77,164 +85,160 @@ to add initial items to the array. Otherwise, the iterable initializer is passed to the :meth:`extend` method. - .. audit-event:: array.__new__ typecode,initializer array.array - -.. data:: typecodes + Array objects support the ordinary sequence operations of indexing, slicing, + concatenation, and multiplication. When using slice assignment, the assigned + value must be an array object with the same type code; in all other cases, + :exc:`TypeError` is raised. Array objects also implement the buffer interface, + and may be used wherever :term:`bytes-like objects ` are supported. - A string with all available type codes. + .. audit-event:: array.__new__ typecode,initializer array.array -Array objects support the ordinary sequence operations of indexing, slicing, -concatenation, and multiplication. When using slice assignment, the assigned -value must be an array object with the same type code; in all other cases, -:exc:`TypeError` is raised. Array objects also implement the buffer interface, -and may be used wherever :term:`bytes-like objects ` are supported. -The following data items and methods are also supported: + .. attribute:: typecode -.. attribute:: array.typecode + The typecode character used to create the array. - The typecode character used to create the array. + .. attribute:: itemsize -.. attribute:: array.itemsize + The length in bytes of one array item in the internal representation. - The length in bytes of one array item in the internal representation. + .. method:: append(x) -.. method:: array.append(x) + Append a new item with value *x* to the end of the array. - Append a new item with value *x* to the end of the array. + .. method:: buffer_info() -.. method:: array.buffer_info() + Return a tuple ``(address, length)`` giving the current memory address and the + length in elements of the buffer used to hold array's contents. The size of the + memory buffer in bytes can be computed as ``array.buffer_info()[1] * + array.itemsize``. This is occasionally useful when working with low-level (and + inherently unsafe) I/O interfaces that require memory addresses, such as certain + :c:func:`!ioctl` operations. The returned numbers are valid as long as the array + exists and no length-changing operations are applied to it. - Return a tuple ``(address, length)`` giving the current memory address and the - length in elements of the buffer used to hold array's contents. The size of the - memory buffer in bytes can be computed as ``array.buffer_info()[1] * - array.itemsize``. This is occasionally useful when working with low-level (and - inherently unsafe) I/O interfaces that require memory addresses, such as certain - :c:func:`ioctl` operations. The returned numbers are valid as long as the array - exists and no length-changing operations are applied to it. + .. note:: - .. note:: + When using array objects from code written in C or C++ (the only way to + effectively make use of this information), it makes more sense to use the buffer + interface supported by array objects. This method is maintained for backward + compatibility and should be avoided in new code. The buffer interface is + documented in :ref:`bufferobjects`. - When using array objects from code written in C or C++ (the only way to - effectively make use of this information), it makes more sense to use the buffer - interface supported by array objects. This method is maintained for backward - compatibility and should be avoided in new code. The buffer interface is - documented in :ref:`bufferobjects`. + .. method:: byteswap() -.. method:: array.byteswap() + "Byteswap" all items of the array. This is only supported for values which are + 1, 2, 4, or 8 bytes in size; for other types of values, :exc:`RuntimeError` is + raised. It is useful when reading data from a file written on a machine with a + different byte order. - "Byteswap" all items of the array. This is only supported for values which are - 1, 2, 4, or 8 bytes in size; for other types of values, :exc:`RuntimeError` is - raised. It is useful when reading data from a file written on a machine with a - different byte order. + .. method:: count(x) -.. method:: array.count(x) + Return the number of occurrences of *x* in the array. - Return the number of occurrences of *x* in the array. + .. method:: extend(iterable) -.. method:: array.extend(iterable) + Append items from *iterable* to the end of the array. If *iterable* is another + array, it must have *exactly* the same type code; if not, :exc:`TypeError` will + be raised. If *iterable* is not an array, it must be iterable and its elements + must be the right type to be appended to the array. - Append items from *iterable* to the end of the array. If *iterable* is another - array, it must have *exactly* the same type code; if not, :exc:`TypeError` will - be raised. If *iterable* is not an array, it must be iterable and its elements - must be the right type to be appended to the array. + .. method:: frombytes(s) -.. method:: array.frombytes(s) + Appends items from the string, interpreting the string as an array of machine + values (as if it had been read from a file using the :meth:`fromfile` method). - Appends items from the string, interpreting the string as an array of machine - values (as if it had been read from a file using the :meth:`fromfile` method). + .. versionadded:: 3.2 + :meth:`!fromstring` is renamed to :meth:`frombytes` for clarity. - .. versionadded:: 3.2 - :meth:`fromstring` is renamed to :meth:`frombytes` for clarity. + .. method:: fromfile(f, n) -.. method:: array.fromfile(f, n) + Read *n* items (as machine values) from the :term:`file object` *f* and append + them to the end of the array. If less than *n* items are available, + :exc:`EOFError` is raised, but the items that were available are still + inserted into the array. - Read *n* items (as machine values) from the :term:`file object` *f* and append - them to the end of the array. If less than *n* items are available, - :exc:`EOFError` is raised, but the items that were available are still - inserted into the array. + .. method:: fromlist(list) -.. method:: array.fromlist(list) + Append items from the list. This is equivalent to ``for x in list: + a.append(x)`` except that if there is a type error, the array is unchanged. - Append items from the list. This is equivalent to ``for x in list: - a.append(x)`` except that if there is a type error, the array is unchanged. + .. method:: fromunicode(s) -.. method:: array.fromunicode(s) + Extends this array with data from the given unicode string. The array must + be a type ``'u'`` array; otherwise a :exc:`ValueError` is raised. Use + ``array.frombytes(unicodestring.encode(enc))`` to append Unicode data to an + array of some other type. - Extends this array with data from the given unicode string. The array must - be a type ``'u'`` array; otherwise a :exc:`ValueError` is raised. Use - ``array.frombytes(unicodestring.encode(enc))`` to append Unicode data to an - array of some other type. + .. method:: index(x[, start[, stop]]) -.. method:: array.index(x[, start[, stop]]) + Return the smallest *i* such that *i* is the index of the first occurrence of + *x* in the array. The optional arguments *start* and *stop* can be + specified to search for *x* within a subsection of the array. Raise + :exc:`ValueError` if *x* is not found. - Return the smallest *i* such that *i* is the index of the first occurrence of - *x* in the array. The optional arguments *start* and *stop* can be - specified to search for *x* within a subsection of the array. Raise - :exc:`ValueError` if *x* is not found. + .. versionchanged:: 3.10 + Added optional *start* and *stop* parameters. - .. versionchanged:: 3.10 - Added optional *start* and *stop* parameters. -.. method:: array.insert(i, x) + .. method:: insert(i, x) - Insert a new item with value *x* in the array before position *i*. Negative - values are treated as being relative to the end of the array. + Insert a new item with value *x* in the array before position *i*. Negative + values are treated as being relative to the end of the array. -.. method:: array.pop([i]) + .. method:: pop([i]) - Removes the item with the index *i* from the array and returns it. The optional - argument defaults to ``-1``, so that by default the last item is removed and - returned. + Removes the item with the index *i* from the array and returns it. The optional + argument defaults to ``-1``, so that by default the last item is removed and + returned. -.. method:: array.remove(x) + .. method:: remove(x) - Remove the first occurrence of *x* from the array. + Remove the first occurrence of *x* from the array. -.. method:: array.reverse() + .. method:: reverse() - Reverse the order of the items in the array. + Reverse the order of the items in the array. -.. method:: array.tobytes() + .. method:: tobytes() - Convert the array to an array of machine values and return the bytes - representation (the same sequence of bytes that would be written to a file by - the :meth:`tofile` method.) + Convert the array to an array of machine values and return the bytes + representation (the same sequence of bytes that would be written to a file by + the :meth:`tofile` method.) - .. versionadded:: 3.2 - :meth:`tostring` is renamed to :meth:`tobytes` for clarity. + .. versionadded:: 3.2 + :meth:`!tostring` is renamed to :meth:`tobytes` for clarity. -.. method:: array.tofile(f) + .. method:: tofile(f) - Write all items (as machine values) to the :term:`file object` *f*. + Write all items (as machine values) to the :term:`file object` *f*. -.. method:: array.tolist() + .. method:: tolist() - Convert the array to an ordinary list with the same items. + Convert the array to an ordinary list with the same items. -.. method:: array.tounicode() + .. method:: tounicode() - Convert the array to a unicode string. The array must be a type ``'u'`` array; - otherwise a :exc:`ValueError` is raised. Use ``array.tobytes().decode(enc)`` to - obtain a unicode string from an array of some other type. + Convert the array to a unicode string. The array must be a type ``'u'`` array; + otherwise a :exc:`ValueError` is raised. Use ``array.tobytes().decode(enc)`` to + obtain a unicode string from an array of some other type. When an array object is printed or converted to a string, it is represented as diff -Nru python3.10-3.10.7/Doc/library/ast.rst python3.10-3.10.12/Doc/library/ast.rst --- python3.10-3.10.7/Doc/library/ast.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/ast.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1959,20 +1959,28 @@ .. function:: literal_eval(node_or_string) - Safely evaluate an expression node or a string containing a Python literal or + Evaluate an expression node or a string containing only a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, ``None`` and ``Ellipsis``. - This can be used for safely evaluating strings containing Python values from - untrusted sources without the need to parse the values oneself. It is not - capable of evaluating arbitrarily complex expressions, for example involving - operators or indexing. + This can be used for evaluating strings containing Python values without the + need to parse the values oneself. It is not capable of evaluating + arbitrarily complex expressions, for example involving operators or + indexing. + + This function had been documented as "safe" in the past without defining + what that meant. That was misleading. This is specifically designed not to + execute Python code, unlike the more general :func:`eval`. There is no + namespace, no name lookups, or ability to call out. But it is not free from + attack: A relatively small input can lead to memory exhaustion or to C stack + exhaustion, crashing the process. There is also the possibility for + excessive CPU consumption denial of service on some inputs. Calling it on + untrusted data is thus not recommended. .. warning:: - It is possible to crash the Python interpreter with a - sufficiently large/complex string due to stack depth limitations - in Python's AST compiler. + It is possible to crash the Python interpreter due to stack depth + limitations in Python's AST compiler. It can raise :exc:`ValueError`, :exc:`TypeError`, :exc:`SyntaxError`, :exc:`MemoryError` and :exc:`RecursionError` depending on the malformed @@ -2237,7 +2245,7 @@ code that generated them. This is helpful for tools that make source code transformations. - `leoAst.py `_ unifies the + `leoAst.py `_ unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes. diff -Nru python3.10-3.10.7/Doc/library/asyncio-dev.rst python3.10-3.10.12/Doc/library/asyncio-dev.rst --- python3.10-3.10.7/Doc/library/asyncio-dev.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-dev.rst 2023-06-06 22:30:33.000000000 +0000 @@ -109,7 +109,7 @@ There is currently no way to schedule coroutines or callbacks directly from a different process (such as one started with -:mod:`multiprocessing`). The :ref:`Event Loop Methods ` +:mod:`multiprocessing`). The :ref:`asyncio-event-loop-methods` section lists APIs that can read from pipes and watch file descriptors without blocking the event loop. In addition, asyncio's :ref:`Subprocess ` APIs provide a way to start a @@ -148,6 +148,11 @@ logging.getLogger("asyncio").setLevel(logging.WARNING) +Network logging can block the event loop. It is recommended to use +a separate thread for handling logs or use non-blocking IO. For example, +see :ref:`blocking-handlers`. + + .. _asyncio-coroutine-not-scheduled: Detect never-awaited coroutines diff -Nru python3.10-3.10.7/Doc/library/asyncio-eventloop.rst python3.10-3.10.12/Doc/library/asyncio-eventloop.rst --- python3.10-3.10.7/Doc/library/asyncio-eventloop.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-eventloop.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1,6 +1,8 @@ .. currentmodule:: asyncio +.. _asyncio-event-loop: + ========== Event Loop ========== @@ -31,7 +33,8 @@ Return the running event loop in the current OS thread. - If there is no running event loop a :exc:`RuntimeError` is raised. + Raise a :exc:`RuntimeError` if there is no running event loop. + This function can only be called from a coroutine or a callback. .. versionadded:: 3.7 @@ -40,27 +43,35 @@ Get the current event loop. - If there is no current event loop set in the current OS thread, - the OS thread is main, and :func:`set_event_loop` has not yet - been called, asyncio will create a new event loop and set it as the - current one. + When called from a coroutine or a callback (e.g. scheduled with + call_soon or similar API), this function will always return the + running event loop. + + If there is no running event loop set, the function will return + the result of the ``get_event_loop_policy().get_event_loop()`` call. Because this function has rather complex behavior (especially when custom event loop policies are in use), using the :func:`get_running_loop` function is preferred to :func:`get_event_loop` in coroutines and callbacks. - Consider also using the :func:`asyncio.run` function instead of using - lower level functions to manually create and close an event loop. + As noted above, consider using the higher-level :func:`asyncio.run` function, + instead of using these lower level functions to manually create and close an + event loop. - .. deprecated:: 3.10 - Deprecation warning is emitted if there is no running event loop. - In future Python releases, this function will be an alias of - :func:`get_running_loop`. + .. note:: + In Python versions 3.10.0--3.10.8 and 3.11.0 this function + (and other functions which use it implicitly) emitted a + :exc:`DeprecationWarning` if there was no running event loop, even if + the current loop was set on the policy. + In Python versions 3.10.9, 3.11.1 and 3.12 they emit a + :exc:`DeprecationWarning` if there is no running event loop and no + current loop is set. + In some future Python release this will become an error. .. function:: set_event_loop(loop) - Set *loop* as a current event loop for the current OS thread. + Set *loop* as the current event loop for the current OS thread. .. function:: new_event_loop() @@ -92,7 +103,7 @@ loop APIs. -.. _asyncio-event-loop: +.. _asyncio-event-loop-methods: Event Loop Methods ================== @@ -181,12 +192,15 @@ .. coroutinemethod:: loop.shutdown_default_executor() Schedule the closure of the default executor and wait for it to join all of - the threads in the :class:`ThreadPoolExecutor`. After calling this method, a - :exc:`RuntimeError` will be raised if :meth:`loop.run_in_executor` is called - while using the default executor. + the threads in the :class:`~concurrent.futures.ThreadPoolExecutor`. + Once this method has been called, + using the default executor with :meth:`loop.run_in_executor` + will raise a :exc:`RuntimeError`. - Note that there is no need to call this function when - :func:`asyncio.run` is used. + .. note:: + + Do not call this method when using :func:`asyncio.run`, + as the latter handles default executor shutdown automatically. .. versionadded:: 3.9 @@ -199,22 +213,23 @@ Schedule the *callback* :term:`callback` to be called with *args* arguments at the next iteration of the event loop. + Return an instance of :class:`asyncio.Handle`, + which can be used later to cancel the callback. + Callbacks are called in the order in which they are registered. Each callback will be called exactly once. - An optional keyword-only *context* argument allows specifying a + The optional keyword-only *context* argument specifies a custom :class:`contextvars.Context` for the *callback* to run in. - The current context is used when no *context* is provided. - - An instance of :class:`asyncio.Handle` is returned, which can be - used later to cancel the callback. + Callbacks use the current context when no *context* is provided. - This method is not thread-safe. + Unlike :meth:`call_soon_threadsafe`, this method is not thread-safe. .. method:: loop.call_soon_threadsafe(callback, *args, context=None) - A thread-safe variant of :meth:`call_soon`. Must be used to - schedule callbacks *from another thread*. + A thread-safe variant of :meth:`call_soon`. When scheduling callbacks from + another thread, this function *must* be used, since :meth:`call_soon` is not + thread-safe. Raises :exc:`RuntimeError` if called on a loop that's been closed. This can happen on a secondary thread when the main application is @@ -448,6 +463,12 @@ *happy_eyeballs_delay*, *interleave* and *local_addr* should be specified. + .. note:: + + The *sock* argument transfers ownership of the socket to the + transport created. To close the socket, call the transport's + :meth:`~asyncio.BaseTransport.close` method. + * *local_addr*, if given, is a ``(local_host, local_port)`` tuple used to bind the socket locally. The *local_host* and *local_port* are looked up using ``getaddrinfo()``, similarly to *host* and *port*. @@ -477,8 +498,8 @@ When a server's IPv4 path and protocol are working, but the server's IPv6 path and protocol are not working, a dual-stack client application experiences significant connection delay compared to an - IPv4-only client. This is undesirable because it causes the dual- - stack client to have a worse user experience. This document + IPv4-only client. This is undesirable because it causes the + dual-stack client to have a worse user experience. This document specifies requirements for algorithms that reduce this user-visible delay and provides an algorithm. @@ -553,6 +574,12 @@ transport. If specified, *local_addr* and *remote_addr* should be omitted (must be :const:`None`). + .. note:: + + The *sock* argument transfers ownership of the socket to the + transport created. To close the socket, call the transport's + :meth:`~asyncio.BaseTransport.close` method. + See :ref:`UDP echo client protocol ` and :ref:`UDP echo server protocol ` examples. @@ -642,6 +669,12 @@ * *sock* can optionally be specified in order to use a preexisting socket object. If specified, *host* and *port* must not be specified. + .. note:: + + The *sock* argument transfers ownership of the socket to the + server created. To close the socket, call the server's + :meth:`~asyncio.Server.close` method. + * *backlog* is the maximum number of queued connections passed to :meth:`~socket.socket.listen` (defaults to 100). @@ -727,6 +760,12 @@ * *sock* is a preexisting socket object returned from :meth:`socket.accept `. + .. note:: + + The *sock* argument transfers ownership of the socket to the + transport created. To close the socket, call the transport's + :meth:`~asyncio.BaseTransport.close` method. + * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the accepted connections. @@ -782,9 +821,14 @@ Upgrade an existing transport-based connection to TLS. - Return a new transport instance, that the *protocol* must start using - immediately after the *await*. The *transport* instance passed to - the *start_tls* method should never be used again. + Create a TLS coder/decoder instance and insert it between the *transport* + and the *protocol*. The coder/decoder implements both *transport*-facing + protocol and *protocol*-facing transport. + + Return the created two-interface instance. After *await*, the *protocol* + must stop using the original *transport* and communicate with the returned + object only because the coder caches *protocol*-side data and sporadically + exchanges extra TLS session packets with *transport*. Parameters: @@ -818,7 +862,8 @@ .. method:: loop.remove_reader(fd) - Stop monitoring the *fd* file descriptor for read availability. + Stop monitoring the *fd* file descriptor for read availability. Returns + ``True`` if *fd* was previously being monitored for reads. .. method:: loop.add_writer(fd, callback, *args) @@ -831,7 +876,8 @@ .. method:: loop.remove_writer(fd) - Stop monitoring the *fd* file descriptor for write availability. + Stop monitoring the *fd* file descriptor for write availability. Returns + ``True`` if *fd* was previously being monitored for writes. See also :ref:`Platform Support ` section for some limitations of these methods. @@ -1114,7 +1160,13 @@ pool, cpu_bound) print('custom process pool', result) - asyncio.run(main()) + if __name__ == '__main__': + asyncio.run(main()) + + Note that the entry point guard (``if __name__ == '__main__'``) + is required for option 3 due to the peculiarities of :mod:`multiprocessing`, + which is used by :class:`~concurrent.futures.ProcessPoolExecutor`. + See :ref:`Safe importing of main module `. This method returns a :class:`asyncio.Future` object. @@ -1498,6 +1550,7 @@ .. _asyncio-event-loops: +.. _asyncio-event-loop-implementations: Event Loop Implementations ========================== @@ -1520,9 +1573,12 @@ import asyncio import selectors - selector = selectors.SelectSelector() - loop = asyncio.SelectorEventLoop(selector) - asyncio.set_event_loop(loop) + class MyPolicy(asyncio.DefaultEventLoopPolicy): + def new_event_loop(self): + selector = selectors.SelectSelector() + return asyncio.SelectorEventLoop(selector) + + asyncio.set_event_loop_policy(MyPolicy()) .. availability:: Unix, Windows. @@ -1544,7 +1600,7 @@ Abstract base class for asyncio-compliant event loops. - The :ref:`Event Loop Methods ` section lists all + The :ref:`asyncio-event-loop-methods` section lists all methods that an alternative implementation of ``AbstractEventLoop`` should have defined. diff -Nru python3.10-3.10.7/Doc/library/asyncio-future.rst python3.10-3.10.12/Doc/library/asyncio-future.rst --- python3.10-3.10.7/Doc/library/asyncio-future.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-future.rst 2023-06-06 22:30:33.000000000 +0000 @@ -55,7 +55,7 @@ preferred way for creating new Tasks. Save a reference to the result of this function, to avoid - a task disappearing mid execution. + a task disappearing mid-execution. .. versionchanged:: 3.5.1 The function accepts any :term:`awaitable` object. @@ -85,7 +85,8 @@ Future is an :term:`awaitable` object. Coroutines can await on Future objects until they either have a result or an exception - set, or until they are cancelled. + set, or until they are cancelled. A Future can be awaited multiple + times and the result is same. Typically Futures are used to enable low-level callback-based code (e.g. in protocols implemented using asyncio diff -Nru python3.10-3.10.7/Doc/library/asyncio-llapi-index.rst python3.10-3.10.12/Doc/library/asyncio-llapi-index.rst --- python3.10-3.10.7/Doc/library/asyncio-llapi-index.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-llapi-index.rst 2023-06-06 22:30:33.000000000 +0000 @@ -19,7 +19,7 @@ - The **preferred** function to get the running event loop. * - :func:`asyncio.get_event_loop` - - Get an event loop instance (current or via the policy). + - Get an event loop instance (running or current via the current policy). * - :func:`asyncio.set_event_loop` - Set the event loop as current via the current policy. @@ -37,7 +37,7 @@ ================== See also the main documentation section about the -:ref:`event loop methods `. +:ref:`asyncio-event-loop-methods`. .. rubric:: Lifecycle .. list-table:: diff -Nru python3.10-3.10.7/Doc/library/asyncio-policy.rst python3.10-3.10.12/Doc/library/asyncio-policy.rst --- python3.10-3.10.7/Doc/library/asyncio-policy.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-policy.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,22 +7,29 @@ Policies ======== -An event loop policy is a global per-process object that controls -the management of the event loop. Each event loop has a default -policy, which can be changed and customized using the policy API. - -A policy defines the notion of *context* and manages a -separate event loop per context. The default policy -defines *context* to be the current thread. - -By using a custom event loop policy, the behavior of -:func:`get_event_loop`, :func:`set_event_loop`, and -:func:`new_event_loop` functions can be customized. +An event loop policy is a global object +used to get and set the current :ref:`event loop `, +as well as create new event loops. +The default policy can be :ref:`replaced ` with +:ref:`built-in alternatives ` +to use different event loop implementations, +or substituted by a :ref:`custom policy ` +that can override these behaviors. + +The :ref:`policy object ` +gets and sets a separate event loop per *context*. +This is per-thread by default, +though custom policies could define *context* differently. + +Custom event loop policies can control the behavior of +:func:`get_event_loop`, :func:`set_event_loop`, and :func:`new_event_loop`. Policy objects should implement the APIs defined in the :class:`AbstractEventLoopPolicy` abstract base class. +.. _asyncio-policy-get-set: + Getting and Setting the Policy ============================== @@ -40,6 +47,8 @@ If *policy* is set to ``None``, the default policy is restored. +.. _asyncio-policy-objects: + Policy Objects ============== @@ -86,6 +95,8 @@ This function is Unix specific. +.. _asyncio-policy-builtin: + asyncio ships with the following built-in policies: @@ -101,6 +112,12 @@ On Windows, :class:`ProactorEventLoop` is now used by default. + .. note:: + In Python versions 3.10.9, 3.11.1 and 3.12 the :meth:`get_event_loop` + method of the default asyncio policy emits a :exc:`DeprecationWarning` + if there is no running event loop and no current loop is set. + In some future Python release this will become an error. + .. class:: WindowsSelectorEventLoopPolicy @@ -117,6 +134,7 @@ .. availability:: Windows. + .. _asyncio-watchers: Process Watchers @@ -270,6 +288,8 @@ .. versionadded:: 3.9 +.. _asyncio-custom-policies: + Custom Policies =============== diff -Nru python3.10-3.10.7/Doc/library/asyncio-protocol.rst python3.10-3.10.12/Doc/library/asyncio-protocol.rst --- python3.10-3.10.7/Doc/library/asyncio-protocol.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-protocol.rst 2023-06-06 22:30:33.000000000 +0000 @@ -156,7 +156,8 @@ will be received. After all buffered data is flushed, the protocol's :meth:`protocol.connection_lost() ` method will be called with - :const:`None` as its argument. + :const:`None` as its argument. The transport should not be + used once it is closed. .. method:: BaseTransport.is_closing() @@ -553,7 +554,7 @@ a connection is open. However, :meth:`protocol.eof_received() ` - is called at most once. Once `eof_received()` is called, + is called at most once. Once ``eof_received()`` is called, ``data_received()`` is not called anymore. .. method:: Protocol.eof_received() diff -Nru python3.10-3.10.7/Doc/library/asyncio.rst python3.10-3.10.12/Doc/library/asyncio.rst --- python3.10-3.10.7/Doc/library/asyncio.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio.rst 2023-06-06 22:30:33.000000000 +0000 @@ -56,6 +56,17 @@ * :ref:`bridge ` callback-based libraries and code with async/await syntax. +You can experiment with an ``asyncio`` concurrent context in the REPL: + +.. code-block:: pycon + + $ python -m asyncio + asyncio REPL ... + Use "await" directly instead of "asyncio.run()". + Type "help", "copyright", "credits" or "license" for more information. + >>> import asyncio + >>> await asyncio.sleep(10, result='hello') + 'hello' .. We use the "rubric" directive here to avoid creating the "Reference" subsection in the TOC. diff -Nru python3.10-3.10.7/Doc/library/asyncio-stream.rst python3.10-3.10.12/Doc/library/asyncio-stream.rst --- python3.10-3.10.7/Doc/library/asyncio-stream.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-stream.rst 2023-06-06 22:30:33.000000000 +0000 @@ -67,6 +67,12 @@ The rest of the arguments are passed directly to :meth:`loop.create_connection`. + .. note:: + + The *sock* argument transfers ownership of the socket to the + :class:`StreamWriter` created. To close the socket, call its + :meth:`~asyncio.StreamWriter.close` method. + .. versionchanged:: 3.7 Added the *ssl_handshake_timeout* parameter. @@ -103,6 +109,12 @@ The rest of the arguments are passed directly to :meth:`loop.create_server`. + .. note:: + + The *sock* argument transfers ownership of the socket to the + server created. To close the socket, call the server's + :meth:`~asyncio.Server.close` method. + .. versionchanged:: 3.7 Added the *ssl_handshake_timeout* and *start_serving* parameters. @@ -123,6 +135,12 @@ See also the documentation of :meth:`loop.create_unix_connection`. + .. note:: + + The *sock* argument transfers ownership of the socket to the + :class:`StreamWriter` created. To close the socket, call its + :meth:`~asyncio.StreamWriter.close` method. + .. availability:: Unix. .. versionchanged:: 3.7 @@ -143,6 +161,12 @@ See also the documentation of :meth:`loop.create_unix_server`. + .. note:: + + The *sock* argument transfers ownership of the socket to the + server created. To close the socket, call the server's + :meth:`~asyncio.Server.close` method. + .. availability:: Unix. .. versionchanged:: 3.7 @@ -159,7 +183,8 @@ .. class:: StreamReader Represents a reader object that provides APIs to read data - from the IO stream. + from the IO stream. As an :term:`asynchronous iterable`, the + object supports the :keyword:`async for` statement. It is not recommended to instantiate *StreamReader* objects directly; use :func:`open_connection` and :func:`start_server` @@ -167,12 +192,20 @@ .. coroutinemethod:: read(n=-1) - Read up to *n* bytes. If *n* is not provided, or set to ``-1``, - read until EOF and return all read bytes. + Read up to *n* bytes from the stream. + If *n* is not provided or set to ``-1``, + read until EOF, then return all read :class:`bytes`. If EOF was received and the internal buffer is empty, return an empty ``bytes`` object. + If *n* is ``0``, return an empty ``bytes`` object immediately. + + If *n* is positive, return at most *n* available ``bytes`` + as soon as at least 1 byte is available in the internal buffer. + If EOF is received before any byte is read, return an empty + ``bytes`` object. + .. coroutinemethod:: readline() Read one line, where "line" is a sequence of bytes @@ -256,7 +289,8 @@ The method closes the stream and the underlying socket. - The method should be used along with the ``wait_closed()`` method:: + The method should be used, though not mandatory, + along with the ``wait_closed()`` method:: stream.close() await stream.wait_closed() @@ -307,7 +341,8 @@ Wait until the stream is closed. Should be called after :meth:`close` to wait until the underlying - connection is closed. + connection is closed, ensuring that all data has been flushed + before e.g. exiting the program. .. versionadded:: 3.7 @@ -336,6 +371,7 @@ print('Close the connection') writer.close() + await writer.wait_closed() asyncio.run(tcp_echo_client('Hello World!')) @@ -368,6 +404,7 @@ print("Close the connection") writer.close() + await writer.wait_closed() async def main(): server = await asyncio.start_server( @@ -424,6 +461,7 @@ # Ignore the body, close the socket writer.close() + await writer.wait_closed() url = sys.argv[1] asyncio.run(print_http_headers(url)) @@ -469,6 +507,7 @@ # Got data, we are done: close the socket print("Received:", data.decode()) writer.close() + await writer.wait_closed() # Close the second socket wsock.close() diff -Nru python3.10-3.10.7/Doc/library/asyncio-subprocess.rst python3.10-3.10.12/Doc/library/asyncio-subprocess.rst --- python3.10-3.10.7/Doc/library/asyncio-subprocess.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-subprocess.rst 2023-06-06 22:30:33.000000000 +0000 @@ -175,7 +175,7 @@ * the :meth:`~asyncio.subprocess.Process.communicate` and :meth:`~asyncio.subprocess.Process.wait` methods don't have a - *timeout* parameter: use the :func:`wait_for` function; + *timeout* parameter: use the :func:`~asyncio.wait_for` function; * the :meth:`Process.wait() ` method is asynchronous, whereas :meth:`subprocess.Popen.wait` method diff -Nru python3.10-3.10.7/Doc/library/asyncio-task.rst python3.10-3.10.12/Doc/library/asyncio-task.rst --- python3.10-3.10.7/Doc/library/asyncio-task.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/asyncio-task.rst 2023-06-06 22:30:33.000000000 +0000 @@ -18,6 +18,10 @@ Coroutines ========== +**Source code:** :source:`Lib/asyncio/coroutines.py` + +---------------------------------------------------- + :term:`Coroutines ` declared with the async/await syntax is the preferred way of writing asyncio applications. For example, the following snippet of code prints "hello", waits 1 second, @@ -247,6 +251,10 @@ Creating Tasks ============== +**Source code:** :source:`Lib/asyncio/tasks.py` + +----------------------------------------------- + .. function:: create_task(coro, *, name=None) Wrap the *coro* :ref:`coroutine ` into a :class:`Task` @@ -262,9 +270,9 @@ .. important:: Save a reference to the result of this function, to avoid - a task disappearing mid execution. The event loop only keeps + a task disappearing mid-execution. The event loop only keeps weak references to tasks. A task that isn't referenced elsewhere - may get garbage-collected at any time, even before it's done. + may get garbage collected at any time, even before it's done. For reliable "fire-and-forget" background tasks, gather them in a collection:: @@ -441,7 +449,8 @@ The statement:: - res = await shield(something()) + task = asyncio.create_task(something()) + res = await shield(task) is equivalent to:: @@ -460,11 +469,19 @@ the ``shield()`` function should be combined with a try/except clause, as follows:: + task = asyncio.create_task(something()) try: - res = await shield(something()) + res = await shield(task) except CancelledError: res = None + .. important:: + + Save a reference to tasks passed to this function, to avoid + a task disappearing mid-execution. The event loop only keeps + weak references to tasks. A task that isn't referenced elsewhere + may get garbage collected at any time, even before it's done. + .. versionchanged:: 3.10 Removed the *loop* parameter. @@ -637,9 +654,6 @@ Raises :exc:`asyncio.TimeoutError` if the timeout occurs before all Futures are done. - .. versionchanged:: 3.10 - Removed the *loop* parameter. - Example:: for coro in as_completed(aws): @@ -698,17 +712,17 @@ # blocking_io complete at 19:50:54 # finished main at 19:50:54 - Directly calling `blocking_io()` in any coroutine would block the event loop + Directly calling ``blocking_io()`` in any coroutine would block the event loop for its duration, resulting in an additional 1 second of run time. Instead, - by using `asyncio.to_thread()`, we can run it in a separate thread without + by using ``asyncio.to_thread()``, we can run it in a separate thread without blocking the event loop. .. note:: - Due to the :term:`GIL`, `asyncio.to_thread()` can typically only be used + Due to the :term:`GIL`, ``asyncio.to_thread()`` can typically only be used to make IO-bound functions non-blocking. However, for extension modules that release the GIL or alternative Python implementations that don't - have one, `asyncio.to_thread()` can also be used for CPU-bound functions. + have one, ``asyncio.to_thread()`` can also be used for CPU-bound functions. .. versionadded:: 3.9 @@ -985,7 +999,7 @@ The *limit* argument is passed to :meth:`get_stack` directly. The *file* argument is an I/O stream to which the output - is written; by default output is written to :data:`sys.stderr`. + is written; by default output is written to :data:`sys.stdout`. .. method:: get_coro() diff -Nru python3.10-3.10.7/Doc/library/base64.rst python3.10-3.10.12/Doc/library/base64.rst --- python3.10-3.10.7/Doc/library/base64.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/base64.rst 2023-06-06 22:30:33.000000000 +0000 @@ -53,11 +53,13 @@ Encode the :term:`bytes-like object` *s* using Base64 and return the encoded :class:`bytes`. - Optional *altchars* must be a :term:`bytes-like object` of at least - length 2 (additional characters are ignored) which specifies an alternative - alphabet for the ``+`` and ``/`` characters. This allows an application to e.g. - generate URL or filesystem safe Base64 strings. The default is ``None``, for - which the standard Base64 alphabet is used. + Optional *altchars* must be a :term:`bytes-like object` of length 2 which + specifies an alternative alphabet for the ``+`` and ``/`` characters. + This allows an application to e.g. generate URL or filesystem safe Base64 + strings. The default is ``None``, for which the standard Base64 alphabet is used. + + May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2. Raises a + :exc:`TypeError` if *altchars* is not a :term:`bytes-like object`. .. function:: b64decode(s, altchars=None, validate=False) @@ -65,9 +67,9 @@ Decode the Base64 encoded :term:`bytes-like object` or ASCII string *s* and return the decoded :class:`bytes`. - Optional *altchars* must be a :term:`bytes-like object` or ASCII string of - at least length 2 (additional characters are ignored) which specifies the - alternative alphabet used instead of the ``+`` and ``/`` characters. + Optional *altchars* must be a :term:`bytes-like object` or ASCII string + of length 2 which specifies the alternative alphabet used instead of the + ``+`` and ``/`` characters. A :exc:`binascii.Error` exception is raised if *s* is incorrectly padded. @@ -78,6 +80,7 @@ these non-alphabet characters in the input result in a :exc:`binascii.Error`. + May assert or raise a :exc:`ValueError` if the length of *altchars* is not 2. .. function:: standard_b64encode(s) diff -Nru python3.10-3.10.7/Doc/library/bdb.rst python3.10-3.10.12/Doc/library/bdb.rst --- python3.10-3.10.7/Doc/library/bdb.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/bdb.rst 2023-06-06 22:30:33.000000000 +0000 @@ -143,7 +143,7 @@ For real file names, the canonical form is an operating-system-dependent, :func:`case-normalized ` :func:`absolute path - `. A *filename* with angle brackets, such as `""` + `. A *filename* with angle brackets, such as ``""`` generated in interactive mode, is returned unchanged. .. method:: reset() diff -Nru python3.10-3.10.7/Doc/library/bisect.rst python3.10-3.10.12/Doc/library/bisect.rst --- python3.10-3.10.7/Doc/library/bisect.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/bisect.rst 2023-06-06 22:30:33.000000000 +0000 @@ -127,7 +127,7 @@ .. seealso:: * `Sorted Collections - `_ is a high performance + `_ is a high performance module that uses *bisect* to managed sorted collections of data. * The `SortedCollection recipe diff -Nru python3.10-3.10.7/Doc/library/bz2.rst python3.10-3.10.12/Doc/library/bz2.rst --- python3.10-3.10.7/Doc/library/bz2.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/bz2.rst 2023-06-06 22:30:33.000000000 +0000 @@ -206,7 +206,7 @@ will be set to ``True``. Attempting to decompress data after the end of stream is reached - raises an `EOFError`. Any data found after the end of the + raises an :exc:`EOFError`. Any data found after the end of the stream is ignored and saved in the :attr:`~.unused_data` attribute. .. versionchanged:: 3.5 @@ -303,7 +303,7 @@ >>> out = out + comp.flush() The example above uses a very "nonrandom" stream of data -(a stream of `b"z"` chunks). Random data tends to compress poorly, +(a stream of ``b"z"`` chunks). Random data tends to compress poorly, while ordered, repetitive data usually yields a high compression ratio. Writing and reading a bzip2-compressed file in binary mode: diff -Nru python3.10-3.10.7/Doc/library/cmath.rst python3.10-3.10.12/Doc/library/cmath.rst --- python3.10-3.10.7/Doc/library/cmath.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/cmath.rst 2023-06-06 22:30:33.000000000 +0000 @@ -15,11 +15,27 @@ .. note:: - On platforms with hardware and system-level support for signed - zeros, functions involving branch cuts are continuous on *both* - sides of the branch cut: the sign of the zero distinguishes one - side of the branch cut from the other. On platforms that do not - support signed zeros the continuity is as specified below. + For functions involving branch cuts, we have the problem of deciding how to + define those functions on the cut itself. Following Kahan's "Branch cuts for + complex elementary functions" paper, as well as Annex G of C99 and later C + standards, we use the sign of zero to distinguish one side of the branch cut + from the other: for a branch cut along (a portion of) the real axis we look + at the sign of the imaginary part, while for a branch cut along the + imaginary axis we look at the sign of the real part. + + For example, the :func:`cmath.sqrt` function has a branch cut along the + negative real axis. An argument of ``complex(-2.0, -0.0)`` is treated as + though it lies *below* the branch cut, and so gives a result on the negative + imaginary axis:: + + >>> cmath.sqrt(complex(-2.0, -0.0)) + -1.4142135623730951j + + But an argument of ``complex(-2.0, 0.0)`` is treated as though it lies above + the branch cut:: + + >>> cmath.sqrt(complex(-2.0, 0.0)) + 1.4142135623730951j Conversions to and from polar coordinates @@ -44,14 +60,11 @@ .. function:: phase(x) - Return the phase of *x* (also known as the *argument* of *x*), as a - float. ``phase(x)`` is equivalent to ``math.atan2(x.imag, - x.real)``. The result lies in the range [-\ *π*, *π*], and the branch - cut for this operation lies along the negative real axis, - continuous from above. On systems with support for signed zeros - (which includes most systems in current use), this means that the - sign of the result is the same as the sign of ``x.imag``, even when - ``x.imag`` is zero:: + Return the phase of *x* (also known as the *argument* of *x*), as a float. + ``phase(x)`` is equivalent to ``math.atan2(x.imag, x.real)``. The result + lies in the range [-\ *π*, *π*], and the branch cut for this operation lies + along the negative real axis. The sign of the result is the same as the + sign of ``x.imag``, even when ``x.imag`` is zero:: >>> phase(complex(-1.0, 0.0)) 3.141592653589793 @@ -92,8 +105,8 @@ .. function:: log(x[, base]) Returns the logarithm of *x* to the given *base*. If the *base* is not - specified, returns the natural logarithm of *x*. There is one branch cut, from 0 - along the negative real axis to -∞, continuous from above. + specified, returns the natural logarithm of *x*. There is one branch cut, + from 0 along the negative real axis to -∞. .. function:: log10(x) @@ -112,9 +125,9 @@ .. function:: acos(x) - Return the arc cosine of *x*. There are two branch cuts: One extends right from - 1 along the real axis to ∞, continuous from below. The other extends left from - -1 along the real axis to -∞, continuous from above. + Return the arc cosine of *x*. There are two branch cuts: One extends right + from 1 along the real axis to ∞. The other extends left from -1 along the + real axis to -∞. .. function:: asin(x) @@ -125,9 +138,8 @@ .. function:: atan(x) Return the arc tangent of *x*. There are two branch cuts: One extends from - ``1j`` along the imaginary axis to ``∞j``, continuous from the right. The - other extends from ``-1j`` along the imaginary axis to ``-∞j``, continuous - from the left. + ``1j`` along the imaginary axis to ``∞j``. The other extends from ``-1j`` + along the imaginary axis to ``-∞j``. .. function:: cos(x) @@ -151,23 +163,21 @@ .. function:: acosh(x) Return the inverse hyperbolic cosine of *x*. There is one branch cut, - extending left from 1 along the real axis to -∞, continuous from above. + extending left from 1 along the real axis to -∞. .. function:: asinh(x) Return the inverse hyperbolic sine of *x*. There are two branch cuts: - One extends from ``1j`` along the imaginary axis to ``∞j``, - continuous from the right. The other extends from ``-1j`` along - the imaginary axis to ``-∞j``, continuous from the left. + One extends from ``1j`` along the imaginary axis to ``∞j``. The other + extends from ``-1j`` along the imaginary axis to ``-∞j``. .. function:: atanh(x) Return the inverse hyperbolic tangent of *x*. There are two branch cuts: One - extends from ``1`` along the real axis to ``∞``, continuous from below. The - other extends from ``-1`` along the real axis to ``-∞``, continuous from - above. + extends from ``1`` along the real axis to ``∞``. The other extends from + ``-1`` along the real axis to ``-∞``. .. function:: cosh(x) diff -Nru python3.10-3.10.7/Doc/library/codecs.rst python3.10-3.10.12/Doc/library/codecs.rst --- python3.10-3.10.7/Doc/library/codecs.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/codecs.rst 2023-06-06 22:30:33.000000000 +0000 @@ -189,7 +189,8 @@ .. note:: - Underlying encoded files are always opened in binary mode. + If *encoding* is not ``None``, then the + underlying encoded files are always opened in binary mode. No automatic conversion of ``'\n'`` is done on reading and writing. The *mode* argument may be any binary mode acceptable to the built-in :func:`open` function; the ``'b'`` is automatically added. diff -Nru python3.10-3.10.7/Doc/library/codeop.rst python3.10-3.10.12/Doc/library/codeop.rst --- python3.10-3.10.7/Doc/library/codeop.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/codeop.rst 2023-06-06 22:30:33.000000000 +0000 @@ -19,10 +19,10 @@ There are two parts to this job: -#. Being able to tell if a line of input completes a Python statement: in +#. Being able to tell if a line of input completes a Python statement: in short, telling whether to print '``>>>``' or '``...``' next. -#. Remembering which future statements the user has entered, so subsequent +#. Remembering which future statements the user has entered, so subsequent input can be compiled with these in effect. The :mod:`codeop` module provides a way of doing each of these things, and a way @@ -33,9 +33,9 @@ .. function:: compile_command(source, filename="", symbol="single") Tries to compile *source*, which should be a string of Python code and return a - code object if *source* is valid Python code. In that case, the filename + code object if *source* is valid Python code. In that case, the filename attribute of the code object will be *filename*, which defaults to - ``''``. Returns ``None`` if *source* is *not* valid Python code, but is a + ``''``. Returns ``None`` if *source* is *not* valid Python code, but is a prefix of valid Python code. If there is a problem with *source*, an exception will be raised. @@ -43,9 +43,9 @@ :exc:`OverflowError` or :exc:`ValueError` if there is an invalid literal. The *symbol* argument determines whether *source* is compiled as a statement - (``'single'``, the default), as a sequence of statements (``'exec'``) or + (``'single'``, the default), as a sequence of :term:`statement` (``'exec'``) or as an :term:`expression` (``'eval'``). Any other value will - cause :exc:`ValueError` to be raised. + cause :exc:`ValueError` to be raised. .. note:: @@ -69,5 +69,5 @@ Instances of this class have :meth:`__call__` methods identical in signature to :func:`compile_command`; the difference is that if the instance compiles program - text containing a ``__future__`` statement, the instance 'remembers' and + text containing a :mod:`__future__` statement, the instance 'remembers' and compiles all subsequent program texts with the statement in force. diff -Nru python3.10-3.10.7/Doc/library/collections.abc.rst python3.10-3.10.12/Doc/library/collections.abc.rst --- python3.10-3.10.7/Doc/library/collections.abc.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/collections.abc.rst 2023-06-06 22:30:33.000000000 +0000 @@ -22,7 +22,7 @@ This module provides :term:`abstract base classes ` that can be used to test whether a class provides a particular interface; for -example, whether it is hashable or whether it is a mapping. +example, whether it is :term:`hashable` or whether it is a mapping. An :func:`issubclass` or :func:`isinstance` test for an interface works in one of three ways. @@ -406,7 +406,7 @@ (3) The :class:`Set` mixin provides a :meth:`_hash` method to compute a hash value for the set; however, :meth:`__hash__` is not defined because not all sets - are hashable or immutable. To add set hashability using mixins, + are :term:`hashable` or immutable. To add set hashability using mixins, inherit from both :meth:`Set` and :meth:`Hashable`, then define ``__hash__ = Set._hash``. diff -Nru python3.10-3.10.7/Doc/library/collections.rst python3.10-3.10.12/Doc/library/collections.rst --- python3.10-3.10.7/Doc/library/collections.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/collections.rst 2023-06-06 22:30:33.000000000 +0000 @@ -25,7 +25,7 @@ :func:`namedtuple` factory function for creating tuple subclasses with named fields :class:`deque` list-like container with fast appends and pops on either end :class:`ChainMap` dict-like class for creating a single view of multiple mappings -:class:`Counter` dict subclass for counting hashable objects +:class:`Counter` dict subclass for counting :term:`hashable` objects :class:`OrderedDict` dict subclass that remembers the order entries were added :class:`defaultdict` dict subclass that calls a factory function to supply missing values :class:`UserDict` wrapper around dictionary objects for easier dict subclassing @@ -241,7 +241,7 @@ .. class:: Counter([iterable-or-mapping]) - A :class:`Counter` is a :class:`dict` subclass for counting hashable objects. + A :class:`Counter` is a :class:`dict` subclass for counting :term:`hashable` objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The :class:`Counter` diff -Nru python3.10-3.10.7/Doc/library/compileall.rst python3.10-3.10.12/Doc/library/compileall.rst --- python3.10-3.10.7/Doc/library/compileall.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/compileall.rst 2023-06-06 22:30:33.000000000 +0000 @@ -198,7 +198,7 @@ The *stripdir*, *prependdir* and *limit_sl_dest* arguments correspond to the ``-s``, ``-p`` and ``-e`` options described above. - They may be specified as ``str``, ``bytes`` or :py:class:`os.PathLike`. + They may be specified as ``str`` or :py:class:`os.PathLike`. If *hardlink_dupes* is true and two ``.pyc`` files with different optimization level have the same content, use hard links to consolidate duplicate files. @@ -268,7 +268,7 @@ The *stripdir*, *prependdir* and *limit_sl_dest* arguments correspond to the ``-s``, ``-p`` and ``-e`` options described above. - They may be specified as ``str``, ``bytes`` or :py:class:`os.PathLike`. + They may be specified as ``str`` or :py:class:`os.PathLike`. If *hardlink_dupes* is true and two ``.pyc`` files with different optimization level have the same content, use hard links to consolidate duplicate files. diff -Nru python3.10-3.10.7/Doc/library/concurrent.futures.rst python3.10-3.10.12/Doc/library/concurrent.futures.rst --- python3.10-3.10.7/Doc/library/concurrent.futures.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/concurrent.futures.rst 2023-06-06 22:30:33.000000000 +0000 @@ -151,7 +151,7 @@ All threads enqueued to ``ThreadPoolExecutor`` will be joined before the interpreter can exit. Note that the exit handler which does this is - executed *before* any exit handlers added using `atexit`. This means + executed *before* any exit handlers added using ``atexit``. This means exceptions in the main thread must be caught and handled in order to signal threads to exit gracefully. For this reason, it is recommended that ``ThreadPoolExecutor`` not be used for long-running tasks. @@ -201,7 +201,7 @@ 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', - 'http://some-made-up-domain.com/'] + 'http://nonexistant-subdomain.python.org/'] # Retrieve a single page and report the URL and contents def load_url(url, timeout): @@ -398,13 +398,13 @@ tests. If the method returns ``False`` then the :class:`Future` was cancelled, - i.e. :meth:`Future.cancel` was called and returned `True`. Any threads + i.e. :meth:`Future.cancel` was called and returned ``True``. Any threads waiting on the :class:`Future` completing (i.e. through :func:`as_completed` or :func:`wait`) will be woken up. If the method returns ``True`` then the :class:`Future` was not cancelled and has been put in the running state, i.e. calls to - :meth:`Future.running` will return `True`. + :meth:`Future.running` will return ``True``. This method can only be called once and cannot be called after :meth:`Future.set_result` or :meth:`Future.set_exception` have been diff -Nru python3.10-3.10.7/Doc/library/configparser.rst python3.10-3.10.12/Doc/library/configparser.rst --- python3.10-3.10.7/Doc/library/configparser.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/configparser.rst 2023-06-06 22:30:33.000000000 +0000 @@ -65,10 +65,10 @@ CompressionLevel = 9 ForwardX11 = yes - [bitbucket.org] + [forge.example] User = hg - [topsecret.server.com] + [topsecret.server.example] Port = 50022 ForwardX11 = no @@ -85,10 +85,10 @@ >>> config['DEFAULT'] = {'ServerAliveInterval': '45', ... 'Compression': 'yes', ... 'CompressionLevel': '9'} - >>> config['bitbucket.org'] = {} - >>> config['bitbucket.org']['User'] = 'hg' - >>> config['topsecret.server.com'] = {} - >>> topsecret = config['topsecret.server.com'] + >>> config['forge.example'] = {} + >>> config['forge.example']['User'] = 'hg' + >>> config['topsecret.server.example'] = {} + >>> topsecret = config['topsecret.server.example'] >>> topsecret['Port'] = '50022' # mutates the parser >>> topsecret['ForwardX11'] = 'no' # same here >>> config['DEFAULT']['ForwardX11'] = 'yes' @@ -111,28 +111,28 @@ >>> config.read('example.ini') ['example.ini'] >>> config.sections() - ['bitbucket.org', 'topsecret.server.com'] - >>> 'bitbucket.org' in config + ['forge.example', 'topsecret.server.example'] + >>> 'forge.example' in config True - >>> 'bytebong.com' in config + >>> 'python.org' in config False - >>> config['bitbucket.org']['User'] + >>> config['forge.example']['User'] 'hg' >>> config['DEFAULT']['Compression'] 'yes' - >>> topsecret = config['topsecret.server.com'] + >>> topsecret = config['topsecret.server.example'] >>> topsecret['ForwardX11'] 'no' >>> topsecret['Port'] '50022' - >>> for key in config['bitbucket.org']: # doctest: +SKIP + >>> for key in config['forge.example']: # doctest: +SKIP ... print(key) user compressionlevel serveraliveinterval compression forwardx11 - >>> config['bitbucket.org']['ForwardX11'] + >>> config['forge.example']['ForwardX11'] 'yes' As we can see above, the API is pretty straightforward. The only bit of magic @@ -150,15 +150,15 @@ >>> another_config = configparser.ConfigParser() >>> another_config.read('example.ini') ['example.ini'] - >>> another_config['topsecret.server.com']['Port'] + >>> another_config['topsecret.server.example']['Port'] '50022' - >>> another_config.read_string("[topsecret.server.com]\nPort=48484") - >>> another_config['topsecret.server.com']['Port'] + >>> another_config.read_string("[topsecret.server.example]\nPort=48484") + >>> another_config['topsecret.server.example']['Port'] '48484' - >>> another_config.read_dict({"topsecret.server.com": {"Port": 21212}}) - >>> another_config['topsecret.server.com']['Port'] + >>> another_config.read_dict({"topsecret.server.example": {"Port": 21212}}) + >>> another_config['topsecret.server.example']['Port'] '21212' - >>> another_config['topsecret.server.com']['ForwardX11'] + >>> another_config['topsecret.server.example']['ForwardX11'] 'no' This behaviour is equivalent to a :meth:`ConfigParser.read` call with several @@ -191,9 +191,9 @@ >>> topsecret.getboolean('ForwardX11') False - >>> config['bitbucket.org'].getboolean('ForwardX11') + >>> config['forge.example'].getboolean('ForwardX11') True - >>> config.getboolean('bitbucket.org', 'Compression') + >>> config.getboolean('forge.example', 'Compression') True Apart from :meth:`~ConfigParser.getboolean`, config parsers also @@ -220,7 +220,7 @@ Please note that default values have precedence over fallback values. For instance, in our example the ``'CompressionLevel'`` key was specified only in the ``'DEFAULT'`` section. If we try to get it from -the section ``'topsecret.server.com'``, we will always get the default, +the section ``'topsecret.server.example'``, we will always get the default, even if we specify a fallback: .. doctest:: @@ -235,7 +235,7 @@ .. doctest:: - >>> config.get('bitbucket.org', 'monster', + >>> config.get('forge.example', 'monster', ... fallback='No such things as monsters') 'No such things as monsters' diff -Nru python3.10-3.10.7/Doc/library/contextlib.rst python3.10-3.10.12/Doc/library/contextlib.rst --- python3.10-3.10.7/Doc/library/contextlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/contextlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -66,6 +66,8 @@ # Code to release resource, e.g.: release_resource(resource) + The function can then be used like this:: + >>> with managed_resource(timeout=3600) as resource: ... # Resource is released at the end of this block, ... # even if code in the block raises an exception @@ -140,9 +142,9 @@ finally: print(f'it took {time.monotonic() - now}s to run') - @timeit() - async def main(): - # ... async code ... + @timeit() + async def main(): + # ... async code ... When used as a decorator, a new generator instance is implicitly created on each function call. This allows the otherwise "one-shot" context managers @@ -249,15 +251,15 @@ :ref:`asynchronous context managers `:: async def send_http(session=None): - if not session: - # If no http session, create it with aiohttp - cm = aiohttp.ClientSession() - else: - # Caller is responsible for closing the session - cm = nullcontext(session) + if not session: + # If no http session, create it with aiohttp + cm = aiohttp.ClientSession() + else: + # Caller is responsible for closing the session + cm = nullcontext(session) - async with cm as session: - # Send http requests with session + async with cm as session: + # Send http requests with session .. versionadded:: 3.7 @@ -379,6 +381,8 @@ print('Finishing') return False + The class can then be used like this:: + >>> @mycontext() ... def function(): ... print('The bit in the middle') @@ -449,6 +453,8 @@ print('Finishing') return False + The class can then be used like this:: + >>> @mycontext() ... async def function(): ... print('The bit in the middle') diff -Nru python3.10-3.10.7/Doc/library/contextvars.rst python3.10-3.10.12/Doc/library/contextvars.rst --- python3.10-3.10.7/Doc/library/contextvars.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/contextvars.rst 2023-06-06 22:30:33.000000000 +0000 @@ -110,7 +110,7 @@ A read-only property. Set to the value the variable had before the :meth:`ContextVar.set` method call that created the token. - It points to :attr:`Token.MISSING` is the variable was not set + It points to :attr:`Token.MISSING` if the variable was not set before the call. .. attribute:: Token.MISSING @@ -144,6 +144,11 @@ To get a copy of the current context use the :func:`~contextvars.copy_context` function. + Every thread will have a different top-level :class:`~contextvars.Context` + object. This means that a :class:`ContextVar` object behaves in a similar + fashion to :func:`threading.local()` when values are assigned in different + threads. + Context implements the :class:`collections.abc.Mapping` interface. .. method:: run(callable, *args, **kwargs) diff -Nru python3.10-3.10.7/Doc/library/copyreg.rst python3.10-3.10.12/Doc/library/copyreg.rst --- python3.10-3.10.7/Doc/library/copyreg.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/copyreg.rst 2023-06-06 22:30:33.000000000 +0000 @@ -25,20 +25,17 @@ hence not valid as a constructor), raises :exc:`TypeError`. -.. function:: pickle(type, function, constructor=None) +.. function:: pickle(type, function, constructor_ob=None) Declares that *function* should be used as a "reduction" function for objects of type *type*. *function* should return either a string or a tuple - containing two or three elements. + containing two or three elements. See the :attr:`~pickle.Pickler.dispatch_table` + for more details on the interface of *function*. - The optional *constructor* parameter, if provided, is a callable object which - can be used to reconstruct the object when called with the tuple of arguments - returned by *function* at pickling time. A :exc:`TypeError` is raised if the - *constructor* is not callable. - - See the :mod:`pickle` module for more details on the interface - expected of *function* and *constructor*. Note that the - :attr:`~pickle.Pickler.dispatch_table` attribute of a pickler + The *constructor_ob* parameter is a legacy feature and is now ignored, but if + passed it must be a callable. + + Note that the :attr:`~pickle.Pickler.dispatch_table` attribute of a pickler object or subclass of :class:`pickle.Pickler` can also be used for declaring reduction functions. diff -Nru python3.10-3.10.7/Doc/library/csv.rst python3.10-3.10.12/Doc/library/csv.rst --- python3.10-3.10.7/Doc/library/csv.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/csv.rst 2023-06-06 22:30:33.000000000 +0000 @@ -412,7 +412,7 @@ .. attribute:: Dialect.skipinitialspace - When :const:`True`, whitespace immediately following the *delimiter* is ignored. + When :const:`True`, spaces immediately following the *delimiter* are ignored. The default is :const:`False`. @@ -450,7 +450,7 @@ DictReader objects have the following public attribute: -.. attribute:: csvreader.fieldnames +.. attribute:: DictReader.fieldnames If not passed as a parameter when creating the object, this attribute is initialized upon first access or when the first record is read from the diff -Nru python3.10-3.10.7/Doc/library/ctypes.rst python3.10-3.10.12/Doc/library/ctypes.rst --- python3.10-3.10.7/Doc/library/ctypes.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/ctypes.rst 2023-06-06 22:30:33.000000000 +0000 @@ -6,6 +6,8 @@ .. moduleauthor:: Thomas Heller +**Source code:** :source:`Lib/ctypes` + -------------- :mod:`ctypes` is a foreign function library for Python. It provides C compatible @@ -197,9 +199,9 @@ ``None``, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls. ``None`` is passed as a C ``NULL`` pointer, bytes objects and strings are passed -as pointer to the memory block that contains their data (:c:type:`char *` or -:c:type:`wchar_t *`). Python integers are passed as the platforms default C -:c:type:`int` type, their value is masked to fit into the C type. +as pointer to the memory block that contains their data (:c:expr:`char *` or +:c:expr:`wchar_t *`). Python integers are passed as the platforms default C +:c:expr:`int` type, their value is masked to fit into the C type. Before we move on calling functions with other parameter types, we have to learn more about :mod:`ctypes` data types. @@ -215,49 +217,49 @@ +----------------------+------------------------------------------+----------------------------+ | ctypes type | C type | Python type | +======================+==========================================+============================+ -| :class:`c_bool` | :c:type:`_Bool` | bool (1) | +| :class:`c_bool` | :c:expr:`_Bool` | bool (1) | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_char` | :c:type:`char` | 1-character bytes object | +| :class:`c_char` | :c:expr:`char` | 1-character bytes object | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_wchar` | :c:type:`wchar_t` | 1-character string | +| :class:`c_wchar` | :c:expr:`wchar_t` | 1-character string | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_byte` | :c:type:`char` | int | +| :class:`c_byte` | :c:expr:`char` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_ubyte` | :c:type:`unsigned char` | int | +| :class:`c_ubyte` | :c:expr:`unsigned char` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_short` | :c:type:`short` | int | +| :class:`c_short` | :c:expr:`short` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_ushort` | :c:type:`unsigned short` | int | +| :class:`c_ushort` | :c:expr:`unsigned short` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_int` | :c:type:`int` | int | +| :class:`c_int` | :c:expr:`int` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_uint` | :c:type:`unsigned int` | int | +| :class:`c_uint` | :c:expr:`unsigned int` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_long` | :c:type:`long` | int | +| :class:`c_long` | :c:expr:`long` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_ulong` | :c:type:`unsigned long` | int | +| :class:`c_ulong` | :c:expr:`unsigned long` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_longlong` | :c:type:`__int64` or :c:type:`long long` | int | +| :class:`c_longlong` | :c:expr:`__int64` or :c:expr:`long long` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_ulonglong` | :c:type:`unsigned __int64` or | int | -| | :c:type:`unsigned long long` | | +| :class:`c_ulonglong` | :c:expr:`unsigned __int64` or | int | +| | :c:expr:`unsigned long long` | | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_size_t` | :c:type:`size_t` | int | +| :class:`c_size_t` | :c:expr:`size_t` | int | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_ssize_t` | :c:type:`ssize_t` or | int | -| | :c:type:`Py_ssize_t` | | +| :class:`c_ssize_t` | :c:expr:`ssize_t` or | int | +| | :c:expr:`Py_ssize_t` | | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_float` | :c:type:`float` | float | +| :class:`c_float` | :c:expr:`float` | float | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_double` | :c:type:`double` | float | +| :class:`c_double` | :c:expr:`double` | float | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_longdouble`| :c:type:`long double` | float | +| :class:`c_longdouble`| :c:expr:`long double` | float | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_char_p` | :c:type:`char *` (NUL terminated) | bytes object or ``None`` | +| :class:`c_char_p` | :c:expr:`char *` (NUL terminated) | bytes object or ``None`` | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_wchar_p` | :c:type:`wchar_t *` (NUL terminated) | string or ``None`` | +| :class:`c_wchar_p` | :c:expr:`wchar_t *` (NUL terminated) | string or ``None`` | +----------------------+------------------------------------------+----------------------------+ -| :class:`c_void_p` | :c:type:`void *` | int or ``None`` | +| :class:`c_void_p` | :c:expr:`void *` | int or ``None`` | +----------------------+------------------------------------------+----------------------------+ (1) @@ -333,7 +335,7 @@ The :func:`create_string_buffer` function replaces the :func:`c_buffer` function (which is still available as an alias), as well as the :func:`c_string` function from earlier ctypes releases. To create a mutable memory block containing -unicode characters of the C type :c:type:`wchar_t` use the +unicode characters of the C type :c:expr:`wchar_t` use the :func:`create_unicode_buffer` function. @@ -359,7 +361,7 @@ >>> printf(b"%f bottles of beer\n", 42.5) Traceback (most recent call last): File "", line 1, in - ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2 + ArgumentError: argument 2: TypeError: Don't know how to convert parameter 2 >>> As has been mentioned before, all Python types except integers, strings, and @@ -371,6 +373,26 @@ 31 >>> +.. _ctypes-calling-variadic-functions: + +Calling variadic functions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On a lot of platforms calling variadic functions through ctypes is exactly the same +as calling functions with a fixed number of parameters. On some platforms, and in +particular ARM64 for Apple Platforms, the calling convention for variadic functions +is different than that for regular functions. + +On those platforms it is required to specify the *argtypes* attribute for the +regular, non-variadic, function arguments: + +.. code-block:: python3 + + libc.printf.argtypes = [ctypes.c_char_p] + +Because specifying the attribute does inhibit portability it is advised to always +specify ``argtypes`` for all variadic functions. + .. _ctypes-calling-functions-with-own-custom-data-types: @@ -422,7 +444,7 @@ >>> printf(b"%d %d %d", 1, 2, 3) Traceback (most recent call last): File "", line 1, in - ArgumentError: argument 2: exceptions.TypeError: wrong type + ArgumentError: argument 2: TypeError: wrong type >>> printf(b"%s %d %f\n", b"X", 2, 3) X 2 3.000000 13 @@ -444,7 +466,7 @@ Return types ^^^^^^^^^^^^ -By default functions are assumed to return the C :c:type:`int` type. Other +By default functions are assumed to return the C :c:expr:`int` type. Other return types can be specified by setting the :attr:`restype` attribute of the function object. @@ -472,7 +494,7 @@ >>> strchr(b"abcdef", b"def") Traceback (most recent call last): File "", line 1, in - ArgumentError: argument 2: exceptions.TypeError: one character string expected + ArgumentError: argument 2: TypeError: one character string expected >>> print(strchr(b"abcdef", b"x")) None >>> strchr(b"abcdef", b"d") @@ -1075,7 +1097,7 @@ Quoting the docs for that value: - This pointer is initialized to point to an array of :c:type:`struct _frozen` + This pointer is initialized to point to an array of :c:struct:`_frozen` records, terminated by one whose members are all ``NULL`` or zero. When a frozen module is imported, it is searched in this table. Third-party code could play tricks with this to provide a dynamically created collection of frozen modules. @@ -1092,7 +1114,7 @@ ... >>> -We have defined the :c:type:`struct _frozen` data type, so we can get the pointer +We have defined the :c:struct:`_frozen` data type, so we can get the pointer to the table:: >>> FrozenTable = POINTER(struct_frozen) @@ -1324,7 +1346,7 @@ Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return - :c:type:`int`. + :c:expr:`int`. On Windows creating a :class:`CDLL` instance may fail even if the DLL name exists. When a dependent DLL of the loaded DLL is not found, a @@ -1359,7 +1381,7 @@ Windows only: Instances of this class represent loaded shared libraries, functions in these libraries use the ``stdcall`` calling convention, and are - assumed to return :c:type:`int` by default. + assumed to return :c:expr:`int` by default. The Python :term:`global interpreter lock` is released before calling any function exported by these libraries, and reacquired afterwards. @@ -1515,7 +1537,7 @@ An instance of :class:`PyDLL` that exposes Python C API functions as attributes. Note that all these functions are assumed to return C - :c:type:`int`, which is of course not always the truth, so you have to assign + :c:expr:`int`, which is of course not always the truth, so you have to assign the correct :attr:`restype` attribute to use these functions. .. audit-event:: ctypes.dlopen name ctypes.LibraryLoader @@ -1561,10 +1583,10 @@ .. attribute:: restype Assign a ctypes type to specify the result type of the foreign function. - Use ``None`` for :c:type:`void`, a function not returning anything. + Use ``None`` for :c:expr:`void`, a function not returning anything. It is possible to assign a callable Python object that is not a ctypes - type, in this case the function is assumed to return a C :c:type:`int`, and + type, in this case the function is assumed to return a C :c:expr:`int`, and the callable will be called with this integer, allowing further processing or error checking. Using this is deprecated, for more flexible post processing or error checking use a ctypes data type as @@ -1935,7 +1957,7 @@ .. function:: GetLastError() Windows only: Returns the last error code set by Windows in the calling thread. - This function calls the Windows `GetLastError()` function directly, + This function calls the Windows ``GetLastError()`` function directly, it does not return the ctypes-private copy of the error code. .. function:: get_errno() @@ -2177,21 +2199,21 @@ .. class:: c_byte - Represents the C :c:type:`signed char` datatype, and interprets the value as + Represents the C :c:expr:`signed char` datatype, and interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_char - Represents the C :c:type:`char` datatype, and interprets the value as a single + Represents the C :c:expr:`char` datatype, and interprets the value as a single character. The constructor accepts an optional string initializer, the length of the string must be exactly one character. .. class:: c_char_p - Represents the C :c:type:`char *` datatype when it points to a zero-terminated + Represents the C :c:expr:`char *` datatype when it points to a zero-terminated string. For a general character pointer that may also point to binary data, ``POINTER(c_char)`` must be used. The constructor accepts an integer address, or a bytes object. @@ -2199,68 +2221,68 @@ .. class:: c_double - Represents the C :c:type:`double` datatype. The constructor accepts an + Represents the C :c:expr:`double` datatype. The constructor accepts an optional float initializer. .. class:: c_longdouble - Represents the C :c:type:`long double` datatype. The constructor accepts an + Represents the C :c:expr:`long double` datatype. The constructor accepts an optional float initializer. On platforms where ``sizeof(long double) == sizeof(double)`` it is an alias to :class:`c_double`. .. class:: c_float - Represents the C :c:type:`float` datatype. The constructor accepts an + Represents the C :c:expr:`float` datatype. The constructor accepts an optional float initializer. .. class:: c_int - Represents the C :c:type:`signed int` datatype. The constructor accepts an + Represents the C :c:expr:`signed int` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where ``sizeof(int) == sizeof(long)`` it is an alias to :class:`c_long`. .. class:: c_int8 - Represents the C 8-bit :c:type:`signed int` datatype. Usually an alias for + Represents the C 8-bit :c:expr:`signed int` datatype. Usually an alias for :class:`c_byte`. .. class:: c_int16 - Represents the C 16-bit :c:type:`signed int` datatype. Usually an alias for + Represents the C 16-bit :c:expr:`signed int` datatype. Usually an alias for :class:`c_short`. .. class:: c_int32 - Represents the C 32-bit :c:type:`signed int` datatype. Usually an alias for + Represents the C 32-bit :c:expr:`signed int` datatype. Usually an alias for :class:`c_int`. .. class:: c_int64 - Represents the C 64-bit :c:type:`signed int` datatype. Usually an alias for + Represents the C 64-bit :c:expr:`signed int` datatype. Usually an alias for :class:`c_longlong`. .. class:: c_long - Represents the C :c:type:`signed long` datatype. The constructor accepts an + Represents the C :c:expr:`signed long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_longlong - Represents the C :c:type:`signed long long` datatype. The constructor accepts + Represents the C :c:expr:`signed long long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_short - Represents the C :c:type:`signed short` datatype. The constructor accepts an + Represents the C :c:expr:`signed short` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. @@ -2278,83 +2300,83 @@ .. class:: c_ubyte - Represents the C :c:type:`unsigned char` datatype, it interprets the value as + Represents the C :c:expr:`unsigned char` datatype, it interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_uint - Represents the C :c:type:`unsigned int` datatype. The constructor accepts an + Represents the C :c:expr:`unsigned int` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where ``sizeof(int) == sizeof(long)`` it is an alias for :class:`c_ulong`. .. class:: c_uint8 - Represents the C 8-bit :c:type:`unsigned int` datatype. Usually an alias for + Represents the C 8-bit :c:expr:`unsigned int` datatype. Usually an alias for :class:`c_ubyte`. .. class:: c_uint16 - Represents the C 16-bit :c:type:`unsigned int` datatype. Usually an alias for + Represents the C 16-bit :c:expr:`unsigned int` datatype. Usually an alias for :class:`c_ushort`. .. class:: c_uint32 - Represents the C 32-bit :c:type:`unsigned int` datatype. Usually an alias for + Represents the C 32-bit :c:expr:`unsigned int` datatype. Usually an alias for :class:`c_uint`. .. class:: c_uint64 - Represents the C 64-bit :c:type:`unsigned int` datatype. Usually an alias for + Represents the C 64-bit :c:expr:`unsigned int` datatype. Usually an alias for :class:`c_ulonglong`. .. class:: c_ulong - Represents the C :c:type:`unsigned long` datatype. The constructor accepts an + Represents the C :c:expr:`unsigned long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_ulonglong - Represents the C :c:type:`unsigned long long` datatype. The constructor + Represents the C :c:expr:`unsigned long long` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_ushort - Represents the C :c:type:`unsigned short` datatype. The constructor accepts + Represents the C :c:expr:`unsigned short` datatype. The constructor accepts an optional integer initializer; no overflow checking is done. .. class:: c_void_p - Represents the C :c:type:`void *` type. The value is represented as integer. + Represents the C :c:expr:`void *` type. The value is represented as integer. The constructor accepts an optional integer initializer. .. class:: c_wchar - Represents the C :c:type:`wchar_t` datatype, and interprets the value as a + Represents the C :c:expr:`wchar_t` datatype, and interprets the value as a single character unicode string. The constructor accepts an optional string initializer, the length of the string must be exactly one character. .. class:: c_wchar_p - Represents the C :c:type:`wchar_t *` datatype, which must be a pointer to a + Represents the C :c:expr:`wchar_t *` datatype, which must be a pointer to a zero-terminated wide character string. The constructor accepts an integer address, or a string. .. class:: c_bool - Represent the C :c:type:`bool` datatype (more accurately, :c:type:`_Bool` from + Represent the C :c:expr:`bool` datatype (more accurately, :c:expr:`_Bool` from C99). Its value can be ``True`` or ``False``, and the constructor accepts any object that has a truth value. @@ -2367,8 +2389,8 @@ .. class:: py_object - Represents the C :c:type:`PyObject *` datatype. Calling this without an - argument creates a ``NULL`` :c:type:`PyObject *` pointer. + Represents the C :c:expr:`PyObject *` datatype. Calling this without an + argument creates a ``NULL`` :c:expr:`PyObject *` pointer. The :mod:`ctypes.wintypes` module provides quite some other Windows specific data types, for example :c:type:`HWND`, :c:type:`WPARAM`, or :c:type:`DWORD`. Some diff -Nru python3.10-3.10.7/Doc/library/curses.ascii.rst python3.10-3.10.12/Doc/library/curses.ascii.rst --- python3.10-3.10.7/Doc/library/curses.ascii.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/curses.ascii.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,8 @@ .. moduleauthor:: Eric S. Raymond .. sectionauthor:: Eric S. Raymond +**Source code:** :source:`Lib/curses/ascii.py` + -------------- The :mod:`curses.ascii` module supplies name constants for ASCII characters and diff -Nru python3.10-3.10.7/Doc/library/curses.rst python3.10-3.10.12/Doc/library/curses.rst --- python3.10-3.10.7/Doc/library/curses.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/curses.rst 2023-06-06 22:30:33.000000000 +0000 @@ -9,6 +9,8 @@ .. sectionauthor:: Moshe Zadka .. sectionauthor:: Eric Raymond +**Source code:** :source:`Lib/curses` + -------------- The :mod:`curses` module provides an interface to the curses library, the @@ -292,7 +294,7 @@ Change the definition of a color, taking the number of the color to be changed followed by three RGB values (for the amounts of red, green, and blue components). The value of *color_number* must be between ``0`` and - `COLORS - 1`. Each of *r*, *g*, *b*, must be a value between ``0`` and + ``COLORS - 1``. Each of *r*, *g*, *b*, must be a value between ``0`` and ``1000``. When :func:`init_color` is used, all occurrences of that color on the screen immediately change to the new definition. This function is a no-op on most terminals; it is active only if :func:`can_change_color` returns ``True``. @@ -1312,11 +1314,11 @@ :meth:`refresh`. -.. method:: window.vline(ch, n) - window.vline(y, x, ch, n) +.. method:: window.vline(ch, n[, attr]) + window.vline(y, x, ch, n[, attr]) Display a vertical line starting at ``(y, x)`` with length *n* consisting of the - character *ch*. + character *ch* with attributes *attr*. Constants diff -Nru python3.10-3.10.7/Doc/library/dataclasses.rst python3.10-3.10.12/Doc/library/dataclasses.rst --- python3.10-3.10.7/Doc/library/dataclasses.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/dataclasses.rst 2023-06-06 22:30:33.000000000 +0000 @@ -79,7 +79,8 @@ class C: ... - @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False) + @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, + match_args=True, kw_only=False, slots=False) class C: ... @@ -534,7 +535,7 @@ Class variables --------------- -One of two places where :func:`dataclass` actually inspects the type +One of the few places where :func:`dataclass` actually inspects the type of a field is to determine if a field is a class variable as defined in :pep:`526`. It does this by checking if the type of the field is ``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded @@ -545,7 +546,7 @@ Init-only variables ------------------- -The other place where :func:`dataclass` inspects a type annotation is to +Another place where :func:`dataclass` inspects a type annotation is to determine if a field is an init-only variable. It does this by seeing if the type of a field is of type ``dataclasses.InitVar``. If a field is an ``InitVar``, it is considered a pseudo-field called an init-only @@ -561,8 +562,8 @@ @dataclass class C: i: int - j: int = None - database: InitVar[DatabaseType] = None + j: int | None = None + database: InitVar[DatabaseType | None] = None def __post_init__(self, database): if self.j is None and database is not None: diff -Nru python3.10-3.10.7/Doc/library/datetime.rst python3.10-3.10.12/Doc/library/datetime.rst --- python3.10-3.10.7/Doc/library/datetime.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/datetime.rst 2023-06-06 22:30:33.000000000 +0000 @@ -154,7 +154,7 @@ share these common features: - Objects of these types are immutable. -- Objects of these types are hashable, meaning that they can be used as +- Objects of these types are :term:`hashable`, meaning that they can be used as dictionary keys. - Objects of these types support efficient pickling via the :mod:`pickle` module. @@ -1342,7 +1342,7 @@ Because naive ``datetime`` objects are treated by many ``datetime`` methods as local times, it is preferred to use aware datetimes to represent times - in UTC; as a result, using ``utcfromtimetuple`` may give misleading + in UTC; as a result, using :meth:`datetime.utctimetuple` may give misleading results. If you have a naive ``datetime`` representing UTC, use ``datetime.replace(tzinfo=timezone.utc)`` to make it aware, at which point you can use :meth:`.datetime.timetuple`. @@ -2246,7 +2246,7 @@ two digits of ``offset.hours`` and ``offset.minutes`` respectively. .. versionchanged:: 3.6 - Name generated from ``offset=timedelta(0)`` is now plain `'UTC'`, not + Name generated from ``offset=timedelta(0)`` is now plain ``'UTC'``, not ``'UTC+00:00'``. @@ -2570,7 +2570,7 @@ (9) When used with the :meth:`strptime` method, the leading zero is optional - for formats ``%d``, ``%m``, ``%H``, ``%I``, ``%M``, ``%S``, ``%J``, ``%U``, + for formats ``%d``, ``%m``, ``%H``, ``%I``, ``%M``, ``%S``, ``%j``, ``%U``, ``%W``, and ``%V``. Format ``%y`` does require a leading zero. .. rubric:: Footnotes diff -Nru python3.10-3.10.7/Doc/library/decimal.rst python3.10-3.10.12/Doc/library/decimal.rst --- python3.10-3.10.7/Doc/library/decimal.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/decimal.rst 2023-06-06 22:30:33.000000000 +0000 @@ -40,23 +40,23 @@ people learn at school." -- excerpt from the decimal arithmetic specification. * Decimal numbers can be represented exactly. In contrast, numbers like - :const:`1.1` and :const:`2.2` do not have exact representations in binary + ``1.1`` and ``2.2`` do not have exact representations in binary floating point. End users typically would not expect ``1.1 + 2.2`` to display - as :const:`3.3000000000000003` as it does with binary floating point. + as ``3.3000000000000003`` as it does with binary floating point. * The exactness carries over into arithmetic. In decimal floating point, ``0.1 + 0.1 + 0.1 - 0.3`` is exactly equal to zero. In binary floating point, the result - is :const:`5.5511151231257827e-017`. While near to zero, the differences + is ``5.5511151231257827e-017``. While near to zero, the differences prevent reliable equality testing and differences can accumulate. For this reason, decimal is preferred in accounting applications which have strict equality invariants. * The decimal module incorporates a notion of significant places so that ``1.30 - + 1.20`` is :const:`2.50`. The trailing zero is kept to indicate significance. + + 1.20`` is ``2.50``. The trailing zero is kept to indicate significance. This is the customary presentation for monetary applications. For multiplication, the "schoolbook" approach uses all the figures in the - multiplicands. For instance, ``1.3 * 1.2`` gives :const:`1.56` while ``1.30 * - 1.20`` gives :const:`1.5600`. + multiplicands. For instance, ``1.3 * 1.2`` gives ``1.56`` while ``1.30 * + 1.20`` gives ``1.5600``. * Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for @@ -88,8 +88,8 @@ A decimal number is immutable. It has a sign, coefficient digits, and an exponent. To preserve significance, the coefficient digits do not truncate trailing zeros. Decimals also include special values such as -:const:`Infinity`, :const:`-Infinity`, and :const:`NaN`. The standard also -differentiates :const:`-0` from :const:`+0`. +``Infinity``, ``-Infinity``, and ``NaN``. The standard also +differentiates ``-0`` from ``+0``. The context for arithmetic is an environment specifying precision, rounding rules, limits on exponents, flags indicating the results of operations, and trap @@ -114,7 +114,7 @@ .. seealso:: * IBM's General Decimal Arithmetic Specification, `The General Decimal Arithmetic - Specification `_. + Specification `_. .. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -139,8 +139,8 @@ Decimal instances can be constructed from integers, strings, floats, or tuples. Construction from an integer or a float performs an exact conversion of the value of that integer or float. Decimal numbers include special values such as -:const:`NaN` which stands for "Not a number", positive and negative -:const:`Infinity`, and :const:`-0`:: +``NaN`` which stands for "Not a number", positive and negative +``Infinity``, and ``-0``:: >>> getcontext().prec = 28 >>> Decimal(10) @@ -250,7 +250,7 @@ >>> Decimal('10').log10() Decimal('1') -The :meth:`quantize` method rounds a number to a fixed exponent. This method is +The :meth:`~Decimal.quantize` method rounds a number to a fixed exponent. This method is useful for monetary applications that often round results to a fixed number of places: @@ -299,7 +299,7 @@ Contexts also have signal flags for monitoring exceptional conditions encountered during computations. The flags remain set until explicitly cleared, so it is best to clear the flags before each set of monitored computations by -using the :meth:`clear_flags` method. :: +using the :meth:`~Context.clear_flags` method. :: >>> setcontext(ExtendedContext) >>> getcontext().clear_flags() @@ -309,12 +309,12 @@ Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[]) -The *flags* entry shows that the rational approximation to :const:`Pi` was +The *flags* entry shows that the rational approximation to pi was rounded (digits beyond the context precision were thrown away) and that the result is inexact (some of the discarded digits were non-zero). -Individual traps are set using the dictionary in the :attr:`traps` field of a -context: +Individual traps are set using the dictionary in the :attr:`~Context.traps` +attribute of a context: .. doctest:: newcontext @@ -369,7 +369,7 @@ with the fullwidth digits ``'\uff10'`` through ``'\uff19'``. If *value* is a :class:`tuple`, it should have three components, a sign - (:const:`0` for positive or :const:`1` for negative), a :class:`tuple` of + (``0`` for positive or ``1`` for negative), a :class:`tuple` of digits, and an integer exponent. For example, ``Decimal((0, (1, 4, 1, 4), -3))`` returns ``Decimal('1.414')``. @@ -387,7 +387,7 @@ The purpose of the *context* argument is determining what to do if *value* is a malformed string. If the context traps :const:`InvalidOperation`, an exception is raised; otherwise, the constructor returns a new Decimal with the value of - :const:`NaN`. + ``NaN``. Once constructed, :class:`Decimal` objects are immutable. @@ -576,11 +576,11 @@ Alternative constructor that only accepts instances of :class:`float` or :class:`int`. - Note `Decimal.from_float(0.1)` is not the same as `Decimal('0.1')`. + Note ``Decimal.from_float(0.1)`` is not the same as ``Decimal('0.1')``. Since 0.1 is not exactly representable in binary floating point, the value is stored as the nearest representable value which is - `0x1.999999999999ap-4`. That equivalent value in decimal is - `0.1000000000000000055511151231257827021181583404541015625`. + ``0x1.999999999999ap-4``. That equivalent value in decimal is + ``0.1000000000000000055511151231257827021181583404541015625``. .. note:: From Python 3.2 onwards, a :class:`Decimal` instance can also be constructed directly from a :class:`float`. @@ -701,7 +701,7 @@ .. method:: max(other, context=None) Like ``max(self, other)`` except that the context rounding rule is applied - before returning and that :const:`NaN` values are either signaled or + before returning and that ``NaN`` values are either signaled or ignored (depending on the context and whether they are signaling or quiet). @@ -713,7 +713,7 @@ .. method:: min(other, context=None) Like ``min(self, other)`` except that the context rounding rule is applied - before returning and that :const:`NaN` values are either signaled or + before returning and that ``NaN`` values are either signaled or ignored (depending on the context and whether they are signaling or quiet). @@ -744,8 +744,8 @@ .. method:: normalize(context=None) Normalize the number by stripping the rightmost trailing zeros and - converting any result equal to :const:`Decimal('0')` to - :const:`Decimal('0e0')`. Used for producing canonical values for attributes + converting any result equal to ``Decimal('0')`` to + ``Decimal('0e0')``. Used for producing canonical values for attributes of an equivalence class. For example, ``Decimal('32.100')`` and ``Decimal('0.321000e+2')`` both normalize to the equivalent value ``Decimal('32.1')``. @@ -790,7 +790,7 @@ the current thread's context is used. An error is returned whenever the resulting exponent is greater than - :attr:`Emax` or less than :attr:`Etiny`. + :attr:`~Context.Emax` or less than :meth:`~Context.Etiny`. .. method:: radix() @@ -830,7 +830,7 @@ .. method:: same_quantum(other, context=None) Test whether self and other have the same exponent or whether both are - :const:`NaN`. + ``NaN``. This operation is unaffected by context and is quiet: no flags are changed and no rounding is performed. As an exception, the C version may raise @@ -892,11 +892,11 @@ Logical operands ^^^^^^^^^^^^^^^^ -The :meth:`logical_and`, :meth:`logical_invert`, :meth:`logical_or`, -and :meth:`logical_xor` methods expect their arguments to be *logical +The :meth:`~Decimal.logical_and`, :meth:`~Decimal.logical_invert`, :meth:`~Decimal.logical_or`, +and :meth:`~Decimal.logical_xor` methods expect their arguments to be *logical operands*. A *logical operand* is a :class:`Decimal` instance whose exponent and sign are both zero, and whose digits are all either -:const:`0` or :const:`1`. +``0`` or ``1``. .. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -966,7 +966,7 @@ exceptions are not raised during computations). Because the traps are disabled, this context is useful for applications that - prefer to have result value of :const:`NaN` or :const:`Infinity` instead of + prefer to have result value of ``NaN`` or ``Infinity`` instead of raising exceptions. This allows an application to complete a run in the presence of conditions that would otherwise halt the program. @@ -985,8 +985,8 @@ In single threaded environments, it is preferable to not use this context at all. Instead, simply create contexts explicitly as described below. - The default values are :attr:`prec`\ =\ :const:`28`, - :attr:`rounding`\ =\ :const:`ROUND_HALF_EVEN`, + The default values are :attr:`Context.prec`\ =\ ``28``, + :attr:`Context.rounding`\ =\ :const:`ROUND_HALF_EVEN`, and enabled traps for :class:`Overflow`, :class:`InvalidOperation`, and :class:`DivisionByZero`. @@ -1000,7 +1000,7 @@ default values are copied from the :const:`DefaultContext`. If the *flags* field is not specified or is :const:`None`, all flags are cleared. - *prec* is an integer in the range [:const:`1`, :const:`MAX_PREC`] that sets + *prec* is an integer in the range [``1``, :const:`MAX_PREC`] that sets the precision for arithmetic operations in the context. The *rounding* option is one of the constants listed in the section @@ -1010,20 +1010,20 @@ contexts should only set traps and leave the flags clear. The *Emin* and *Emax* fields are integers specifying the outer limits allowable - for exponents. *Emin* must be in the range [:const:`MIN_EMIN`, :const:`0`], - *Emax* in the range [:const:`0`, :const:`MAX_EMAX`]. + for exponents. *Emin* must be in the range [:const:`MIN_EMIN`, ``0``], + *Emax* in the range [``0``, :const:`MAX_EMAX`]. - The *capitals* field is either :const:`0` or :const:`1` (the default). If set to - :const:`1`, exponents are printed with a capital :const:`E`; otherwise, a - lowercase :const:`e` is used: :const:`Decimal('6.02e+23')`. + The *capitals* field is either ``0`` or ``1`` (the default). If set to + ``1``, exponents are printed with a capital ``E``; otherwise, a + lowercase ``e`` is used: ``Decimal('6.02e+23')``. - The *clamp* field is either :const:`0` (the default) or :const:`1`. - If set to :const:`1`, the exponent ``e`` of a :class:`Decimal` + The *clamp* field is either ``0`` (the default) or ``1``. + If set to ``1``, the exponent ``e`` of a :class:`Decimal` instance representable in this context is strictly limited to the range ``Emin - prec + 1 <= e <= Emax - prec + 1``. If *clamp* is - :const:`0` then a weaker condition holds: the adjusted exponent of - the :class:`Decimal` instance is at most ``Emax``. When *clamp* is - :const:`1`, a large normal number will, where possible, have its + ``0`` then a weaker condition holds: the adjusted exponent of + the :class:`Decimal` instance is at most :attr:`~Context.Emax`. When *clamp* is + ``1``, a large normal number will, where possible, have its exponent reduced and a corresponding number of zeros added to its coefficient, in order to fit the exponent constraints; this preserves the value of the number but loses information about @@ -1032,13 +1032,13 @@ >>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999') Decimal('1.23000E+999') - A *clamp* value of :const:`1` allows compatibility with the + A *clamp* value of ``1`` allows compatibility with the fixed-width decimal interchange formats specified in IEEE 754. The :class:`Context` class defines several general purpose methods as well as a large number of methods for doing arithmetic directly in a given context. In addition, for each of the :class:`Decimal` methods described above (with - the exception of the :meth:`adjusted` and :meth:`as_tuple` methods) there is + the exception of the :meth:`~Decimal.adjusted` and :meth:`~Decimal.as_tuple` methods) there is a corresponding :class:`Context` method. For example, for a :class:`Context` instance ``C`` and :class:`Decimal` instance ``x``, ``C.exp(x)`` is equivalent to ``x.exp(context=C)``. Each :class:`Context` method accepts a @@ -1048,11 +1048,11 @@ .. method:: clear_flags() - Resets all of the flags to :const:`0`. + Resets all of the flags to ``0``. .. method:: clear_traps() - Resets all of the traps to :const:`0`. + Resets all of the traps to ``0``. .. versionadded:: 3.3 @@ -1193,7 +1193,7 @@ .. method:: exp(x) - Returns `e ** x`. + Returns ``e ** x``. .. method:: fma(x, y, z) @@ -1467,13 +1467,13 @@ +---------------------+---------------------+-------------------------------+ | | 32-bit | 64-bit | +=====================+=====================+===============================+ -| .. data:: MAX_PREC | :const:`425000000` | :const:`999999999999999999` | +| .. data:: MAX_PREC | ``425000000`` | ``999999999999999999`` | +---------------------+---------------------+-------------------------------+ -| .. data:: MAX_EMAX | :const:`425000000` | :const:`999999999999999999` | +| .. data:: MAX_EMAX | ``425000000`` | ``999999999999999999`` | +---------------------+---------------------+-------------------------------+ -| .. data:: MIN_EMIN | :const:`-425000000` | :const:`-999999999999999999` | +| .. data:: MIN_EMIN | ``-425000000`` | ``-999999999999999999`` | +---------------------+---------------------+-------------------------------+ -| .. data:: MIN_ETINY | :const:`-849999999` | :const:`-1999999999999999997` | +| .. data:: MIN_ETINY | ``-849999999`` | ``-1999999999999999997`` | +---------------------+---------------------+-------------------------------+ @@ -1498,7 +1498,7 @@ .. data:: ROUND_CEILING - Round towards :const:`Infinity`. + Round towards ``Infinity``. .. data:: ROUND_DOWN @@ -1506,7 +1506,7 @@ .. data:: ROUND_FLOOR - Round towards :const:`-Infinity`. + Round towards ``-Infinity``. .. data:: ROUND_HALF_DOWN @@ -1554,7 +1554,7 @@ Altered an exponent to fit representation constraints. Typically, clamping occurs when an exponent falls outside the context's - :attr:`Emin` and :attr:`Emax` limits. If possible, the exponent is reduced to + :attr:`~Context.Emin` and :attr:`~Context.Emax` limits. If possible, the exponent is reduced to fit by adding zeros to the coefficient. @@ -1568,8 +1568,8 @@ Signals the division of a non-infinite number by zero. Can occur with division, modulo division, or when raising a number to a negative - power. If this signal is not trapped, returns :const:`Infinity` or - :const:`-Infinity` with the sign determined by the inputs to the calculation. + power. If this signal is not trapped, returns ``Infinity`` or + ``-Infinity`` with the sign determined by the inputs to the calculation. .. class:: Inexact @@ -1586,7 +1586,7 @@ An invalid operation was performed. Indicates that an operation was requested that does not make sense. If not - trapped, returns :const:`NaN`. Possible causes include:: + trapped, returns ``NaN``. Possible causes include:: Infinity - Infinity 0 * Infinity @@ -1603,10 +1603,10 @@ Numerical overflow. - Indicates the exponent is larger than :attr:`Emax` after rounding has + Indicates the exponent is larger than :attr:`Context.Emax` after rounding has occurred. If not trapped, the result depends on the rounding mode, either pulling inward to the largest representable finite number or rounding outward - to :const:`Infinity`. In either case, :class:`Inexact` and :class:`Rounded` + to ``Infinity``. In either case, :class:`Inexact` and :class:`Rounded` are also signaled. @@ -1615,14 +1615,14 @@ Rounding occurred though possibly no information was lost. Signaled whenever rounding discards digits; even if those digits are zero - (such as rounding :const:`5.00` to :const:`5.0`). If not trapped, returns + (such as rounding ``5.00`` to ``5.0``). If not trapped, returns the result unchanged. This signal is used to detect loss of significant digits. .. class:: Subnormal - Exponent was lower than :attr:`Emin` prior to rounding. + Exponent was lower than :attr:`~Context.Emin` prior to rounding. Occurs when an operation result is subnormal (the exponent is too small). If not trapped, returns the result unchanged. @@ -1680,7 +1680,7 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The use of decimal floating point eliminates decimal representation error -(making it possible to represent :const:`0.1` exactly); however, some operations +(making it possible to represent ``0.1`` exactly); however, some operations can still incur round-off error when non-zero digits exceed the fixed precision. The effects of round-off error can be amplified by the addition or subtraction @@ -1730,8 +1730,8 @@ ^^^^^^^^^^^^^^ The number system for the :mod:`decimal` module provides special values -including :const:`NaN`, :const:`sNaN`, :const:`-Infinity`, :const:`Infinity`, -and two zeros, :const:`+0` and :const:`-0`. +including ``NaN``, ``sNaN``, ``-Infinity``, ``Infinity``, +and two zeros, ``+0`` and ``-0``. Infinities can be constructed directly with: ``Decimal('Infinity')``. Also, they can arise from dividing by zero when the :exc:`DivisionByZero` signal is @@ -1742,30 +1742,30 @@ where they get treated as very large, indeterminate numbers. For instance, adding a constant to infinity gives another infinite result. -Some operations are indeterminate and return :const:`NaN`, or if the +Some operations are indeterminate and return ``NaN``, or if the :exc:`InvalidOperation` signal is trapped, raise an exception. For example, -``0/0`` returns :const:`NaN` which means "not a number". This variety of -:const:`NaN` is quiet and, once created, will flow through other computations -always resulting in another :const:`NaN`. This behavior can be useful for a +``0/0`` returns ``NaN`` which means "not a number". This variety of +``NaN`` is quiet and, once created, will flow through other computations +always resulting in another ``NaN``. This behavior can be useful for a series of computations that occasionally have missing inputs --- it allows the calculation to proceed while flagging specific results as invalid. -A variant is :const:`sNaN` which signals rather than remaining quiet after every +A variant is ``sNaN`` which signals rather than remaining quiet after every operation. This is a useful return value when an invalid result needs to interrupt a calculation for special handling. The behavior of Python's comparison operators can be a little surprising where a -:const:`NaN` is involved. A test for equality where one of the operands is a -quiet or signaling :const:`NaN` always returns :const:`False` (even when doing +``NaN`` is involved. A test for equality where one of the operands is a +quiet or signaling ``NaN`` always returns :const:`False` (even when doing ``Decimal('NaN')==Decimal('NaN')``), while a test for inequality always returns :const:`True`. An attempt to compare two Decimals using any of the ``<``, ``<=``, ``>`` or ``>=`` operators will raise the :exc:`InvalidOperation` signal -if either operand is a :const:`NaN`, and return :const:`False` if this signal is +if either operand is a ``NaN``, and return :const:`False` if this signal is not trapped. Note that the General Decimal Arithmetic specification does not specify the behavior of direct comparisons; these rules for comparisons -involving a :const:`NaN` were taken from the IEEE 854 standard (see Table 3 in -section 5.7). To ensure strict standards-compliance, use the :meth:`compare` -and :meth:`compare-signal` methods instead. +involving a ``NaN`` were taken from the IEEE 854 standard (see Table 3 in +section 5.7). To ensure strict standards-compliance, use the :meth:`~Decimal.compare` +and :meth:`~Decimal.compare_signal` methods instead. The signed zeros can result from calculations that underflow. They keep the sign that would have resulted if the calculation had been carried out to greater @@ -1997,7 +1997,7 @@ places and need to be rounded. Others are not supposed to have excess digits and need to be validated. What methods should be used? -A. The :meth:`quantize` method rounds to a fixed number of decimal places. If +A. The :meth:`~Decimal.quantize` method rounds to a fixed number of decimal places. If the :const:`Inexact` trap is set, it is also useful for validation: >>> TWOPLACES = Decimal(10) ** -2 # same as Decimal('0.01') @@ -2021,7 +2021,7 @@ A. Some operations like addition, subtraction, and multiplication by an integer will automatically preserve fixed point. Others operations, like division and non-integer multiplication, will change the number of decimal places and need to -be followed-up with a :meth:`quantize` step: +be followed-up with a :meth:`~Decimal.quantize` step: >>> a = Decimal('102.72') # Initial fixed-point values >>> b = Decimal('3.17') @@ -2037,7 +2037,7 @@ Decimal('0.03') In developing fixed-point applications, it is convenient to define functions -to handle the :meth:`quantize` step: +to handle the :meth:`~Decimal.quantize` step: >>> def mul(x, y, fp=TWOPLACES): ... return (x * y).quantize(fp) @@ -2049,12 +2049,12 @@ >>> div(b, a) Decimal('0.03') -Q. There are many ways to express the same value. The numbers :const:`200`, -:const:`200.000`, :const:`2E2`, and :const:`.02E+4` all have the same value at +Q. There are many ways to express the same value. The numbers ``200``, +``200.000``, ``2E2``, and ``.02E+4`` all have the same value at various precisions. Is there a way to transform them to a single recognizable canonical value? -A. The :meth:`normalize` method maps all equivalent values to a single +A. The :meth:`~Decimal.normalize` method maps all equivalent values to a single representative: >>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split()) @@ -2066,7 +2066,7 @@ A. For some values, exponential notation is the only way to express the number of significant places in the coefficient. For example, expressing -:const:`5.0E+3` as :const:`5000` keeps the value constant but cannot show the +``5.0E+3`` as ``5000`` keeps the value constant but cannot show the original's two-place significance. If an application does not care about tracking significance, it is easy to @@ -2142,12 +2142,12 @@ `_ for very large numbers. -The context must be adapted for exact arbitrary precision arithmetic. :attr:`Emin` -and :attr:`Emax` should always be set to the maximum values, :attr:`clamp` -should always be 0 (the default). Setting :attr:`prec` requires some care. +The context must be adapted for exact arbitrary precision arithmetic. :attr:`~Context.Emin` +and :attr:`~Context.Emax` should always be set to the maximum values, :attr:`~Context.clamp` +should always be 0 (the default). Setting :attr:`~Context.prec` requires some care. The easiest approach for trying out bignum arithmetic is to use the maximum -value for :attr:`prec` as well [#]_:: +value for :attr:`~Context.prec` as well [#]_:: >>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN)) >>> x = Decimal(2) ** 256 @@ -2164,7 +2164,7 @@ MemoryError On systems with overallocation (e.g. Linux), a more sophisticated approach is to -adjust :attr:`prec` to the amount of available RAM. Suppose that you have 8GB of +adjust :attr:`~Context.prec` to the amount of available RAM. Suppose that you have 8GB of RAM and expect 10 simultaneous operands using a maximum of 500MB each:: >>> import sys diff -Nru python3.10-3.10.7/Doc/library/dis.rst python3.10-3.10.12/Doc/library/dis.rst --- python3.10-3.10.7/Doc/library/dis.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/dis.rst 2023-06-06 22:30:33.000000000 +0000 @@ -24,6 +24,10 @@ Use 2 bytes for each instruction. Previously the number of bytes varied by instruction. + .. versionchanged:: 3.10 + The argument of jump, exception handling and loop instructions is now + the instruction offset rather than the byte offset. + Example: Given the function :func:`myfunc`:: diff -Nru python3.10-3.10.7/Doc/library/doctest.rst python3.10-3.10.12/Doc/library/doctest.rst --- python3.10-3.10.7/Doc/library/doctest.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/doctest.rst 2023-06-06 22:30:33.000000000 +0000 @@ -697,10 +697,10 @@ .. productionlist:: doctest directive: "#" "doctest:" `directive_options` - directive_options: `directive_option` ("," `directive_option`)\* + directive_options: `directive_option` ("," `directive_option`)* directive_option: `on_or_off` `directive_option_name` - on_or_off: "+" \| "-" - directive_option_name: "DONT_ACCEPT_BLANKLINE" \| "NORMALIZE_WHITESPACE" \| ... + on_or_off: "+" | "-" + directive_option_name: "DONT_ACCEPT_BLANKLINE" | "NORMALIZE_WHITESPACE" | ... Whitespace is not allowed between the ``+`` or ``-`` and the directive option name. The directive option name can be any of the option flag names explained diff -Nru python3.10-3.10.7/Doc/library/email.compat32-message.rst python3.10-3.10.12/Doc/library/email.compat32-message.rst --- python3.10-3.10.7/Doc/library/email.compat32-message.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/email.compat32-message.rst 2023-06-06 22:30:33.000000000 +0000 @@ -83,7 +83,7 @@ Note that this method is provided as a convenience and may not always format the message the way you want. For example, by default it does not do the mangling of lines that begin with ``From`` that is - required by the unix mbox format. For more flexibility, instantiate a + required by the Unix mbox format. For more flexibility, instantiate a :class:`~email.generator.Generator` instance and use its :meth:`~email.generator.Generator.flatten` method directly. For example:: @@ -125,7 +125,7 @@ Note that this method is provided as a convenience and may not always format the message the way you want. For example, by default it does not do the mangling of lines that begin with ``From`` that is - required by the unix mbox format. For more flexibility, instantiate a + required by the Unix mbox format. For more flexibility, instantiate a :class:`~email.generator.BytesGenerator` instance and use its :meth:`~email.generator.BytesGenerator.flatten` method directly. For example:: @@ -298,7 +298,7 @@ In a model generated from bytes, any header values that (in contravention of the RFCs) contain non-ASCII bytes will, when retrieved through this interface, be represented as :class:`~email.header.Header` objects with - a charset of `unknown-8bit`. + a charset of ``unknown-8bit``. .. method:: __len__() diff -Nru python3.10-3.10.7/Doc/library/email.errors.rst python3.10-3.10.12/Doc/library/email.errors.rst --- python3.10-3.10.7/Doc/library/email.errors.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/email.errors.rst 2023-06-06 22:30:33.000000000 +0000 @@ -114,4 +114,4 @@ a multiple of 4). The encoded block was kept as-is. * :class:`InvalidDateDefect` -- When decoding an invalid or unparsable date field. - The original value is kept as-is. \ No newline at end of file + The original value is kept as-is. diff -Nru python3.10-3.10.7/Doc/library/email.generator.rst python3.10-3.10.12/Doc/library/email.generator.rst --- python3.10-3.10.7/Doc/library/email.generator.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/email.generator.rst 2023-06-06 22:30:33.000000000 +0000 @@ -55,7 +55,7 @@ defaults to the value of the :attr:`~email.policy.Policy.mangle_from_` setting of the *policy* (which is ``True`` for the :data:`~email.policy.compat32` policy and ``False`` for all others). - *mangle_from_* is intended for use when messages are stored in unix mbox + *mangle_from_* is intended for use when messages are stored in Unix mbox format (see :mod:`mailbox` and `WHY THE CONTENT-LENGTH FORMAT IS BAD `_). @@ -156,7 +156,7 @@ defaults to the value of the :attr:`~email.policy.Policy.mangle_from_` setting of the *policy* (which is ``True`` for the :data:`~email.policy.compat32` policy and ``False`` for all others). - *mangle_from_* is intended for use when messages are stored in unix mbox + *mangle_from_* is intended for use when messages are stored in Unix mbox format (see :mod:`mailbox` and `WHY THE CONTENT-LENGTH FORMAT IS BAD `_). diff -Nru python3.10-3.10.7/Doc/library/email.headerregistry.rst python3.10-3.10.12/Doc/library/email.headerregistry.rst --- python3.10-3.10.7/Doc/library/email.headerregistry.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/email.headerregistry.rst 2023-06-06 22:30:33.000000000 +0000 @@ -153,7 +153,7 @@ specified as ``-0000`` (indicating it is in UTC but contains no information about the source timezone), then :attr:`.datetime` will be a naive :class:`~datetime.datetime`. If a specific timezone offset is - found (including `+0000`), then :attr:`.datetime` will contain an aware + found (including ``+0000``), then :attr:`.datetime` will contain an aware ``datetime`` that uses :class:`datetime.timezone` to record the timezone offset. diff -Nru python3.10-3.10.7/Doc/library/email.mime.rst python3.10-3.10.12/Doc/library/email.mime.rst --- python3.10-3.10.7/Doc/library/email.mime.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/email.mime.rst 2023-06-06 22:30:33.000000000 +0000 @@ -114,9 +114,9 @@ A subclass of :class:`~email.mime.nonmultipart.MIMENonMultipart`, the :class:`MIMEApplication` class is used to represent MIME message objects of - major type :mimetype:`application`. *_data* is a string containing the raw - byte data. Optional *_subtype* specifies the MIME subtype and defaults to - :mimetype:`octet-stream`. + major type :mimetype:`application`. *_data* contains the bytes for the raw + application data. Optional *_subtype* specifies the MIME subtype and defaults + to :mimetype:`octet-stream`. Optional *_encoder* is a callable (i.e. function) which will perform the actual encoding of the data for transport. This callable takes one argument, which is @@ -145,7 +145,7 @@ A subclass of :class:`~email.mime.nonmultipart.MIMENonMultipart`, the :class:`MIMEAudio` class is used to create MIME message objects of major type - :mimetype:`audio`. *_audiodata* is a string containing the raw audio data. If + :mimetype:`audio`. *_audiodata* contains the bytes for the raw audio data. If this data can be decoded by the standard Python module :mod:`sndhdr`, then the subtype will be automatically included in the :mailheader:`Content-Type` header. Otherwise you can explicitly specify the audio subtype via the *_subtype* @@ -179,7 +179,7 @@ A subclass of :class:`~email.mime.nonmultipart.MIMENonMultipart`, the :class:`MIMEImage` class is used to create MIME message objects of major type - :mimetype:`image`. *_imagedata* is a string containing the raw image data. If + :mimetype:`image`. *_imagedata* contains the bytes for the raw image data. If this data can be decoded by the standard Python module :mod:`imghdr`, then the subtype will be automatically included in the :mailheader:`Content-Type` header. Otherwise you can explicitly specify the image subtype via the *_subtype* diff -Nru python3.10-3.10.7/Doc/library/ensurepip.rst python3.10-3.10.12/Doc/library/ensurepip.rst --- python3.10-3.10.7/Doc/library/ensurepip.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/ensurepip.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,8 @@ .. versionadded:: 3.4 +**Source code:** :source:`Lib/ensurepip` + -------------- The :mod:`ensurepip` package provides support for bootstrapping the ``pip`` diff -Nru python3.10-3.10.7/Doc/library/faulthandler.rst python3.10-3.10.12/Doc/library/faulthandler.rst --- python3.10-3.10.7/Doc/library/faulthandler.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/faulthandler.rst 2023-06-06 22:30:33.000000000 +0000 @@ -43,6 +43,13 @@ The :ref:`Python Development Mode ` calls :func:`faulthandler.enable` at Python startup. +.. seealso:: + + Module :mod:`pdb` + Interactive source code debugger for Python programs. + + Module :mod:`traceback` + Standard interface to extract, format and print stack traces of Python programs. Dumping the traceback --------------------- @@ -52,6 +59,8 @@ Dump the tracebacks of all threads into *file*. If *all_threads* is ``False``, dump only the current thread. + .. seealso:: :func:`traceback.print_tb`, which can be used to print a traceback object. + .. versionchanged:: 3.5 Added support for passing file descriptor to this function. @@ -178,4 +187,3 @@ File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at File "", line 1 in Segmentation fault - diff -Nru python3.10-3.10.7/Doc/library/fractions.rst python3.10-3.10.12/Doc/library/fractions.rst --- python3.10-3.10.7/Doc/library/fractions.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/fractions.rst 2023-06-06 22:30:33.000000000 +0000 @@ -76,7 +76,7 @@ The :class:`Fraction` class inherits from the abstract base class :class:`numbers.Rational`, and implements all of the methods and - operations from that class. :class:`Fraction` instances are hashable, + operations from that class. :class:`Fraction` instances are :term:`hashable`, and should be treated as immutable. In addition, :class:`Fraction` has the following properties and methods: diff -Nru python3.10-3.10.7/Doc/library/functions.rst python3.10-3.10.12/Doc/library/functions.rst --- python3.10-3.10.7/Doc/library/functions.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/functions.rst 2023-06-06 22:30:33.000000000 +0000 @@ -392,6 +392,7 @@ string. The string must be the name of one of the object's attributes. The function deletes the named attribute, provided the object allows it. For example, ``delattr(x, 'foobar')`` is equivalent to ``del x.foobar``. + *name* need not be a Python identifier (see :func:`setattr`). .. _func-dict: @@ -627,20 +628,23 @@ sign may be ``'+'`` or ``'-'``; a ``'+'`` sign has no effect on the value produced. The argument may also be a string representing a NaN (not-a-number), or positive or negative infinity. More precisely, the - input must conform to the following grammar after leading and trailing - whitespace characters are removed: + input must conform to the ``floatvalue`` production rule in the following + grammar, after leading and trailing whitespace characters are removed: .. productionlist:: float sign: "+" | "-" infinity: "Infinity" | "inf" nan: "nan" - numeric_value: `floatnumber` | `infinity` | `nan` - numeric_string: [`sign`] `numeric_value` - - Here ``floatnumber`` is the form of a Python floating-point literal, - described in :ref:`floating`. Case is not significant, so, for example, - "inf", "Inf", "INFINITY", and "iNfINity" are all acceptable spellings for - positive infinity. + digitpart: `digit` (["_"] `digit`)* + number: [`digitpart`] "." `digitpart` | `digitpart` ["."] + exponent: ("e" | "E") ["+" | "-"] `digitpart` + floatnumber: number [`exponent`] + floatvalue: [`sign`] (`floatnumber` | `infinity` | `nan`) + + Here ``digit`` is a Unicode decimal digit (character in the Unicode general + category ``Nd``). Case is not significant, so, for example, "inf", "Inf", + "INFINITY", and "iNfINity" are all acceptable spellings for positive + infinity. Otherwise, if the argument is an integer or a floating point number, a floating point number with the same value (within Python's floating point @@ -724,6 +728,7 @@ value of that attribute. For example, ``getattr(x, 'foobar')`` is equivalent to ``x.foobar``. If the named attribute does not exist, *default* is returned if provided, otherwise :exc:`AttributeError` is raised. + *name* need not be a Python identifier (see :func:`setattr`). .. note:: @@ -863,17 +868,21 @@ For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, - :class:`bytes`, or :class:`bytearray` instance representing an :ref:`integer - literal ` in radix *base*. Optionally, the literal can be - preceded by ``+`` or ``-`` (with no space in between) and surrounded by - whitespace. A base-n literal consists of the digits 0 to n-1, with ``a`` - to ``z`` (or ``A`` to ``Z``) having - values 10 to 35. The default *base* is 10. The allowed values are 0 and 2--36. - Base-2, -8, and -16 literals can be optionally prefixed with ``0b``/``0B``, - ``0o``/``0O``, or ``0x``/``0X``, as with integer literals in code. Base 0 - means to interpret exactly as a code literal, so that the actual base is 2, - 8, 10, or 16, and so that ``int('010', 0)`` is not legal, while - ``int('010')`` is, as well as ``int('010', 8)``. + :class:`bytes`, or :class:`bytearray` instance representing an integer + in radix *base*. Optionally, the string can be preceded by ``+`` or ``-`` + (with no space in between), have leading zeros, be surrounded by whitespace, + and have single underscores interspersed between digits. + + A base-n integer string contains digits, each representing a value from 0 to + n-1. The values 0--9 can be represented by any Unicode decimal digit. The + values 10--35 can be represented by ``a`` to ``z`` (or ``A`` to ``Z``). The + default *base* is 10. The allowed bases are 0 and 2--36. Base-2, -8, and -16 + strings can be optionally prefixed with ``0b``/``0B``, ``0o``/``0O``, or + ``0x``/``0X``, as with integer literals in code. For base 0, the string is + interpreted in a similar way to an :ref:`integer literal in code `, + in that the actual base is 2, 8, 10, or 16 as determined by the prefix. Base + 0 also disallows leading zeros: ``int('010', 0)`` is not legal, while + ``int('010')`` and ``int('010', 8)`` are. The integer type is described in :ref:`typesnumeric`. @@ -1242,8 +1251,8 @@ .. _open-newline-parameter: - *newline* controls how :term:`universal newlines` mode works (it only - applies to text mode). It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and + *newline* determines how to parse newline characters from the stream. + It can be ``None``, ``''``, ``'\n'``, ``'\r'``, and ``'\r\n'``. It works as follows: * When reading input from the stream, if *newline* is ``None``, universal @@ -1397,7 +1406,7 @@ supported. -.. function:: print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) +.. function:: print(*objects, sep=' ', end='\n', file=None, flush=False) Print *objects* to the text stream *file*, separated by *sep* and followed by *end*. *sep*, *end*, *file*, and *flush*, if present, must be given as keyword @@ -1414,8 +1423,9 @@ arguments are converted to text strings, :func:`print` cannot be used with binary mode file objects. For these, use ``file.write(...)`` instead. - Whether the output is buffered is usually determined by *file*, but if the - *flush* keyword argument is true, the stream is forcibly flushed. + Output buffering is usually determined by *file*. + However, if *flush* is true, the stream is forcibly flushed. + .. versionchanged:: 3.3 Added the *flush* keyword argument. @@ -1577,6 +1587,12 @@ object allows it. For example, ``setattr(x, 'foobar', 123)`` is equivalent to ``x.foobar = 123``. + *name* need not be a Python identifier as defined in :ref:`identifiers` + unless the object chooses to enforce that, for example in a custom + :meth:`~object.__getattribute__` or via :attr:`~object.__slots__`. + An attribute whose name is not an identifier will not be accessible using + the dot notation, but is accessible through :func:`getattr` etc.. + .. note:: Since :ref:`private name mangling ` happens at @@ -1883,14 +1899,24 @@ >>> list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True)) [('a', 1), ('b', 2), ('c', 3)] - Unlike the default behavior, it checks that the lengths of iterables are - identical, raising a :exc:`ValueError` if they aren't: + Unlike the default behavior, it raises a :exc:`ValueError` if one iterable + is exhausted before the others: - >>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True)) + >>> for item in zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True): # doctest: +SKIP + ... print(item) + ... + (0, 'fee') + (1, 'fi') + (2, 'fo') Traceback (most recent call last): ... ValueError: zip() argument 2 is longer than argument 1 + .. + This doctest is disabled because doctest does not support capturing + output and exceptions in the same code unit. + https://github.com/python/cpython/issues/65382 + Without the ``strict=True`` argument, any bug that results in iterables of different lengths will be silenced, possibly manifesting as a hard-to-find bug in another part of the program. diff -Nru python3.10-3.10.7/Doc/library/functools.rst python3.10-3.10.12/Doc/library/functools.rst --- python3.10-3.10.7/Doc/library/functools.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/functools.rst 2023-06-06 22:30:33.000000000 +0000 @@ -141,7 +141,7 @@ function is periodically called with the same arguments. Since a dictionary is used to cache results, the positional and keyword - arguments to the function must be hashable. + arguments to the function must be :term:`hashable`. Distinct argument patterns may be considered to be distinct calls with separate cache entries. For example, `f(a=1, b=2)` and `f(b=2, a=1)` diff -Nru python3.10-3.10.7/Doc/library/graphlib.rst python3.10-3.10.12/Doc/library/graphlib.rst --- python3.10-3.10.7/Doc/library/graphlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/graphlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -17,7 +17,7 @@ .. class:: TopologicalSorter(graph=None) - Provides functionality to topologically sort a graph of hashable nodes. + Provides functionality to topologically sort a graph of :term:`hashable` nodes. A topological order is a linear ordering of the vertices in a graph such that for every directed edge u -> v from vertex u to vertex v, vertex u comes @@ -85,7 +85,7 @@ .. method:: add(node, *predecessors) Add a new node and its predecessors to the graph. Both the *node* and all - elements in *predecessors* must be hashable. + elements in *predecessors* must be :term:`hashable`. If called multiple times with the same node argument, the set of dependencies will be the union of all dependencies passed in. diff -Nru python3.10-3.10.7/Doc/library/gzip.rst python3.10-3.10.12/Doc/library/gzip.rst --- python3.10-3.10.7/Doc/library/gzip.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/gzip.rst 2023-06-06 22:30:33.000000000 +0000 @@ -143,6 +143,12 @@ :func:`time.time` and the :attr:`~os.stat_result.st_mtime` attribute of the object returned by :func:`os.stat`. + .. attribute:: name + + The path to the gzip file on disk, as a :class:`str` or :class:`bytes`. + Equivalent to the output of :func:`os.fspath` on the original input path, + with no other normalization, resolution or expansion. + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added, along with the *mtime* constructor argument and :attr:`mtime` attribute. diff -Nru python3.10-3.10.7/Doc/library/hashlib.rst python3.10-3.10.12/Doc/library/hashlib.rst --- python3.10-3.10.7/Doc/library/hashlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/hashlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -391,7 +391,7 @@ BLAKE2s, 0 in sequential mode). * *last_node*: boolean indicating whether the processed node is the last - one (`False` for sequential mode). + one (``False`` for sequential mode). .. figure:: hashlib-blake2-tree.png :alt: Explanation of tree mode parameters. diff -Nru python3.10-3.10.7/Doc/library/http.client.rst python3.10-3.10.12/Doc/library/http.client.rst --- python3.10-3.10.7/Doc/library/http.client.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/http.client.rst 2023-06-06 22:30:33.000000000 +0000 @@ -14,7 +14,7 @@ -------------- -This module defines classes which implement the client side of the HTTP and +This module defines classes that implement the client side of the HTTP and HTTPS protocols. It is normally not used directly --- the module :mod:`urllib.request` uses it to handle URLs that use HTTP and HTTPS. @@ -35,7 +35,7 @@ blocksize=8192) An :class:`HTTPConnection` instance represents one transaction with an HTTP - server. It should be instantiated passing it a host and optional port + server. It should be instantiated by passing it a host and optional port number. If no port number is passed, the port is extracted from the host string if it has the form ``host:port``, else the default HTTP port (80) is used. If the optional *timeout* parameter is given, blocking @@ -59,7 +59,7 @@ .. versionchanged:: 3.4 The *strict* parameter was removed. HTTP 0.9-style "Simple Responses" are - not longer supported. + no longer supported. .. versionchanged:: 3.7 *blocksize* parameter was added. @@ -472,7 +472,7 @@ Return the value of the header *name*, or *default* if there is no header matching *name*. If there is more than one header with the name *name*, - return all of the values joined by ', '. If 'default' is any iterable other + return all of the values joined by ', '. If *default* is any iterable other than a single string, its elements are similarly returned joined by commas. .. method:: HTTPResponse.getheaders() @@ -528,7 +528,7 @@ .. deprecated:: 3.9 Deprecated in favor of :attr:`~HTTPResponse.headers`. -.. method:: HTTPResponse.getstatus() +.. method:: HTTPResponse.getcode() .. deprecated:: 3.9 Deprecated in favor of :attr:`~HTTPResponse.status`. @@ -576,7 +576,7 @@ >>> data == b'' True -Here is an example session that shows how to ``POST`` requests:: +Here is an example session that uses the ``POST`` method:: >>> import http.client, urllib.parse >>> params = urllib.parse.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'}) @@ -592,14 +592,13 @@ b'Redirecting to https://bugs.python.org/issue12524' >>> conn.close() -Client side ``HTTP PUT`` requests are very similar to ``POST`` requests. The -difference lies only the server side where HTTP server will allow resources to -be created via ``PUT`` request. It should be noted that custom HTTP methods +Client side HTTP ``PUT`` requests are very similar to ``POST`` requests. The +difference lies only on the server side where HTTP servers will allow resources to +be created via ``PUT`` requests. It should be noted that custom HTTP methods are also handled in :class:`urllib.request.Request` by setting the appropriate -method attribute. Here is an example session that shows how to send a ``PUT`` -request using http.client:: +method attribute. Here is an example session that uses the ``PUT`` method:: - >>> # This creates an HTTP message + >>> # This creates an HTTP request >>> # with the content of BODY as the enclosed representation >>> # for the resource http://localhost:8080/file ... diff -Nru python3.10-3.10.7/Doc/library/http.cookiejar.rst python3.10-3.10.12/Doc/library/http.cookiejar.rst --- python3.10-3.10.7/Doc/library/http.cookiejar.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/http.cookiejar.rst 2023-06-06 22:30:33.000000000 +0000 @@ -61,7 +61,7 @@ responsible for storing and retrieving cookies from a file or database. -.. class:: FileCookieJar(filename, delayload=None, policy=None) +.. class:: FileCookieJar(filename=None, delayload=None, policy=None) *policy* is an object implementing the :class:`CookiePolicy` interface. For the other arguments, see the documentation for the corresponding attributes. @@ -71,6 +71,8 @@ :meth:`load` or :meth:`revert` method is called. Subclasses of this class are documented in section :ref:`file-cookie-jar-classes`. + This should not be initialized directly – use its subclasses below instead. + .. versionchanged:: 3.8 The filename parameter supports a :term:`path-like object`. @@ -317,11 +319,11 @@ The following :class:`CookieJar` subclasses are provided for reading and writing. -.. class:: MozillaCookieJar(filename, delayload=None, policy=None) +.. class:: MozillaCookieJar(filename=None, delayload=None, policy=None) A :class:`FileCookieJar` that can load from and save cookies to disk in the - Mozilla ``cookies.txt`` file format (which is also used by the Lynx and Netscape - browsers). + Mozilla ``cookies.txt`` file format (which is also used by curl and the Lynx + and Netscape browsers). .. note:: @@ -338,7 +340,7 @@ Mozilla. -.. class:: LWPCookieJar(filename, delayload=None, policy=None) +.. class:: LWPCookieJar(filename=None, delayload=None, policy=None) A :class:`FileCookieJar` that can load from and save cookies to disk in format compatible with the libwww-perl library's ``Set-Cookie3`` file format. This is diff -Nru python3.10-3.10.7/Doc/library/http.server.rst python3.10-3.10.12/Doc/library/http.server.rst --- python3.10-3.10.7/Doc/library/http.server.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/http.server.rst 2023-06-06 22:30:33.000000000 +0000 @@ -388,8 +388,8 @@ contents of the file are output. If the file's MIME type starts with ``text/`` the file is opened in text mode; otherwise binary mode is used. - For example usage, see the implementation of the :func:`test` function - invocation in the :mod:`http.server` module. + For example usage, see the implementation of the ``test`` function + in :source:`Lib/http/server.py`. .. versionchanged:: 3.7 Support of the ``'If-Modified-Since'`` header. @@ -499,3 +499,12 @@ :class:`SimpleHTTPRequestHandler` will follow symbolic links when handling requests, this makes it possible for files outside of the specified directory to be served. + +Earlier versions of Python did not scrub control characters from the +log messages emitted to stderr from ``python -m http.server`` or the +default :class:`BaseHTTPRequestHandler` ``.log_message`` +implementation. This could allow remote clients connecting to your +server to send nefarious control codes to your terminal. + +.. versionadded:: 3.10.9 + Control characters are scrubbed in stderr logs. diff -Nru python3.10-3.10.7/Doc/library/importlib.metadata.rst python3.10-3.10.12/Doc/library/importlib.metadata.rst --- python3.10-3.10.7/Doc/library/importlib.metadata.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/importlib.metadata.rst 2023-06-06 22:30:33.000000000 +0000 @@ -41,7 +41,7 @@ .. code-block:: shell-session - $ python3 -m venv example + $ python -m venv example $ source example/bin/activate (example) $ pip install wheel diff -Nru python3.10-3.10.7/Doc/library/importlib.rst python3.10-3.10.12/Doc/library/importlib.rst --- python3.10-3.10.7/Doc/library/importlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/importlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -809,9 +809,12 @@ .. class:: Traversable - An object with a subset of pathlib.Path methods suitable for + An object with a subset of :class:`pathlib.Path` methods suitable for traversing directories and opening files. + For a representation of the object on the file-system, use + :meth:`importlib.resources.as_file`. + .. versionadded:: 3.9 .. abstractmethod:: name() @@ -854,13 +857,15 @@ Read contents of self as text. + Note: In Python 3.11 and later, this class is found in ``importlib.resources.abc``. + .. class:: TraversableResources An abstract base class for resource readers capable of serving the ``files`` interface. Subclasses ResourceReader and provides concrete implementations of the ResourceReader's abstract - methods. Therefore, any loader supplying TraversableReader + methods. Therefore, any loader supplying TraversableResources also supplies ResourceReader. Loaders that wish to support resource reading are expected to @@ -868,6 +873,8 @@ .. versionadded:: 3.9 + Note: In Python 3.11 and later, this class is found in ``importlib.resources.abc``. + :mod:`importlib.resources` -- Resources --------------------------------------- @@ -930,7 +937,7 @@ .. function:: files(package) - Returns an :class:`importlib.resources.abc.Traversable` object + Returns an :class:`importlib.abc.Traversable` object representing the resource container for the package (think directory) and its resources (think files). A Traversable may contain other containers (think subdirectories). @@ -942,7 +949,7 @@ .. function:: as_file(traversable) - Given a :class:`importlib.resources.abc.Traversable` object representing + Given a :class:`importlib.abc.Traversable` object representing a file, typically from :func:`importlib.resources.files`, return a context manager for use in a :keyword:`with` statement. The context manager provides a :class:`pathlib.Path` object. @@ -1718,7 +1725,7 @@ .. classmethod:: factory(loader) - A static method which returns a callable that creates a lazy loader. This + A class method which returns a callable that creates a lazy loader. This is meant to be used in situations where the loader is passed by class instead of by instance. :: diff -Nru python3.10-3.10.7/Doc/library/inspect.rst python3.10-3.10.12/Doc/library/inspect.rst --- python3.10-3.10.7/Doc/library/inspect.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/inspect.rst 2023-06-06 22:30:33.000000000 +0000 @@ -526,6 +526,8 @@ object and the line number indicates where in the original source file the first line of code was found. An :exc:`OSError` is raised if the source code cannot be retrieved. + A :exc:`TypeError` is raised if the object is a built-in module, class, or + function. .. versionchanged:: 3.3 :exc:`OSError` is raised instead of :exc:`IOError`, now an alias of the @@ -538,6 +540,8 @@ class, method, function, traceback, frame, or code object. The source code is returned as a single string. An :exc:`OSError` is raised if the source code cannot be retrieved. + A :exc:`TypeError` is raised if the object is a built-in module, class, or + function. .. versionchanged:: 3.3 :exc:`OSError` is raised instead of :exc:`IOError`, now an alias of the @@ -641,7 +645,7 @@ modified copy. .. versionchanged:: 3.5 - Signature objects are picklable and hashable. + Signature objects are picklable and :term:`hashable`. .. attribute:: Signature.empty @@ -719,7 +723,7 @@ you can use :meth:`Parameter.replace` to create a modified copy. .. versionchanged:: 3.5 - Parameter objects are picklable and hashable. + Parameter objects are picklable and :term:`hashable`. .. attribute:: Parameter.empty @@ -753,8 +757,9 @@ .. attribute:: Parameter.kind - Describes how argument values are bound to the parameter. Possible values - (accessible via :class:`Parameter`, like ``Parameter.KEYWORD_ONLY``): + Describes how argument values are bound to the parameter. The possible + values are accessible via :class:`Parameter` (like ``Parameter.KEYWORD_ONLY``), + and support comparison and ordering, in the following order: .. tabularcolumns:: |l|L| diff -Nru python3.10-3.10.7/Doc/library/io.rst python3.10-3.10.12/Doc/library/io.rst --- python3.10-3.10.7/Doc/library/io.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/io.rst 2023-06-06 22:30:33.000000000 +0000 @@ -265,7 +265,7 @@ The :class:`BufferedIOBase` ABC extends :class:`IOBase`. It deals with buffering on a raw binary stream (:class:`RawIOBase`). Its subclasses, :class:`BufferedWriter`, :class:`BufferedReader`, and :class:`BufferedRWPair` -buffer raw binary streams that are readable, writable, and both readable and writable, +buffer raw binary streams that are writable, readable, and both readable and writable, respectively. :class:`BufferedRandom` provides a buffered interface to seekable streams. Another :class:`BufferedIOBase` subclass, :class:`BytesIO`, is a stream of in-memory bytes. @@ -1015,8 +1015,8 @@ .. versionadded:: 3.7 - .. method:: reconfigure(*[, encoding][, errors][, newline][, \ - line_buffering][, write_through]) + .. method:: reconfigure(*, encoding=None, errors=None, newline=None, \ + line_buffering=None, write_through=None) Reconfigure this text stream using new settings for *encoding*, *errors*, *newline*, *line_buffering* and *write_through*. diff -Nru python3.10-3.10.7/Doc/library/json.rst python3.10-3.10.12/Doc/library/json.rst --- python3.10-3.10.7/Doc/library/json.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/json.rst 2023-06-06 22:30:33.000000000 +0000 @@ -120,7 +120,7 @@ .. note:: - JSON is a subset of `YAML `_ 1.2. The JSON produced by + JSON is a subset of `YAML `_ 1.2. The JSON produced by this module's default settings (in particular, the default *separators* value) is also a subset of YAML 1.0 and 1.1. This module can thus also be used as a YAML serializer. diff -Nru python3.10-3.10.7/Doc/library/locale.rst python3.10-3.10.12/Doc/library/locale.rst --- python3.10-3.10.7/Doc/library/locale.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/locale.rst 2023-06-06 22:30:33.000000000 +0000 @@ -147,12 +147,12 @@ | ``CHAR_MAX`` | Nothing is specified in this locale. | +--------------+-----------------------------------------+ - The function sets temporarily the ``LC_CTYPE`` locale to the ``LC_NUMERIC`` + The function temporarily sets the ``LC_CTYPE`` locale to the ``LC_NUMERIC`` locale or the ``LC_MONETARY`` locale if locales are different and numeric or monetary strings are non-ASCII. This temporary change affects other threads. .. versionchanged:: 3.7 - The function now sets temporarily the ``LC_CTYPE`` locale to the + The function now temporarily sets the ``LC_CTYPE`` locale to the ``LC_NUMERIC`` locale in some cases. @@ -227,16 +227,18 @@ Get a regular expression that can be used with the regex function to recognize a positive response to a yes/no question. - .. note:: - - The expression is in the syntax suitable for the :c:func:`regex` function - from the C library, which might differ from the syntax used in :mod:`re`. - .. data:: NOEXPR Get a regular expression that can be used with the regex(3) function to recognize a negative response to a yes/no question. + .. note:: + + The regular expressions for :const:`YESEXPR` and + :const:`NOEXPR` use syntax suitable for the + :c:func:`regex` function from the C library, which might + differ from the syntax used in :mod:`re`. + .. data:: CRNCYSTR Get the currency symbol, preceded by "-" if the symbol should appear before @@ -375,7 +377,7 @@ Formats a number *val* according to the current :const:`LC_NUMERIC` setting. The format follows the conventions of the ``%`` operator. For floating point - values, the decimal point is modified if appropriate. If *grouping* is true, + values, the decimal point is modified if appropriate. If *grouping* is ``True``, also takes the grouping into account. If *monetary* is true, the conversion uses monetary thousands separator and @@ -405,12 +407,14 @@ Formats a number *val* according to the current :const:`LC_MONETARY` settings. The returned string includes the currency symbol if *symbol* is true, which is - the default. If *grouping* is true (which is not the default), grouping is done - with the value. If *international* is true (which is not the default), the + the default. If *grouping* is ``True`` (which is not the default), grouping is done + with the value. If *international* is ``True`` (which is not the default), the international currency symbol is used. - Note that this function will not work with the 'C' locale, so you have to set a - locale via :func:`setlocale` first. + .. note:: + + This function will not work with the 'C' locale, so you have to set a + locale via :func:`setlocale` first. .. function:: str(float) @@ -480,6 +484,9 @@ system, like those returned by :func:`os.strerror` might be affected by this category. + This value may not be available on operating systems not conforming to the + POSIX standard, most notably Windows. + .. data:: LC_NUMERIC @@ -597,4 +604,3 @@ :c:func:`gettext` or :c:func:`dcgettext`. For these applications, it may be necessary to bind the text domain, so that the libraries can properly locate their message catalogs. - diff -Nru python3.10-3.10.7/Doc/library/logging.config.rst python3.10-3.10.12/Doc/library/logging.config.rst --- python3.10-3.10.7/Doc/library/logging.config.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/logging.config.rst 2023-06-06 22:30:33.000000000 +0000 @@ -519,6 +519,11 @@ my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42) +.. warning:: The values for keys such as ``bar``, ``spam`` and ``answer`` in + the above example should not be configuration dictionaries or references such + as ``cfg://foo`` or ``ext://bar``, because they will not be processed by the + configuration machinery, but passed to the callable as-is. + The key ``'()'`` has been used as the special key because it is not a valid keyword parameter name, and so will not clash with the names of the keyword arguments used in the call. The ``'()'`` also serves as a @@ -543,6 +548,34 @@ the returned formatter will have attribute ``foo`` set to ``'bar'`` and attribute ``baz`` set to ``'bozz'``. +.. warning:: The values for attributes such as ``foo`` and ``baz`` in + the above example should not be configuration dictionaries or references such + as ``cfg://foo`` or ``ext://bar``, because they will not be processed by the + configuration machinery, but set as attribute values as-is. + + +.. _handler-config-dict-order: + +Handler configuration order +""""""""""""""""""""""""""" + +Handlers are configured in alphabetical order of their keys, and a configured +handler replaces the configuration dictionary in (a working copy of) the +``handlers`` dictionary in the schema. If you use a construct such as +``cfg://handlers.foo``, then initially ``handlers['foo']`` points to the +configuration dictionary for the handler named ``foo``, and later (once that +handler has been configured) it points to the configured handler instance. +Thus, ``cfg://handlers.foo`` could resolve to either a dictionary or a handler +instance. In general, it is wise to name handlers in a way such that dependent +handlers are configured _after_ any handlers they depend on; that allows +something like ``cfg://handlers.foo`` to be used in configuring a handler that +depends on handler ``foo``. If that dependent handler were named ``bar``, +problems would result, because the configuration of ``bar`` would be attempted +before that of ``foo``, and ``foo`` would not yet have been configured. +However, if the dependent handler were named ``foobar``, it would be configured +after ``foo``, with the result that ``cfg://handlers.foo`` would resolve to +configured handler ``foo``, and not its configuration dictionary. + .. _logging-config-dict-externalobj: diff -Nru python3.10-3.10.7/Doc/library/logging.rst python3.10-3.10.12/Doc/library/logging.rst --- python3.10-3.10.7/Doc/library/logging.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/logging.rst 2023-06-06 22:30:33.000000000 +0000 @@ -522,6 +522,22 @@ is intended to be implemented by subclasses and so raises a :exc:`NotImplementedError`. + .. warning:: This method is called after a handler-level lock is acquired, which + is released after this method returns. When you override this method, note + that you should be careful when calling anything that invokes other parts of + the logging API which might do locking, because that might result in a + deadlock. Specifically: + + * Logging configuration APIs acquire the module-level lock, and then + individual handler-level locks as those handlers are configured. + + * Many logging APIs lock the module-level lock. If such an API is called + from this method, it could cause a deadlock if a configuration call is + made on another thread, because that thread will try to acquire the + module-level lock *before* the handler-level lock, whereas this thread + tries to acquire the module-level lock *after* the handler-level lock + (because in this method, the handler-level lock has already been acquired). + For a list of handlers included as standard, see :mod:`logging.handlers`. .. _formatter-objects: @@ -652,6 +668,35 @@ :func:`traceback.print_stack`, but with the last newline removed) as a string. This default implementation just returns the input value. +.. class:: BufferingFormatter(linefmt=None) + + A base formatter class suitable for subclassing when you want to format a + number of records. You can pass a :class:`Formatter` instance which you want + to use to format each line (that corresponds to a single record). If not + specified, the default formatter (which just outputs the event message) is + used as the line formatter. + + .. method:: formatHeader(records) + + Return a header for a list of *records*. The base implementation just + returns the empty string. You will need to override this method if you + want specific behaviour, e.g. to show the count of records, a title or a + separator line. + + .. method:: formatFooter(records) + + Return a footer for a list of *records*. The base implementation just + returns the empty string. You will need to override this method if you + want specific behaviour, e.g. to show the count of records or a separator + line. + + .. method:: format(records) + + Return formatted text for a list of *records*. The base implementation + just returns the empty string if there are no records; otherwise, it + returns the concatenation of the header, each record formatted with the + line formatter, and the footer. + .. _filter: Filter Objects @@ -751,8 +796,9 @@ :type lineno: int :param msg: The event description message, - which can be a %-format string with placeholders for variable data. - :type msg: str + which can be a %-format string with placeholders for variable data, + or an arbitrary object (see :ref:`arbitrary-object-messages`). + :type msg: typing.Any :param args: Variable data to merge into the *msg* argument to obtain the event description. diff -Nru python3.10-3.10.7/Doc/library/lzma.rst python3.10-3.10.12/Doc/library/lzma.rst --- python3.10-3.10.7/Doc/library/lzma.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/lzma.rst 2023-06-06 22:30:33.000000000 +0000 @@ -258,7 +258,7 @@ will be set to ``True``. Attempting to decompress data after the end of stream is reached - raises an `EOFError`. Any data found after the end of the + raises an :exc:`EOFError`. Any data found after the end of the stream is ignored and saved in the :attr:`~.unused_data` attribute. .. versionchanged:: 3.5 diff -Nru python3.10-3.10.7/Doc/library/mailbox.rst python3.10-3.10.12/Doc/library/mailbox.rst --- python3.10-3.10.7/Doc/library/mailbox.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/mailbox.rst 2023-06-06 22:30:33.000000000 +0000 @@ -426,7 +426,7 @@ .. seealso:: - `maildir man page from Courier `_ + `maildir man page from Courier `_ A specification of the format. Describes a common extension for supporting folders. @@ -614,7 +614,7 @@ .. seealso:: - `nmh - Message Handling System `_ + `nmh - Message Handling System `_ Home page of :program:`nmh`, an updated version of the original :program:`mh`. `MH & nmh: Email for Users & Programmers `_ diff -Nru python3.10-3.10.7/Doc/library/mailcap.rst python3.10-3.10.12/Doc/library/mailcap.rst --- python3.10-3.10.7/Doc/library/mailcap.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/mailcap.rst 2023-06-06 22:30:33.000000000 +0000 @@ -60,6 +60,18 @@ use) to determine whether or not the mailcap line applies. :func:`findmatch` will automatically check such conditions and skip the entry if the check fails. + .. versionchanged:: 3.10.8 + + To prevent security issues with shell metacharacters (symbols that have + special effects in a shell command line), ``findmatch`` will refuse + to inject ASCII characters other than alphanumerics and ``@+=:,./-_`` + into the returned command line. + + If a disallowed character appears in *filename*, ``findmatch`` will always + return ``(None, None)`` as if no entry was found. + If such a character appears elsewhere (a value in *plist* or in *MIMEtype*), + ``findmatch`` will ignore all mailcap entries which use that value. + A :mod:`warning ` will be raised in either case. .. function:: getcaps() diff -Nru python3.10-3.10.7/Doc/library/__main__.rst python3.10-3.10.12/Doc/library/__main__.rst --- python3.10-3.10.7/Doc/library/__main__.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/__main__.rst 2023-06-06 22:30:33.000000000 +0000 @@ -259,7 +259,7 @@ See :mod:`venv` for an example of a package with a minimal ``__main__.py`` in the standard library. It doesn't contain a ``if __name__ == '__main__'`` - block. You can invoke it with ``python3 -m venv [directory]``. + block. You can invoke it with ``python -m venv [directory]``. See :mod:`runpy` for more details on the :option:`-m` flag to the interpreter executable. diff -Nru python3.10-3.10.7/Doc/library/multiprocessing.rst python3.10-3.10.12/Doc/library/multiprocessing.rst --- python3.10-3.10.7/Doc/library/multiprocessing.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/multiprocessing.rst 2023-06-06 22:30:33.000000000 +0000 @@ -142,8 +142,8 @@ subprocess. See :issue:`33725`. .. versionchanged:: 3.4 - *spawn* added on all unix platforms, and *forkserver* added for - some unix platforms. + *spawn* added on all Unix platforms, and *forkserver* added for + some Unix platforms. Child processes no longer inherit all of the parents inheritable handles on Windows. @@ -657,7 +657,6 @@ Example usage of some of the methods of :class:`Process`: .. doctest:: - :options: +ELLIPSIS >>> import multiprocessing, time, signal >>> p = multiprocessing.Process(target=time.sleep, args=(1000,)) @@ -2596,9 +2595,9 @@ filesystem. * An ``'AF_PIPE'`` address is a string of the form - :samp:`r'\\\\.\\pipe\\{PipeName}'`. To use :func:`Client` to connect to a named + :samp:`r'\\\\\\.\\pipe\\\\{PipeName}'`. To use :func:`Client` to connect to a named pipe on a remote computer called *ServerName* one should use an address of the - form :samp:`r'\\\\{ServerName}\\pipe\\{PipeName}'` instead. + form :samp:`r'\\\\\\\\{ServerName}\\pipe\\\\{PipeName}'` instead. Note that any string beginning with two backslashes is assumed by default to be an ``'AF_PIPE'`` address rather than an ``'AF_UNIX'`` address. @@ -2921,6 +2920,8 @@ However, global variables which are just module level constants cause no problems. +.. _multiprocessing-safe-main-import: + Safe importing of main module Make sure that the main module can be safely imported by a new Python diff -Nru python3.10-3.10.7/Doc/library/multiprocessing.shared_memory.rst python3.10-3.10.12/Doc/library/multiprocessing.shared_memory.rst --- python3.10-3.10.7/Doc/library/multiprocessing.shared_memory.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/multiprocessing.shared_memory.rst 2023-06-06 22:30:33.000000000 +0000 @@ -125,7 +125,7 @@ The following example demonstrates a practical use of the :class:`SharedMemory` -class with `NumPy arrays `_, accessing the +class with `NumPy arrays `_, accessing the same ``numpy.ndarray`` from two distinct Python shells: .. doctest:: diff -Nru python3.10-3.10.7/Doc/library/operator.rst python3.10-3.10.12/Doc/library/operator.rst --- python3.10-3.10.7/Doc/library/operator.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/operator.rst 2023-06-06 22:30:33.000000000 +0000 @@ -316,7 +316,7 @@ return g The items can be any type accepted by the operand's :meth:`__getitem__` - method. Dictionaries accept any hashable value. Lists, tuples, and + method. Dictionaries accept any :term:`hashable` value. Lists, tuples, and strings accept an index or a slice: >>> itemgetter(1)('ABCDEFG') diff -Nru python3.10-3.10.7/Doc/library/optparse.rst python3.10-3.10.12/Doc/library/optparse.rst --- python3.10-3.10.7/Doc/library/optparse.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/optparse.rst 2023-06-06 22:30:33.000000000 +0000 @@ -404,7 +404,7 @@ Some other actions supported by :mod:`optparse` are: ``"store_const"`` - store a constant value + store a constant value, pre-set via :attr:`Option.const` ``"append"`` append this option's argument to a list @@ -925,7 +925,7 @@ store this option's argument (default) ``"store_const"`` - store a constant value + store a constant value, pre-set via :attr:`Option.const` ``"store_true"`` store ``True`` @@ -937,7 +937,7 @@ append this option's argument to a list ``"append_const"`` - append a constant value to a list + append a constant value to a list, pre-set via :attr:`Option.const` ``"count"`` increment a counter by one diff -Nru python3.10-3.10.7/Doc/library/os.path.rst python3.10-3.10.12/Doc/library/os.path.rst --- python3.10-3.10.7/Doc/library/os.path.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/os.path.rst 2023-06-06 22:30:33.000000000 +0000 @@ -16,7 +16,7 @@ module. The path parameters can be passed as strings, or bytes, or any object implementing the :class:`os.PathLike` protocol. -Unlike a unix shell, Python does not do any *automatic* path expansions. +Unlike a Unix shell, Python does not do any *automatic* path expansions. Functions such as :func:`expanduser` and :func:`expandvars` can be invoked explicitly when an application desires shell-like path expansion. (See also the :mod:`glob` module.) @@ -297,17 +297,18 @@ .. function:: join(path, *paths) - Join one or more path components intelligently. The return value is the - concatenation of *path* and any members of *\*paths* with exactly one - directory separator following each non-empty part except the last, meaning - that the result will only end in a separator if the last part is empty. If - a component is an absolute path, all previous components are thrown away - and joining continues from the absolute path component. - - On Windows, the drive letter is not reset when an absolute path component - (e.g., ``r'\foo'``) is encountered. If a component contains a drive - letter, all previous components are thrown away and the drive letter is - reset. Note that since there is a current directory for each drive, + Join one or more path segments intelligently. The return value is the + concatenation of *path* and all members of *\*paths*, with exactly one + directory separator following each non-empty part, except the last. That is, + the result will only end in a separator if the last part is either empty or + ends in a separator. If a segment is an absolute path (which on Windows + requires both a drive and a root), then all previous segments are ignored and + joining continues from the absolute path segment. + + On Windows, the drive is not reset when a rooted path segment (e.g., + ``r'\foo'``) is encountered. If a segment is on a different drive or is an + absolute path, all previous segments are ignored and the drive is reset. Note + that since there is a current directory for each drive, ``os.path.join("c:", "foo")`` represents a path relative to the current directory on drive :file:`C:` (:file:`c:foo`), not :file:`c:\\foo`. diff -Nru python3.10-3.10.7/Doc/library/os.rst python3.10-3.10.12/Doc/library/os.rst --- python3.10-3.10.7/Doc/library/os.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/os.rst 2023-06-06 22:30:33.000000000 +0000 @@ -188,6 +188,11 @@ ``'surrogateescape'`` error handler. Use :data:`environb` if you would like to use a different encoding. + On Windows, the keys are converted to uppercase. This also applies when + getting, setting, or deleting an item. For example, + ``environ['monty'] = 'python'`` maps the key ``'MONTY'`` to the value + ``'python'``. + .. note:: Calling :func:`putenv` directly does not change :data:`os.environ`, so it's better @@ -291,8 +296,8 @@ .. function:: getenv(key, default=None) - Return the value of the environment variable *key* if it exists, or - *default* if it doesn't. *key*, *default* and the result are str. Note that + Return the value of the environment variable *key* as a string if it exists, or + *default* if it doesn't. *key* is a string. Note that since :func:`getenv` uses :data:`os.environ`, the mapping of :func:`getenv` is similarly also captured on import, and the function may not reflect future environment changes. @@ -306,8 +311,8 @@ .. function:: getenvb(key, default=None) - Return the value of the environment variable *key* if it exists, or - *default* if it doesn't. *key*, *default* and the result are bytes. Note that + Return the value of the environment variable *key* as bytes if it exists, or + *default* if it doesn't. *key* must be bytes. Note that since :func:`getenvb` uses :data:`os.environb`, the mapping of :func:`getenvb` is similarly also captured on import, and the function may not reflect future environment changes. @@ -2256,7 +2261,7 @@ .. function:: remove(path, *, dir_fd=None) Remove (delete) the file *path*. If *path* is a directory, an - :exc:`IsADirectoryError` is raised. Use :func:`rmdir` to remove directories. + :exc:`OSError` is raised. Use :func:`rmdir` to remove directories. If the file does not exist, a :exc:`FileNotFoundError` is raised. This function can support :ref:`paths relative to directory descriptors @@ -2302,6 +2307,8 @@ will fail with an :exc:`OSError` subclass in a number of cases: On Windows, if *dst* exists a :exc:`FileExistsError` is always raised. + The operation may fail if *src* and *dst* are on different filesystems. Use + :func:`shutil.move` to support moves to a different filesystem. On Unix, if *src* is a file and *dst* is a directory or vice-versa, an :exc:`IsADirectoryError` or a :exc:`NotADirectoryError` will be raised @@ -3107,7 +3114,7 @@ system records access and modification times; see :func:`~os.stat`. The best way to preserve exact times is to use the *st_atime_ns* and *st_mtime_ns* fields from the :func:`os.stat` result object with the *ns* parameter to - `utime`. + :func:`utime`. This function can support :ref:`specifying a file descriptor `, :ref:`paths relative to directory descriptors ` and :ref:`not @@ -3135,7 +3142,8 @@ filenames)``. *dirpath* is a string, the path to the directory. *dirnames* is a list of the - names of the subdirectories in *dirpath* (excluding ``'.'`` and ``'..'``). + names of the subdirectories in *dirpath* (including symlinks to directories, + and excluding ``'.'`` and ``'..'``). *filenames* is a list of the names of the non-directory files in *dirpath*. Note that the names in the lists contain no path components. To get a full path (which begins with *top*) to a file or directory in *dirpath*, do @@ -3650,7 +3658,7 @@ .. note:: - The standard way to exit is ``sys.exit(n)``. :func:`_exit` should + The standard way to exit is :func:`sys.exit(n) `. :func:`!_exit` should normally only be used in the child process after a :func:`fork`. The following exit codes are defined and can be used with :func:`_exit`, @@ -3983,7 +3991,7 @@ library :c:data:`POSIX_SPAWN_RESETIDS` flag. If the *setsid* argument is ``True``, it will create a new session ID - for `posix_spawn`. *setsid* requires :c:data:`POSIX_SPAWN_SETSID` + for ``posix_spawn``. *setsid* requires :c:data:`POSIX_SPAWN_SETSID` or :c:data:`POSIX_SPAWN_SETSID_NP` flag. Otherwise, :exc:`NotImplementedError` is raised. diff -Nru python3.10-3.10.7/Doc/library/pathlib.rst python3.10-3.10.12/Doc/library/pathlib.rst --- python3.10-3.10.7/Doc/library/pathlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/pathlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -118,16 +118,16 @@ >>> PurePath() PurePosixPath('.') - When several absolute paths are given, the last is taken as an anchor - (mimicking :func:`os.path.join`'s behaviour):: + If a segment is an absolute path, all previous segments are ignored + (like :func:`os.path.join`):: >>> PurePath('/etc', '/usr', 'lib64') PurePosixPath('/usr/lib64') >>> PureWindowsPath('c:/Windows', 'd:bar') PureWindowsPath('d:bar') - However, in a Windows path, changing the local root doesn't discard the - previous drive setting:: + On Windows, the drive is not reset when a rooted relative path + segment (e.g., ``r'\foo'``) is encountered:: >>> PureWindowsPath('c:/Windows', '/Program Files') PureWindowsPath('c:/Program Files') @@ -186,7 +186,7 @@ General properties ^^^^^^^^^^^^^^^^^^ -Paths are immutable and hashable. Paths of a same flavour are comparable +Paths are immutable and :term:`hashable`. Paths of a same flavour are comparable and orderable. These properties respect the flavour's case-folding semantics:: @@ -212,7 +212,10 @@ Operators ^^^^^^^^^ -The slash operator helps create child paths, similarly to :func:`os.path.join`:: +The slash operator helps create child paths, like :func:`os.path.join`. +If the argument is an absolute path, the previous path is ignored. +On Windows, the drive is not reset when the argument is a rooted +relative path (e.g., ``r'\foo'``):: >>> p = PurePath('/etc') >>> p @@ -222,6 +225,10 @@ >>> q = PurePath('bin') >>> '/usr' / q PurePosixPath('/usr/bin') + >>> p / '/an_absolute_path' + PurePosixPath('/an_absolute_path') + >>> PureWindowsPath('c:/Windows', '/Program Files') + PureWindowsPath('c:/Program Files') A path object can be used anywhere an object implementing :class:`os.PathLike` is accepted:: @@ -259,7 +266,7 @@ To access the individual "parts" (components) of a path, use the following property: -.. data:: PurePath.parts +.. attribute:: PurePath.parts A tuple giving access to the path's various components:: @@ -283,7 +290,7 @@ Pure paths provide the following methods and properties: -.. data:: PurePath.drive +.. attribute:: PurePath.drive A string representing the drive letter or name, if any:: @@ -299,7 +306,7 @@ >>> PureWindowsPath('//host/share/foo.txt').drive '\\\\host\\share' -.. data:: PurePath.root +.. attribute:: PurePath.root A string representing the (local or global) root, if any:: @@ -335,7 +342,7 @@ an implementation-defined manner, although more than two leading slashes shall be treated as a single slash."* -.. data:: PurePath.anchor +.. attribute:: PurePath.anchor The concatenation of the drive and root:: @@ -349,7 +356,7 @@ '\\\\host\\share\\' -.. data:: PurePath.parents +.. attribute:: PurePath.parents An immutable sequence providing access to the logical ancestors of the path:: @@ -365,7 +372,7 @@ .. versionchanged:: 3.10 The parents sequence now supports :term:`slices ` and negative index values. -.. data:: PurePath.parent +.. attribute:: PurePath.parent The logical parent of the path:: @@ -394,7 +401,7 @@ symlinks and eliminate `".."` components. -.. data:: PurePath.name +.. attribute:: PurePath.name A string representing the final path component, excluding the drive and root, if any:: @@ -410,7 +417,7 @@ '' -.. data:: PurePath.suffix +.. attribute:: PurePath.suffix The file extension of the final component, if any:: @@ -422,7 +429,7 @@ '' -.. data:: PurePath.suffixes +.. attribute:: PurePath.suffixes A list of the path's file extensions:: @@ -434,7 +441,7 @@ [] -.. data:: PurePath.stem +.. attribute:: PurePath.stem The final path component, without its suffix:: @@ -1061,6 +1068,8 @@ relative to the current working directory, *not* the directory of the Path object. + It is implemented in terms of :func:`os.rename` and gives the same guarantees. + .. versionchanged:: 3.8 Added return value, return the new Path instance. @@ -1297,11 +1306,11 @@ :meth:`Path.group` :func:`os.path.isabs` :meth:`PurePath.is_absolute` :func:`os.path.join` :func:`PurePath.joinpath` -:func:`os.path.basename` :data:`PurePath.name` -:func:`os.path.dirname` :data:`PurePath.parent` +:func:`os.path.basename` :attr:`PurePath.name` +:func:`os.path.dirname` :attr:`PurePath.parent` :func:`os.path.samefile` :meth:`Path.samefile` -:func:`os.path.splitext` :data:`PurePath.stem` and - :data:`PurePath.suffix` +:func:`os.path.splitext` :attr:`PurePath.stem` and + :attr:`PurePath.suffix` ==================================== ============================== .. rubric:: Footnotes diff -Nru python3.10-3.10.7/Doc/library/pdb.rst python3.10-3.10.12/Doc/library/pdb.rst --- python3.10-3.10.7/Doc/library/pdb.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/pdb.rst 2023-06-06 22:30:33.000000000 +0000 @@ -27,6 +27,15 @@ This is currently undocumented but easily understood by reading the source. The extension interface uses the modules :mod:`bdb` and :mod:`cmd`. +.. seealso:: + + Module :mod:`faulthandler` + Used to dump Python tracebacks explicitly, on a fault, after a timeout, + or on a user signal. + + Module :mod:`traceback` + Standard interface to extract, format and print stack traces of Python programs. + The debugger's prompt is ``(Pdb)``. Typical usage to run a program under control of the debugger is:: @@ -49,7 +58,7 @@ :file:`pdb.py` can also be invoked as a script to debug other scripts. For example:: - python3 -m pdb myscript.py + python -m pdb myscript.py When invoked as a script, pdb will automatically enter post-mortem debugging if the program being debugged exits abnormally. After post-mortem debugging (or @@ -63,7 +72,7 @@ .. versionadded:: 3.7 :file:`pdb.py` now accepts a ``-m`` option that execute modules similar to the way - ``python3 -m`` does. As with a script, the debugger will pause execution just + ``python -m`` does. As with a script, the debugger will pause execution just before the first line of the module. @@ -116,7 +125,7 @@ Evaluate the *expression* (given as a string or a code object) under debugger control. When :func:`runeval` returns, it returns the value of the - expression. Otherwise this function is similar to :func:`run`. + *expression*. Otherwise this function is similar to :func:`run`. .. function:: runcall(function, *args, **kwds) @@ -169,7 +178,7 @@ that matches one of these patterns. [1]_ By default, Pdb sets a handler for the SIGINT signal (which is sent when the - user presses :kbd:`Ctrl-C` on the console) when you give a ``continue`` command. + user presses :kbd:`Ctrl-C` on the console) when you give a :pdbcmd:`continue` command. This allows you to break into the debugger again by pressing :kbd:`Ctrl-C`. If you want Pdb not to touch the SIGINT handler, set *nosigint* to true. @@ -315,9 +324,9 @@ .. pdbcommand:: ignore bpnumber [count] - Set the ignore count for the given breakpoint number. If count is omitted, + Set the ignore count for the given breakpoint number. If *count* is omitted, the ignore count is set to 0. A breakpoint becomes active when the ignore - count is zero. When non-zero, the count is decremented each time the + count is zero. When non-zero, the *count* is decremented each time the breakpoint is reached and the breakpoint is not disabled and any associated condition evaluates to true. @@ -356,7 +365,7 @@ breakpoint—which could have its own command list, leading to ambiguities about which list to execute. - If you use the 'silent' command in the command list, the usual message about + If you use the ``silent`` command in the command list, the usual message about stopping at a breakpoint is not printed. This may be desirable for breakpoints that are to print a specific message and then continue. If none of the other commands print anything, you see no sign that the breakpoint was reached. @@ -379,8 +388,8 @@ Without argument, continue execution until the line with a number greater than the current one is reached. - With a line number, continue execution until a line with a number greater or - equal to that is reached. In both cases, also stop when the current frame + With *lineno*, continue execution until a line with a number greater or + equal to *lineno* is reached. In both cases, also stop when the current frame returns. .. versionchanged:: 3.2 @@ -433,7 +442,7 @@ .. pdbcommand:: p expression - Evaluate the *expression* in the current context and print its value. + Evaluate *expression* in the current context and print its value. .. note:: @@ -443,32 +452,32 @@ .. pdbcommand:: pp expression - Like the :pdbcmd:`p` command, except the value of the expression is + Like the :pdbcmd:`p` command, except the value of *expression* is pretty-printed using the :mod:`pprint` module. .. pdbcommand:: whatis expression - Print the type of the *expression*. + Print the type of *expression*. .. pdbcommand:: source expression - Try to get source code for the given object and display it. + Try to get source code of *expression* and display it. .. versionadded:: 3.2 .. pdbcommand:: display [expression] - Display the value of the expression if it changed, each time execution stops + Display the value of *expression* if it changed, each time execution stops in the current frame. - Without expression, list all display expressions for the current frame. + Without *expression*, list all display expressions for the current frame. .. versionadded:: 3.2 .. pdbcommand:: undisplay [expression] - Do not display the expression any more in the current frame. Without - expression, clear all display expressions for the current frame. + Do not display *expression* anymore in the current frame. Without + *expression*, clear all display expressions for the current frame. .. versionadded:: 3.2 @@ -484,10 +493,10 @@ .. pdbcommand:: alias [name [command]] - Create an alias called *name* that executes *command*. The command must + Create an alias called *name* that executes *command*. The *command* must *not* be enclosed in quotes. Replaceable parameters can be indicated by ``%1``, ``%2``, and so on, while ``%*`` is replaced by all the parameters. - If no command is given, the current alias for *name* is shown. If no + If *command* is omitted, the current alias for *name* is shown. If no arguments are given, all aliases are listed. Aliases may be nested and can contain anything that can be legally typed at @@ -500,13 +509,13 @@ :file:`.pdbrc` file):: # Print instance variables (usage "pi classInst") - alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k]) + alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}") # Print instance variables in self alias ps pi self .. pdbcommand:: unalias name - Delete the specified alias. + Delete the specified alias *name*. .. pdbcommand:: ! statement @@ -522,7 +531,7 @@ .. pdbcommand:: run [args ...] restart [args ...] - Restart the debugged Python program. If an argument is supplied, it is split + Restart the debugged Python program. If *args* is supplied, it is split with :mod:`shlex` and the result is used as the new :data:`sys.argv`. History, breakpoints, actions and debugger options are preserved. :pdbcmd:`restart` is an alias for :pdbcmd:`run`. @@ -533,8 +542,8 @@ .. pdbcommand:: debug code - Enter a recursive debugger that steps through the code - argument (which is an arbitrary expression or statement to be + Enter a recursive debugger that steps through *code* + (which is an arbitrary expression or statement to be executed in the current environment). .. pdbcommand:: retval diff -Nru python3.10-3.10.7/Doc/library/pickle.rst python3.10-3.10.12/Doc/library/pickle.rst --- python3.10-3.10.7/Doc/library/pickle.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/pickle.rst 2023-06-06 22:30:33.000000000 +0000 @@ -90,7 +90,7 @@ ^^^^^^^^^^^^^^^^^^^^^^^^ There are fundamental differences between the pickle protocols and -`JSON (JavaScript Object Notation) `_: +`JSON (JavaScript Object Notation) `_: * JSON is a text serialization format (it outputs unicode text, although most of the time it is then encoded to ``utf-8``), while pickle is diff -Nru python3.10-3.10.7/Doc/library/plistlib.rst python3.10-3.10.12/Doc/library/plistlib.rst --- python3.10-3.10.7/Doc/library/plistlib.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/plistlib.rst 2023-06-06 22:30:33.000000000 +0000 @@ -159,6 +159,9 @@ Generating a plist:: + import datetime + import plistlib + pl = dict( aString = "Doodah", aList = ["A", "B", 12, 32.1, [1, 2, 3]], @@ -172,13 +175,19 @@ ), someData = b"", someMoreData = b"" * 10, - aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())), + aDate = datetime.datetime.now() ) - with open(fileName, 'wb') as fp: - dump(pl, fp) + print(plistlib.dumps(pl).decode()) Parsing a plist:: - with open(fileName, 'rb') as fp: - pl = load(fp) - print(pl["aKey"]) + import plistlib + + plist = b""" + + foo + bar + + """ + pl = plistlib.loads(plist) + print(pl["foo"]) diff -Nru python3.10-3.10.7/Doc/library/posix.rst python3.10-3.10.12/Doc/library/posix.rst --- python3.10-3.10.7/Doc/library/posix.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/posix.rst 2023-06-06 22:30:33.000000000 +0000 @@ -39,12 +39,12 @@ Several operating systems (including AIX and Solaris) provide support for files that are larger than 2 GiB from a C programming model where -:c:type:`int` and :c:type:`long` are 32-bit values. This is typically accomplished +:c:expr:`int` and :c:expr:`long` are 32-bit values. This is typically accomplished by defining the relevant size and offset types as 64-bit values. Such files are sometimes referred to as :dfn:`large files`. Large file support is enabled in Python when the size of an :c:type:`off_t` is -larger than a :c:type:`long` and the :c:type:`long long` is at least as large +larger than a :c:expr:`long` and the :c:expr:`long long` is at least as large as an :c:type:`off_t`. It may be necessary to configure and compile Python with certain compiler flags to enable this mode. For example, with Solaris 2.6 and 2.7 you need to do diff -Nru python3.10-3.10.7/Doc/library/profile.rst python3.10-3.10.12/Doc/library/profile.rst --- python3.10-3.10.7/Doc/library/profile.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/profile.rst 2023-06-06 22:30:33.000000000 +0000 @@ -273,7 +273,7 @@ with cProfile.Profile() as pr: # ... do something ... - pr.print_stats() + pr.print_stats() .. versionchanged:: 3.8 Added context manager support. diff -Nru python3.10-3.10.7/Doc/library/pydoc.rst python3.10-3.10.12/Doc/library/pydoc.rst --- python3.10-3.10.7/Doc/library/pydoc.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/pydoc.rst 2023-06-06 22:30:33.000000000 +0000 @@ -33,7 +33,7 @@ outside the Python interpreter by running :program:`pydoc` as a script at the operating system's command prompt. For example, running :: - pydoc sys + python -m pydoc sys at a shell prompt will display documentation on the :mod:`sys` module, in a style similar to the manual pages shown by the Unix :program:`man` command. The @@ -65,18 +65,18 @@ module is the first line of its documentation string. You can also use :program:`pydoc` to start an HTTP server on the local machine -that will serve documentation to visiting web browsers. :program:`pydoc -p 1234` +that will serve documentation to visiting web browsers. :program:`python -m pydoc -p 1234` will start a HTTP server on port 1234, allowing you to browse the documentation at ``http://localhost:1234/`` in your preferred web browser. Specifying ``0`` as the port number will select an arbitrary unused port. -:program:`pydoc -n ` will start the server listening at the given +:program:`python -m pydoc -n ` will start the server listening at the given hostname. By default the hostname is 'localhost' but if you want the server to be reached from other machines, you may want to change the host name that the server responds to. During development this is especially useful if you want to run pydoc from within a container. -:program:`pydoc -b` will start the server and additionally open a web +:program:`python -m pydoc -b` will start the server and additionally open a web browser to a module index page. Each served page has a navigation bar at the top where you can *Get* help on an individual item, *Search* all modules with a keyword in their synopsis line, and go to the *Module index*, *Topics* and diff -Nru python3.10-3.10.7/Doc/library/queue.rst python3.10-3.10.12/Doc/library/queue.rst --- python3.10-3.10.7/Doc/library/queue.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/queue.rst 2023-06-06 22:30:33.000000000 +0000 @@ -15,7 +15,7 @@ The module implements three types of queue, which differ only in the order in which the entries are retrieved. In a :abbr:`FIFO (first-in, first-out)` -queue, the first tasks added are the first retrieved. In a +queue, the first tasks added are the first retrieved. In a :abbr:`LIFO (last-in, first-out)` queue, the most recently added entry is the first retrieved (operating like a stack). With a priority queue, the entries are kept sorted (using the :mod:`heapq` module) and the @@ -57,8 +57,8 @@ *maxsize* is less than or equal to zero, the queue size is infinite. The lowest valued entries are retrieved first (the lowest valued entry is the - one returned by ``sorted(list(entries))[0]``). A typical pattern for entries - is a tuple in the form: ``(priority_number, data)``. + one that would be returned by ``min(entries)``). A typical pattern for + entries is a tuple in the form: ``(priority_number, data)``. If the *data* elements are not comparable, the data can be wrapped in a class that ignores the data item and only compares the priority number:: @@ -127,8 +127,8 @@ .. method:: Queue.put(item, block=True, timeout=None) - Put *item* into the queue. If optional args *block* is true and *timeout* is - ``None`` (the default), block if necessary until a free slot is available. If + Put *item* into the queue. If optional args *block* is true and *timeout* is + ``None`` (the default), block if necessary until a free slot is available. If *timeout* is a positive number, it blocks at most *timeout* seconds and raises the :exc:`Full` exception if no free slot was available within that time. Otherwise (*block* is false), put an item on the queue if a free slot is @@ -143,7 +143,7 @@ .. method:: Queue.get(block=True, timeout=None) - Remove and return an item from the queue. If optional args *block* is true and + Remove and return an item from the queue. If optional args *block* is true and *timeout* is ``None`` (the default), block if necessary until an item is available. If *timeout* is a positive number, it blocks at most *timeout* seconds and raises the :exc:`Empty` exception if no item was available within that time. @@ -152,7 +152,7 @@ Prior to 3.0 on POSIX systems, and for all versions on Windows, if *block* is true and *timeout* is ``None``, this operation goes into - an uninterruptible wait on an underlying lock. This means that no exceptions + an uninterruptible wait on an underlying lock. This means that no exceptions can occur, and in particular a SIGINT will not trigger a :exc:`KeyboardInterrupt`. @@ -184,7 +184,7 @@ The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls :meth:`task_done` to - indicate that the item was retrieved and all work on it is complete. When the + indicate that the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, :meth:`join` unblocks. @@ -227,7 +227,7 @@ .. method:: SimpleQueue.empty() - Return ``True`` if the queue is empty, ``False`` otherwise. If empty() + Return ``True`` if the queue is empty, ``False`` otherwise. If empty() returns ``False`` it doesn't guarantee that a subsequent call to get() will not block. diff -Nru python3.10-3.10.7/Doc/library/random.rst python3.10-3.10.12/Doc/library/random.rst --- python3.10-3.10.7/Doc/library/random.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/random.rst 2023-06-06 22:30:33.000000000 +0000 @@ -546,15 +546,15 @@ including simulation, sampling, shuffling, and cross-validation. `Economics Simulation - `_ + `_ a simulation of a marketplace by - `Peter Norvig `_ that shows effective + `Peter Norvig `_ that shows effective use of many of the tools and distributions provided by this module (gauss, uniform, sample, betavariate, choice, triangular, and randrange). `A Concrete Introduction to Probability (using Python) - `_ - a tutorial by `Peter Norvig `_ covering + `_ + a tutorial by `Peter Norvig `_ covering the basics of probability theory, how to write simulations, and how to perform data analysis using Python. diff -Nru python3.10-3.10.7/Doc/library/re.rst python3.10-3.10.12/Doc/library/re.rst --- python3.10-3.10.7/Doc/library/re.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/re.rst 2023-06-06 22:30:33.000000000 +0000 @@ -232,7 +232,8 @@ * To match a literal ``']'`` inside a set, precede it with a backslash, or place it at the beginning of the set. For example, both ``[()[\]{}]`` and - ``[]()[{}]`` will both match a parenthesis. + ``[]()[{}]`` will match a right bracket, as well as left bracket, braces, + and parentheses. .. .. index:: single: --; in regular expressions .. .. index:: single: &&; in regular expressions @@ -421,6 +422,9 @@ some fixed length. Patterns which start with negative lookbehind assertions may match at the beginning of the string being searched. +.. _re-conditional-expression: +.. index:: single: (?(; in regular expressions + ``(?(id/name)yes-pattern|no-pattern)`` Will try to match with ``yes-pattern`` if the group with given *id* or *name* exists, and with ``no-pattern`` if it doesn't. ``no-pattern`` is @@ -523,10 +527,9 @@ ``\w`` For Unicode (str) patterns: - Matches Unicode word characters; this includes most characters - that can be part of a word in any language, as well as numbers and - the underscore. If the :const:`ASCII` flag is used, only - ``[a-zA-Z0-9_]`` is matched. + Matches Unicode word characters; this includes alphanumeric characters (as defined by :meth:`str.isalnum`) + as well as the underscore (``_``). + If the :const:`ASCII` flag is used, only ``[a-zA-Z0-9_]`` is matched. For 8-bit (bytes) patterns: Matches characters considered alphanumeric in the ASCII character set; @@ -702,7 +705,8 @@ more readable by allowing you to visually separate logical sections of the pattern and add comments. Whitespace within the pattern is ignored, except when in a character class, or when preceded by an unescaped backslash, - or within tokens like ``*?``, ``(?:`` or ``(?P<...>``. + or within tokens like ``*?``, ``(?:`` or ``(?P<...>``. For example, ``(? :`` + and ``* ?`` are not allowed. When a line contains a ``#`` that is not in a character class and is not preceded by an unescaped backslash, all characters from the leftmost such ``#`` through the end of the line are ignored. @@ -1467,16 +1471,22 @@ .. sectionauthor:: Fred L. Drake, Jr. -Python offers two different primitive operations based on regular expressions: -:func:`re.match` checks for a match only at the beginning of the string, while -:func:`re.search` checks for a match anywhere in the string (this is what Perl -does by default). +Python offers different primitive operations based on regular expressions: + ++ :func:`re.match` checks for a match only at the beginning of the string ++ :func:`re.search` checks for a match anywhere in the string + (this is what Perl does by default) ++ :func:`re.fullmatch` checks for entire string to be a match + For example:: >>> re.match("c", "abcdef") # No match >>> re.search("c", "abcdef") # Match + >>> re.fullmatch("p.*n", "python") # Match + + >>> re.fullmatch("r.*n", "python") # No match Regular expressions beginning with ``'^'`` can be used with :func:`search` to restrict the match at the beginning of the string:: @@ -1490,8 +1500,8 @@ beginning of the string, whereas using :func:`search` with a regular expression beginning with ``'^'`` will match at the beginning of each line. :: - >>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match - >>> re.search('^X', 'A\nB\nX', re.MULTILINE) # Match + >>> re.match("X", "A\nB\nX", re.MULTILINE) # No match + >>> re.search("^X", "A\nB\nX", re.MULTILINE) # Match diff -Nru python3.10-3.10.7/Doc/library/sched.rst python3.10-3.10.12/Doc/library/sched.rst --- python3.10-3.10.7/Doc/library/sched.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/sched.rst 2023-06-06 22:30:33.000000000 +0000 @@ -44,16 +44,22 @@ ... print(time.time()) ... s.enter(10, 1, print_time) ... s.enter(5, 2, print_time, argument=('positional',)) + ... # despite having higher priority, 'keyword' runs after 'positional' as enter() is relative ... s.enter(5, 1, print_time, kwargs={'a': 'keyword'}) + ... s.enterabs(1_650_000_000, 10, print_time, argument=("first enterabs",)) + ... s.enterabs(1_650_000_000, 5, print_time, argument=("second enterabs",)) ... s.run() ... print(time.time()) ... >>> print_some_times() - 930343690.257 - From print_time 930343695.274 positional - From print_time 930343695.275 keyword - From print_time 930343700.273 default - 930343700.276 + 1652342830.3640375 + From print_time 1652342830.3642538 second enterabs + From print_time 1652342830.3643398 first enterabs + From print_time 1652342835.3694863 positional + From print_time 1652342835.3696074 keyword + From print_time 1652342840.369612 default + 1652342840.3697174 + .. _scheduler-objects: diff -Nru python3.10-3.10.7/Doc/library/secrets.rst python3.10-3.10.12/Doc/library/secrets.rst --- python3.10-3.10.7/Doc/library/secrets.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/secrets.rst 2023-06-06 22:30:33.000000000 +0000 @@ -128,7 +128,9 @@ .. function:: compare_digest(a, b) - Return ``True`` if strings *a* and *b* are equal, otherwise ``False``, + Return ``True`` if strings or + :term:`bytes-like objects ` + *a* and *b* are equal, otherwise ``False``, using a "constant-time compare" to reduce the risk of `timing attacks `_. See :func:`hmac.compare_digest` for additional details. diff -Nru python3.10-3.10.7/Doc/library/select.rst python3.10-3.10.12/Doc/library/select.rst --- python3.10-3.10.7/Doc/library/select.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/select.rst 2023-06-06 22:30:33.000000000 +0000 @@ -60,7 +60,7 @@ events. *sizehint* informs epoll about the expected number of events to be - registered. It must be positive, or `-1` to use the default. It is only + registered. It must be positive, or ``-1`` to use the default. It is only used on older systems where :c:func:`epoll_create1` is not available; otherwise it has no effect (though its value is still checked). diff -Nru python3.10-3.10.7/Doc/library/shutil.rst python3.10-3.10.12/Doc/library/shutil.rst --- python3.10-3.10.7/Doc/library/shutil.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/shutil.rst 2023-06-06 22:30:33.000000000 +0000 @@ -620,7 +620,7 @@ Remove the archive format *name* from the list of supported formats. -.. function:: unpack_archive(filename[, extract_dir[, format]]) +.. function:: unpack_archive(filename[, extract_dir[, format[, filter]]]) Unpack an archive. *filename* is the full path of the archive. @@ -634,6 +634,15 @@ registered for that extension. In case none is found, a :exc:`ValueError` is raised. + The keyword-only *filter* argument, which was added in Python 3.10.12, + is passed to the underlying unpacking function. + For zip files, *filter* is not accepted. + For tar files, it is recommended to set it to ``'data'``, + unless using features specific to tar and UNIX-like filesystems. + (See :ref:`tarfile-extraction-filter` for details.) + The ``'data'`` filter will become the default for tar files + in Python 3.14. + .. audit-event:: shutil.unpack_archive filename,extract_dir,format shutil.unpack_archive .. warning:: @@ -646,6 +655,9 @@ .. versionchanged:: 3.7 Accepts a :term:`path-like object` for *filename* and *extract_dir*. + .. versionchanged:: 3.10.12 + Added the *filter* argument. + .. function:: register_unpack_format(name, extensions, function[, extra_args[, description]]) Registers an unpack format. *name* is the name of the format and @@ -653,11 +665,14 @@ ``.zip`` for Zip files. *function* is the callable that will be used to unpack archives. The - callable will receive the path of the archive, followed by the directory - the archive must be extracted to. + callable will receive: - When provided, *extra_args* is a sequence of ``(name, value)`` tuples that - will be passed as keywords arguments to the callable. + - the path of the archive, as a positional argument; + - the directory the archive must be extracted to, as a positional argument; + - possibly a *filter* keyword argument, if it was given to + :func:`unpack_archive`; + - additional keyword arguments, specified by *extra_args* as a sequence + of ``(name, value)`` tuples. *description* can be provided to describe the format, and will be returned by the :func:`get_unpack_formats` function. diff -Nru python3.10-3.10.7/Doc/library/signal.rst python3.10-3.10.12/Doc/library/signal.rst --- python3.10-3.10.7/Doc/library/signal.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/signal.rst 2023-06-06 22:30:33.000000000 +0000 @@ -4,6 +4,8 @@ .. module:: signal :synopsis: Set handlers for asynchronous events. +**Source code:** :source:`Lib/signal.py` + -------------- This module provides mechanisms to use signal handlers in Python. diff -Nru python3.10-3.10.7/Doc/library/socket.rst python3.10-3.10.12/Doc/library/socket.rst --- python3.10-3.10.7/Doc/library/socket.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/socket.rst 2023-06-06 22:30:33.000000000 +0000 @@ -604,7 +604,7 @@ When :const:`SOCK_NONBLOCK` or :const:`SOCK_CLOEXEC` bit flags are applied to *type* they are cleared, and :attr:`socket.type` will not reflect them. They are still passed - to the underlying system `socket()` call. Therefore, + to the underlying system ``socket()`` call. Therefore, :: @@ -670,8 +670,8 @@ ``(host, port)``) and return the socket object. *family* should be either :data:`AF_INET` or :data:`AF_INET6`. - *backlog* is the queue size passed to :meth:`socket.listen`; when ``0`` - a default reasonable value is chosen. + *backlog* is the queue size passed to :meth:`socket.listen`; if not specified + , a default reasonable value is chosen. *reuse_port* dictates whether to set the :data:`SO_REUSEPORT` socket option. If *dualstack_ipv6* is true and the platform supports it the socket will @@ -948,7 +948,7 @@ Convert an IPv4 address from dotted-quad string format (for example, '123.45.67.89') to 32-bit packed binary format, as a bytes object four characters in length. This is useful when conversing with a program that uses the standard C - library and needs objects of type :c:type:`struct in_addr`, which is the C type + library and needs objects of type :c:struct:`in_addr`, which is the C type for the 32-bit packed binary this function returns. :func:`inet_aton` also accepts strings with less than three dots; see the @@ -967,7 +967,7 @@ Convert a 32-bit packed IPv4 address (a :term:`bytes-like object` four bytes in length) to its standard dotted-quad string representation (for example, '123.45.67.89'). This is useful when conversing with a program that uses the - standard C library and needs objects of type :c:type:`struct in_addr`, which + standard C library and needs objects of type :c:struct:`in_addr`, which is the C type for the 32-bit packed binary data this function takes as an argument. @@ -984,8 +984,8 @@ Convert an IP address from its family-specific string format to a packed, binary format. :func:`inet_pton` is useful when a library or network protocol - calls for an object of type :c:type:`struct in_addr` (similar to - :func:`inet_aton`) or :c:type:`struct in6_addr`. + calls for an object of type :c:struct:`in_addr` (similar to + :func:`inet_aton`) or :c:struct:`in6_addr`. Supported values for *address_family* are currently :const:`AF_INET` and :const:`AF_INET6`. If the IP address string *ip_string* is invalid, @@ -1005,8 +1005,8 @@ bytes) to its standard, family-specific string representation (for example, ``'7.10.0.5'`` or ``'5aef:2b::8'``). :func:`inet_ntop` is useful when a library or network protocol returns an - object of type :c:type:`struct in_addr` (similar to :func:`inet_ntoa`) or - :c:type:`struct in6_addr`. + object of type :c:struct:`in_addr` (similar to :func:`inet_ntoa`) or + :c:struct:`in6_addr`. Supported values for *address_family* are currently :const:`AF_INET` and :const:`AF_INET6`. If the bytes object *packed_ip* is not the correct @@ -1477,7 +1477,7 @@ ancillary data, items of the form ``(socket.SOL_SOCKET, socket.SCM_RIGHTS, fds)``, where *fds* is a :class:`bytes` object representing the new file descriptors as a binary array of the - native C :c:type:`int` type. If :meth:`recvmsg` raises an + native C :c:expr:`int` type. If :meth:`recvmsg` raises an exception after the system call returns, it will first attempt to close any file descriptors received via this mechanism. @@ -1596,7 +1596,7 @@ much data, if any, was successfully sent. .. versionchanged:: 3.5 - The socket timeout is no more reset each time data is sent successfully. + The socket timeout is no longer reset each time data is sent successfully. The socket timeout is now the maximum total duration to send all data. .. versionchanged:: 3.5 @@ -1814,8 +1814,8 @@ * In *non-blocking mode*, operations fail (with an error that is unfortunately system-dependent) if they cannot be completed immediately: functions from the - :mod:`select` can be used to know when and whether a socket is available for - reading or writing. + :mod:`select` module can be used to know when and whether a socket is available + for reading or writing. * In *timeout mode*, operations fail if they cannot be completed within the timeout specified for the socket (they raise a :exc:`timeout` exception) @@ -2004,7 +2004,7 @@ socket.socket(socket.AF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM) After binding (:const:`CAN_RAW`) or connecting (:const:`CAN_BCM`) the socket, you -can use the :meth:`socket.send`, and the :meth:`socket.recv` operations (and +can use the :meth:`socket.send` and :meth:`socket.recv` operations (and their counterparts) on the socket object as usual. This last example might require special privileges:: diff -Nru python3.10-3.10.7/Doc/library/socketserver.rst python3.10-3.10.12/Doc/library/socketserver.rst --- python3.10-3.10.7/Doc/library/socketserver.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/socketserver.rst 2023-06-06 22:30:33.000000000 +0000 @@ -94,8 +94,7 @@ Note that :class:`UnixDatagramServer` derives from :class:`UDPServer`, not from :class:`UnixStreamServer` --- the only difference between an IP and a Unix -stream server is the address family, which is simply repeated in both Unix -server classes. +server is the address family. .. class:: ForkingMixIn @@ -430,11 +429,8 @@ The :attr:`self.rfile` and :attr:`self.wfile` attributes can be read or written, respectively, to get the request data or return data to the client. - - The :attr:`rfile` attributes of both classes support the - :class:`io.BufferedIOBase` readable interface, and - :attr:`DatagramRequestHandler.wfile` supports the - :class:`io.BufferedIOBase` writable interface. + The :attr:`!rfile` attributes support the :class:`io.BufferedIOBase` readable interface, + and :attr:`!wfile` attributes support the :class:`!io.BufferedIOBase` writable interface. .. versionchanged:: 3.6 :attr:`StreamRequestHandler.wfile` also supports the diff -Nru python3.10-3.10.7/Doc/library/sqlite3.rst python3.10-3.10.12/Doc/library/sqlite3.rst --- python3.10-3.10.7/Doc/library/sqlite3.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/sqlite3.rst 2023-06-06 22:30:33.000000000 +0000 @@ -72,7 +72,7 @@ First, we need to create a new database and open a database connection to allow :mod:`!sqlite3` to work with it. -Call :func:`sqlite3.connect` to to create a connection to +Call :func:`sqlite3.connect` to create a connection to the database :file:`tutorial.db` in the current working directory, implicitly creating it if it does not exist: @@ -239,6 +239,7 @@ * :ref:`sqlite3-adapters` * :ref:`sqlite3-converters` * :ref:`sqlite3-connection-context-manager` + * :ref:`sqlite3-howto-row-factory` * :ref:`sqlite3-explanation` for in-depth background on transaction control. @@ -257,7 +258,7 @@ .. function:: connect(database, timeout=5.0, detect_types=0, \ isolation_level="DEFERRED", check_same_thread=True, \ - factory=sqlite3.Connection, cached_statements=128, \ + factory=sqlite3.Connection, cached_statements=100, \ uri=False) Open a connection to an SQLite database. @@ -270,9 +271,9 @@ :param float timeout: How many seconds the connection should wait before raising - an exception, if the database is locked by another connection. - If another connection opens a transaction to modify the database, - it will be locked until that transaction is committed. + an :exc:`OperationalError` when a table is locked. + If another connection opens a transaction to modify a table, + that table will be locked until the transaction is committed. Default five seconds. :param int detect_types: @@ -298,10 +299,13 @@ :type isolation_level: str | None :param bool check_same_thread: - If ``True`` (default), only the creating thread may use the connection. - If ``False``, the connection may be shared across multiple threads; - if so, write operations should be serialized by the user to avoid data - corruption. + If ``True`` (default), :exc:`ProgrammingError` will be raised + if the database connection is used by a thread + other than the one that created it. + If ``False``, the connection may be accessed in multiple threads; + write operations may need to be serialized by the user + to avoid data corruption. + See :attr:`threadsafety` for more information. :param Connection factory: A custom subclass of :class:`Connection` to create the connection with, @@ -452,10 +456,7 @@ .. note:: - The :mod:`!sqlite3` module supports both ``qmark`` and ``numeric`` DB-API - parameter styles, because that is what the underlying SQLite library - supports. However, the DB-API does not allow multiple values for - the ``paramstyle`` attribute. + The ``named`` DB-API parameter style is also supported. .. data:: sqlite_version @@ -515,103 +516,6 @@ An SQLite database connection has the following attributes and methods: - .. attribute:: isolation_level - - This attribute controls the :ref:`transaction handling - ` performed by :mod:`!sqlite3`. - If set to ``None``, transactions are never implicitly opened. - If set to one of ``"DEFERRED"``, ``"IMMEDIATE"``, or ``"EXCLUSIVE"``, - corresponding to the underlying `SQLite transaction behaviour`_, - implicit :ref:`transaction management - ` is performed. - - If not overridden by the *isolation_level* parameter of :func:`connect`, - the default is ``""``, which is an alias for ``"DEFERRED"``. - - .. attribute:: in_transaction - - This read-only attribute corresponds to the low-level SQLite - `autocommit mode`_. - - ``True`` if a transaction is active (there are uncommitted changes), - ``False`` otherwise. - - .. versionadded:: 3.2 - - .. attribute:: row_factory - - A callable that accepts two arguments, - a :class:`Cursor` object and the raw row results as a :class:`tuple`, - and returns a custom object representing an SQLite row. - - Example: - - .. doctest:: - - >>> def dict_factory(cursor, row): - ... col_names = [col[0] for col in cursor.description] - ... return {key: value for key, value in zip(col_names, row)} - >>> con = sqlite3.connect(":memory:") - >>> con.row_factory = dict_factory - >>> for row in con.execute("SELECT 1 AS a, 2 AS b"): - ... print(row) - {'a': 1, 'b': 2} - - If returning a tuple doesn't suffice and you want name-based access to - columns, you should consider setting :attr:`row_factory` to the - highly optimized :class:`sqlite3.Row` type. :class:`Row` provides both - index-based and case-insensitive name-based access to columns with almost no - memory overhead. It will probably be better than your own custom - dictionary-based approach or even a db_row based solution. - - .. XXX what's a db_row-based solution? - - .. attribute:: text_factory - - A callable that accepts a :class:`bytes` parameter and returns a text - representation of it. - The callable is invoked for SQLite values with the ``TEXT`` data type. - By default, this attribute is set to :class:`str`. - If you want to return ``bytes`` instead, set *text_factory* to ``bytes``. - - Example: - - .. testcode:: - - con = sqlite3.connect(":memory:") - cur = con.cursor() - - AUSTRIA = "Österreich" - - # by default, rows are returned as str - cur.execute("SELECT ?", (AUSTRIA,)) - row = cur.fetchone() - assert row[0] == AUSTRIA - - # but we can make sqlite3 always return bytestrings ... - con.text_factory = bytes - cur.execute("SELECT ?", (AUSTRIA,)) - row = cur.fetchone() - assert type(row[0]) is bytes - # the bytestrings will be encoded in UTF-8, unless you stored garbage in the - # database ... - assert row[0] == AUSTRIA.encode("utf-8") - - # we can also implement a custom text_factory ... - # here we implement one that appends "foo" to all strings - con.text_factory = lambda x: x.decode("utf-8") + "foo" - cur.execute("SELECT ?", ("bar",)) - row = cur.fetchone() - assert row[0] == "barfoo" - - con.close() - - .. attribute:: total_changes - - Return the total number of database rows that have been modified, inserted, or - deleted since the database connection was opened. - - .. method:: cursor(factory=Cursor) Create and return a :class:`Cursor` object. @@ -654,7 +558,7 @@ :meth:`~Cursor.executescript` on it with the given *sql_script*. Return the new cursor object. - .. method:: create_function(name, narg, func, \*, deterministic=False) + .. method:: create_function(name, narg, func, *, deterministic=False) Create or remove a user-defined SQL function. @@ -796,7 +700,7 @@ Call this method from a different thread to abort any queries that might be executing on the connection. - Aborted queries will raise an exception. + Aborted queries will raise an :exc:`OperationalError`. .. method:: set_authorizer(authorizer_callback) @@ -952,7 +856,7 @@ con.close() - .. method:: backup(target, \*, pages=-1, progress=None, name="main", sleep=0.250) + .. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250) Create a backup of an SQLite database. @@ -1017,6 +921,84 @@ .. versionadded:: 3.7 + .. attribute:: in_transaction + + This read-only attribute corresponds to the low-level SQLite + `autocommit mode`_. + + ``True`` if a transaction is active (there are uncommitted changes), + ``False`` otherwise. + + .. versionadded:: 3.2 + + .. attribute:: isolation_level + + This attribute controls the :ref:`transaction handling + ` performed by :mod:`!sqlite3`. + If set to ``None``, transactions are never implicitly opened. + If set to one of ``"DEFERRED"``, ``"IMMEDIATE"``, or ``"EXCLUSIVE"``, + corresponding to the underlying `SQLite transaction behaviour`_, + implicit :ref:`transaction management + ` is performed. + + If not overridden by the *isolation_level* parameter of :func:`connect`, + the default is ``""``, which is an alias for ``"DEFERRED"``. + + .. attribute:: row_factory + + The initial :attr:`~Cursor.row_factory` + for :class:`Cursor` objects created from this connection. + Assigning to this attribute does not affect the :attr:`!row_factory` + of existing cursors belonging to this connection, only new ones. + Is ``None`` by default, + meaning each row is returned as a :class:`tuple`. + + See :ref:`sqlite3-howto-row-factory` for more details. + + .. attribute:: text_factory + + A callable that accepts a :class:`bytes` parameter and returns a text + representation of it. + The callable is invoked for SQLite values with the ``TEXT`` data type. + By default, this attribute is set to :class:`str`. + If you want to return ``bytes`` instead, set *text_factory* to ``bytes``. + + Example: + + .. testcode:: + + con = sqlite3.connect(":memory:") + cur = con.cursor() + + AUSTRIA = "Österreich" + + # by default, rows are returned as str + cur.execute("SELECT ?", (AUSTRIA,)) + row = cur.fetchone() + assert row[0] == AUSTRIA + + # but we can make sqlite3 always return bytestrings ... + con.text_factory = bytes + cur.execute("SELECT ?", (AUSTRIA,)) + row = cur.fetchone() + assert type(row[0]) is bytes + # the bytestrings will be encoded in UTF-8, unless you stored garbage in the + # database ... + assert row[0] == AUSTRIA.encode("utf-8") + + # we can also implement a custom text_factory ... + # here we implement one that appends "foo" to all strings + con.text_factory = lambda x: x.decode("utf-8") + "foo" + cur.execute("SELECT ?", ("bar",)) + row = cur.fetchone() + assert row[0] == "barfoo" + + con.close() + + .. attribute:: total_changes + + Return the total number of database rows that have been modified, inserted, or + deleted since the database connection was opened. .. _sqlite3-cursor-objects: @@ -1062,30 +1044,53 @@ .. method:: execute(sql, parameters=(), /) - Execute SQL statement *sql*. - Bind values to the statement using :ref:`placeholders - ` that map to the :term:`sequence` or :class:`dict` - *parameters*. - - :meth:`execute` will only execute a single SQL statement. If you try to execute - more than one statement with it, it will raise a :exc:`Warning`. Use - :meth:`executescript` if you want to execute multiple SQL statements with one - call. + Execute SQL a single SQL statement, + optionally binding Python values using + :ref:`placeholders `. + + :param str sql: + A single SQL statement. + + :param parameters: + Python values to bind to placeholders in *sql*. + A :class:`!dict` if named placeholders are used. + A :term:`!sequence` if unnamed placeholders are used. + See :ref:`sqlite3-placeholders`. + :type parameters: :class:`dict` | :term:`sequence` + + :raises Warning: + If *sql* contains more than one SQL statement. If :attr:`~Connection.isolation_level` is not ``None``, *sql* is an ``INSERT``, ``UPDATE``, ``DELETE``, or ``REPLACE`` statement, and there is no open transaction, a transaction is implicitly opened before executing *sql*. + Use :meth:`executescript` to execute multiple SQL statements. .. method:: executemany(sql, parameters, /) - Execute :ref:`parameterized ` SQL statement *sql* - against all parameter sequences or mappings found in the sequence - *parameters*. It is also possible to use an - :term:`iterator` yielding parameters instead of a sequence. + For every item in *parameters*, + repeatedly execute the :ref:`parameterized ` + SQL statement *sql*. + Uses the same implicit transaction handling as :meth:`~Cursor.execute`. + :param str sql: + A single SQL :abbr:`DML (Data Manipulation Language)` statement. + + :param parameters: + An :term:`!iterable` of parameters to bind with + the placeholders in *sql*. + See :ref:`sqlite3-placeholders`. + :type parameters: :term:`iterable` + + :raises ProgrammingError: + If *sql* is not a DML statment. + + :raises Warning: + If *sql* contains more than one SQL statement. + Example: .. testcode:: sqlite3.cursor @@ -1123,7 +1128,9 @@ .. method:: fetchone() - Return the next row of a query result set as a :class:`tuple`. + If :attr:`~Cursor.row_factory` is ``None``, + return the next row query result set as a :class:`tuple`. + Else, pass it to the row factory and return its result. Return ``None`` if no more data is available. @@ -1215,6 +1222,22 @@ including :abbr:`CTE (Common Table Expression)` queries. It is only updated by the :meth:`execute` and :meth:`executemany` methods. + .. attribute:: row_factory + + Control how a row fetched from this :class:`!Cursor` is represented. + If ``None``, a row is represented as a :class:`tuple`. + Can be set to the included :class:`sqlite3.Row`; + or a :term:`callable` that accepts two arguments, + a :class:`Cursor` object and the :class:`!tuple` of row values, + and returns a custom object representing an SQLite row. + + Defaults to what :attr:`Connection.row_factory` was set to + when the :class:`!Cursor` was created. + Assigning to this attribute does not affect + :attr:`Connection.row_factory` of the parent connection. + + See :ref:`sqlite3-howto-row-factory` for more details. + .. The sqlite3.Row example used to be a how-to. It has now been incorporated into the Row reference. We keep the anchor here in order not to break @@ -1233,7 +1256,10 @@ It supports iteration, equality testing, :func:`len`, and :term:`mapping` access by column name and index. - Two row objects compare equal if have equal columns and equal members. + Two :class:`!Row` objects compare equal + if they have identical column names and values. + + See :ref:`sqlite3-howto-row-factory` for more details. .. method:: keys @@ -1244,21 +1270,6 @@ .. versionchanged:: 3.5 Added support of slicing. - Example: - - .. doctest:: - - >>> con = sqlite3.connect(":memory:") - >>> con.row_factory = sqlite3.Row - >>> res = con.execute("SELECT 'Earth' AS name, 6378 AS radius") - >>> row = res.fetchone() - >>> row.keys() - ['name', 'radius'] - >>> row[0], row["name"] # Access by index and name. - ('Earth', 'Earth') - >>> row["RADIUS"] # Column names are case-insensitive. - 6378 - PrepareProtocol objects ^^^^^^^^^^^^^^^^^^^^^^^ @@ -1438,44 +1449,50 @@ SQL operations usually need to use values from Python variables. However, beware of using Python's string operations to assemble queries, as they -are vulnerable to `SQL injection attacks`_ (see the `xkcd webcomic -`_ for a humorous example of what can go wrong):: +are vulnerable to `SQL injection attacks`_. For example, an attacker can simply +close the single quote and inject ``OR TRUE`` to select all rows:: - # Never do this -- insecure! - symbol = 'RHAT' - cur.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) + >>> # Never do this -- insecure! + >>> symbol = input() + ' OR TRUE; -- + >>> sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol + >>> print(sql) + SELECT * FROM stocks WHERE symbol = '' OR TRUE; --' + >>> cur.execute(sql) Instead, use the DB-API's parameter substitution. To insert a variable into a query string, use a placeholder in the string, and substitute the actual values into the query by providing them as a :class:`tuple` of values to the second -argument of the cursor's :meth:`~Cursor.execute` method. An SQL statement may -use one of two kinds of placeholders: question marks (qmark style) or named -placeholders (named style). For the qmark style, ``parameters`` must be a -:term:`sequence `. For the named style, it can be either a -:term:`sequence ` or :class:`dict` instance. The length of the -:term:`sequence ` must match the number of placeholders, or a -:exc:`ProgrammingError` is raised. If a :class:`dict` is given, it must contain -keys for all named parameters. Any extra items are ignored. Here's an example of -both styles: +argument of the cursor's :meth:`~Cursor.execute` method. + +An SQL statement may use one of two kinds of placeholders: +question marks (qmark style) or named placeholders (named style). +For the qmark style, *parameters* must be a +:term:`sequence` whose length must match the number of placeholders, +or a :exc:`ProgrammingError` is raised. +For the named style, *parameters* should be +an instance of a :class:`dict` (or a subclass), +which must contain keys for all named parameters; +any extra items are ignored. +Here's an example of both styles: .. testcode:: con = sqlite3.connect(":memory:") cur = con.execute("CREATE TABLE lang(name, first_appeared)") - # This is the qmark style: - cur.execute("INSERT INTO lang VALUES(?, ?)", ("C", 1972)) - - # The qmark style used with executemany(): - lang_list = [ - ("Fortran", 1957), - ("Python", 1991), - ("Go", 2009), - ] - cur.executemany("INSERT INTO lang VALUES(?, ?)", lang_list) - - # And this is the named style: - cur.execute("SELECT * FROM lang WHERE first_appeared = :year", {"year": 1972}) + # This is the named style used with executemany(): + data = ( + {"name": "C", "year": 1972}, + {"name": "Fortran", "year": 1957}, + {"name": "Python", "year": 1991}, + {"name": "Go", "year": 2009}, + ) + cur.executemany("INSERT INTO lang VALUES(:name, :year)", data) + + # This is the qmark style used in a SELECT query: + params = (1972,) + cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params) print(cur.fetchall()) .. testoutput:: @@ -1483,6 +1500,11 @@ [('C', 1972)] +.. note:: + + :pep:`249` numeric placeholders are *not* supported. + If used, they will be interpreted as named placeholders. + .. _sqlite3-adapters: @@ -1616,7 +1638,7 @@ return f"Point({self.x}, {self.y})" def adapt_point(point): - return f"{point.x};{point.y}".encode("utf-8") + return f"{point.x};{point.y}" def convert_point(s): x, y = list(map(float, s.split(b";"))) @@ -1682,20 +1704,39 @@ def convert_date(val): """Convert ISO 8601 date to datetime.date object.""" - return datetime.date.fromisoformat(val) + return datetime.date.fromisoformat(val.decode()) def convert_datetime(val): """Convert ISO 8601 datetime to datetime.datetime object.""" - return datetime.datetime.fromisoformat(val) + return datetime.datetime.fromisoformat(val.decode()) def convert_timestamp(val): """Convert Unix epoch timestamp to datetime.datetime object.""" - return datetime.datetime.fromtimestamp(val) + return datetime.datetime.fromtimestamp(int(val)) sqlite3.register_converter("date", convert_date) sqlite3.register_converter("datetime", convert_datetime) sqlite3.register_converter("timestamp", convert_timestamp) +.. testcode:: + :hide: + + dt = datetime.datetime(2019, 5, 18, 15, 17, 8, 123456) + + assert adapt_date_iso(dt.date()) == "2019-05-18" + assert convert_date(b"2019-05-18") == dt.date() + + assert adapt_datetime_iso(dt) == "2019-05-18T15:17:08.123456" + assert convert_datetime(b"2019-05-18T15:17:08.123456") == dt + + # Using current time as fromtimestamp() returns local date/time. + # Droping microseconds as adapt_datetime_epoch truncates fractional second part. + now = datetime.datetime.now().replace(microsecond=0) + current_timestamp = int(now.timestamp()) + + assert adapt_datetime_epoch(now) == current_timestamp + assert convert_timestamp(str(current_timestamp).encode()) == now + .. _sqlite3-connection-shortcuts: @@ -1835,6 +1876,96 @@ .. _SQLite URI documentation: https://www.sqlite.org/uri.html +.. _sqlite3-howto-row-factory: + +How to create and use row factories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, :mod:`!sqlite3` represents each row as a :class:`tuple`. +If a :class:`!tuple` does not suit your needs, +you can use the :class:`sqlite3.Row` class +or a custom :attr:`~Cursor.row_factory`. + +While :attr:`!row_factory` exists as an attribute both on the +:class:`Cursor` and the :class:`Connection`, +it is recommended to set :class:`Connection.row_factory`, +so all cursors created from the connection will use the same row factory. + +:class:`!Row` provides indexed and case-insensitive named access to columns, +with minimal memory overhead and performance impact over a :class:`!tuple`. +To use :class:`!Row` as a row factory, +assign it to the :attr:`!row_factory` attribute: + +.. doctest:: + + >>> con = sqlite3.connect(":memory:") + >>> con.row_factory = sqlite3.Row + +Queries now return :class:`!Row` objects: + +.. doctest:: + + >>> res = con.execute("SELECT 'Earth' AS name, 6378 AS radius") + >>> row = res.fetchone() + >>> row.keys() + ['name', 'radius'] + >>> row[0] # Access by index. + 'Earth' + >>> row["name"] # Access by name. + 'Earth' + >>> row["RADIUS"] # Column names are case-insensitive. + 6378 + +You can create a custom :attr:`~Cursor.row_factory` +that returns each row as a :class:`dict`, with column names mapped to values: + +.. testcode:: + + def dict_factory(cursor, row): + fields = [column[0] for column in cursor.description] + return {key: value for key, value in zip(fields, row)} + +Using it, queries now return a :class:`!dict` instead of a :class:`!tuple`: + +.. doctest:: + + >>> con = sqlite3.connect(":memory:") + >>> con.row_factory = dict_factory + >>> for row in con.execute("SELECT 1 AS a, 2 AS b"): + ... print(row) + {'a': 1, 'b': 2} + +The following row factory returns a :term:`named tuple`: + +.. testcode:: + + from collections import namedtuple + + def namedtuple_factory(cursor, row): + fields = [column[0] for column in cursor.description] + cls = namedtuple("Row", fields) + return cls._make(row) + +:func:`!namedtuple_factory` can be used as follows: + +.. doctest:: + + >>> con = sqlite3.connect(":memory:") + >>> con.row_factory = namedtuple_factory + >>> cur = con.execute("SELECT 1 AS a, 2 AS b") + >>> row = cur.fetchone() + >>> row + Row(a=1, b=2) + >>> row[0] # Indexed access. + 1 + >>> row.b # Attribute access. + 2 + +With some adjustments, the above recipe can be adapted to use a +:class:`~dataclasses.dataclass`, or any other custom class, +instead of a :class:`~collections.namedtuple`. + + .. _sqlite3-explanation: Explanation @@ -1852,7 +1983,8 @@ is not ``None``, new transactions are implicitly opened before :meth:`~Cursor.execute` and :meth:`~Cursor.executemany` executes -``INSERT``, ``UPDATE``, ``DELETE``, or ``REPLACE`` statements. +``INSERT``, ``UPDATE``, ``DELETE``, or ``REPLACE`` statements; +for other statements, no implicit transaction handling is performed. Use the :meth:`~Connection.commit` and :meth:`~Connection.rollback` methods to respectively commit and roll back pending transactions. You can choose the underlying `SQLite transaction behaviour`_ — diff -Nru python3.10-3.10.7/Doc/library/ssl.rst python3.10-3.10.12/Doc/library/ssl.rst --- python3.10-3.10.7/Doc/library/ssl.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/ssl.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1144,7 +1144,7 @@ .. versionchanged:: 3.5 The :meth:`shutdown` does not reset the socket timeout each time bytes - are received or sent. The socket timeout is now to maximum total duration + are received or sent. The socket timeout is now the maximum total duration of the shutdown. .. deprecated:: 3.6 @@ -1177,8 +1177,8 @@ cause write operations. .. versionchanged:: 3.5 - The socket timeout is no more reset each time bytes are received or sent. - The socket timeout is now to maximum total duration to read up to *len* + The socket timeout is no longer reset each time bytes are received or sent. + The socket timeout is now the maximum total duration to read up to *len* bytes. .. deprecated:: 3.6 @@ -1196,8 +1196,8 @@ also cause read operations. .. versionchanged:: 3.5 - The socket timeout is no more reset each time bytes are received or sent. - The socket timeout is now to maximum total duration to write *buf*. + The socket timeout is no longer reset each time bytes are received or sent. + The socket timeout is now the maximum total duration to write *buf*. .. deprecated:: 3.6 Use :meth:`~SSLSocket.send` instead of :meth:`~SSLSocket.write`. @@ -1224,14 +1224,14 @@ :attr:`~SSLSocket.context` is true. .. versionchanged:: 3.5 - The socket timeout is no more reset each time bytes are received or sent. - The socket timeout is now to maximum total duration of the handshake. + The socket timeout is no longer reset each time bytes are received or sent. + The socket timeout is now the maximum total duration of the handshake. .. versionchanged:: 3.7 Hostname or IP address is matched by OpenSSL during handshake. The function :func:`match_hostname` is no longer used. In case OpenSSL refuses a hostname or IP address, the handshake is aborted early and - a TLS alert message is send to the peer. + a TLS alert message is sent to the peer. .. method:: SSLSocket.getpeercert(binary_form=False) @@ -1311,7 +1311,7 @@ .. method:: SSLSocket.shared_ciphers() - Return the list of ciphers shared by the client during the handshake. Each + Return the list of ciphers available in both the client and server. Each entry of the returned list is a three-value tuple containing the name of the cipher, the version of the SSL protocol that defines its use, and the number of secret bits the cipher uses. :meth:`~SSLSocket.shared_ciphers` returns diff -Nru python3.10-3.10.7/Doc/library/statistics.rst python3.10-3.10.12/Doc/library/statistics.rst --- python3.10-3.10.7/Doc/library/statistics.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/statistics.rst 2023-06-06 22:30:33.000000000 +0000 @@ -786,7 +786,7 @@ The relative likelihood is computed as the probability of a sample occurring in a narrow range divided by the width of the range (hence the word "density"). Since the likelihood is relative to other points, - its value can be greater than `1.0`. + its value can be greater than ``1.0``. .. method:: NormalDist.cdf(x) diff -Nru python3.10-3.10.7/Doc/library/stdtypes.rst python3.10-3.10.12/Doc/library/stdtypes.rst --- python3.10-3.10.7/Doc/library/stdtypes.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/stdtypes.rst 2023-06-06 22:30:33.000000000 +0000 @@ -84,8 +84,8 @@ +-------------+---------------------------------+-------+ | Operation | Result | Notes | +=============+=================================+=======+ -| ``x or y`` | if *x* is false, then *y*, else | \(1) | -| | *x* | | +| ``x or y`` | if *x* is true, then *x*, else | \(1) | +| | *y* | | +-------------+---------------------------------+-------+ | ``x and y`` | if *x* is false, then *x*, else | \(2) | | | *y* | | @@ -215,7 +215,7 @@ There are three distinct numeric types: :dfn:`integers`, :dfn:`floating point numbers`, and :dfn:`complex numbers`. In addition, Booleans are a subtype of integers. Integers have unlimited precision. Floating point -numbers are usually implemented using :c:type:`double` in C; information +numbers are usually implemented using :c:expr:`double` in C; information about the precision and internal representation of floating point numbers for the machine on which your program is running is available in :data:`sys.float_info`. Complex numbers have a real and imaginary @@ -335,11 +335,10 @@ single: ceil() (in module math) single: trunc() (in module math) pair: numeric; conversions - pair: C; language - Conversion from floating point to integer may round or truncate - as in C; see functions :func:`math.floor` and :func:`math.ceil` for - well-defined conversions. + Conversion from :class:`float` to :class:`int` truncates, discarding the + fractional part. See functions :func:`math.floor` and :func:`math.ceil` for + alternative conversions. (4) float also accepts the strings "nan" and "inf" with an optional prefix "+" @@ -1579,28 +1578,34 @@ range [*start*, *end*]. Optional arguments *start* and *end* are interpreted as in slice notation. + If *sub* is empty, returns the number of empty strings between characters + which is the length of the string plus one. + .. method:: str.encode(encoding="utf-8", errors="strict") - Return an encoded version of the string as a bytes object. Default encoding - is ``'utf-8'``. *errors* may be given to set a different error handling scheme. - The default for *errors* is ``'strict'``, meaning that encoding errors raise - a :exc:`UnicodeError`. Other possible - values are ``'ignore'``, ``'replace'``, ``'xmlcharrefreplace'``, - ``'backslashreplace'`` and any other name registered via - :func:`codecs.register_error`, see section :ref:`error-handlers`. For a - list of possible encodings, see section :ref:`standard-encodings`. - - By default, the *errors* argument is not checked for best performances, but - only used at the first encoding error. Enable the :ref:`Python Development - Mode `, or use a :ref:`debug build ` to check - *errors*. + Return the string encoded to :class:`bytes`. + + *encoding* defaults to ``'utf-8'``; + see :ref:`standard-encodings` for possible values. + + *errors* controls how encoding errors are handled. + If ``'strict'`` (the default), a :exc:`UnicodeError` exception is raised. + Other possible values are ``'ignore'``, + ``'replace'``, ``'xmlcharrefreplace'``, ``'backslashreplace'`` and any + other name registered via :func:`codecs.register_error`. + See :ref:`error-handlers` for details. + + For performance reasons, the value of *errors* is not checked for validity + unless an encoding error actually occurs, + :ref:`devmode` is enabled + or a :ref:`debug build ` is used. .. versionchanged:: 3.1 - Support for keyword arguments added. + Added support for keyword arguments. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and + The value of the *errors* argument is now checked in :ref:`devmode` and in :ref:`debug mode `. @@ -2658,6 +2663,9 @@ The subsequence to search for may be any :term:`bytes-like object` or an integer in the range 0 to 255. + If *sub* is empty, returns the number of empty slices between characters + which is the length of the bytes object plus one. + .. versionchanged:: 3.3 Also accept an integer in the range 0 to 255 as the subsequence. @@ -2709,29 +2717,32 @@ .. method:: bytes.decode(encoding="utf-8", errors="strict") bytearray.decode(encoding="utf-8", errors="strict") - Return a string decoded from the given bytes. Default encoding is - ``'utf-8'``. *errors* may be given to set a different - error handling scheme. The default for *errors* is ``'strict'``, meaning - that encoding errors raise a :exc:`UnicodeError`. Other possible values are - ``'ignore'``, ``'replace'`` and any other name registered via - :func:`codecs.register_error`, see section :ref:`error-handlers`. For a - list of possible encodings, see section :ref:`standard-encodings`. - - By default, the *errors* argument is not checked for best performances, but - only used at the first decoding error. Enable the :ref:`Python Development - Mode `, or use a :ref:`debug build ` to check *errors*. + Return the bytes decoded to a :class:`str`. + + *encoding* defaults to ``'utf-8'``; + see :ref:`standard-encodings` for possible values. + + *errors* controls how decoding errors are handled. + If ``'strict'`` (the default), a :exc:`UnicodeError` exception is raised. + Other possible values are ``'ignore'``, ``'replace'``, + and any other name registered via :func:`codecs.register_error`. + See :ref:`error-handlers` for details. + + For performance reasons, the value of *errors* is not checked for validity + unless a decoding error actually occurs, + :ref:`devmode` is enabled or a :ref:`debug build ` is used. .. note:: Passing the *encoding* argument to :class:`str` allows decoding any :term:`bytes-like object` directly, without needing to make a temporary - bytes or bytearray object. + :class:`!bytes` or :class:`!bytearray` object. .. versionchanged:: 3.1 Added support for keyword arguments. .. versionchanged:: 3.9 - The *errors* is now checked in development mode and + The value of the *errors* argument is now checked in :ref:`devmode` and in :ref:`debug mode `. @@ -3713,7 +3724,7 @@ >>> data bytearray(b'z1spam') - One-dimensional memoryviews of hashable (read-only) types with formats + One-dimensional memoryviews of :term:`hashable` (read-only) types with formats 'B', 'b' or 'c' are also hashable. The hash is defined as ``hash(m) == hash(m.tobytes())``:: @@ -3727,7 +3738,7 @@ .. versionchanged:: 3.3 One-dimensional memoryviews can now be sliced. - One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable. + One-dimensional memoryviews with formats 'B', 'b' or 'c' are now :term:`hashable`. .. versionchanged:: 3.4 memoryview is now registered automatically with @@ -4330,11 +4341,9 @@ A dictionary's keys are *almost* arbitrary values. Values that are not :term:`hashable`, that is, values containing lists, dictionaries or other mutable types (that are compared by value rather than by object identity) may -not be used as keys. Numeric types used for keys obey the normal rules for -numeric comparison: if two numbers compare equal (such as ``1`` and ``1.0``) -then they can be used interchangeably to index the same dictionary entry. (Note -however, that since computers store floating-point numbers as approximations it -is usually unwise to use them as dictionary keys.) +not be used as keys. +Values that compare equal (such as ``1``, ``1.0``, and ``True``) +can be used interchangeably to index the same dictionary entry. .. class:: dict(**kwargs) dict(mapping, **kwargs) @@ -4649,7 +4658,7 @@ .. versionadded:: 3.10 -Keys views are set-like since their entries are unique and hashable. If all +Keys views are set-like since their entries are unique and :term:`hashable`. If all values are hashable, so that ``(key, value)`` pairs are unique and hashable, then the items view is also set-like. (Values views are not treated as set-like since the entries are generally not unique.) For set-like views, all of the @@ -4689,7 +4698,7 @@ >>> # get back a read-only proxy for the original dictionary >>> values.mapping - mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}) + mappingproxy({'bacon': 1, 'spam': 500}) >>> values.mapping['spam'] 500 @@ -5417,7 +5426,7 @@ other non-power-of-two number bases. Hexadecimal, octal, and binary conversions are unlimited. The limit can be configured. -The :class:`int` type in CPython is an abitrary length number stored in binary +The :class:`int` type in CPython is an arbitrary length number stored in binary form (commonly known as a "bignum"). There exists no algorithm that can convert a string to a binary integer or a binary integer to a string in linear time, *unless* the base is a power of 2. Even the best known algorithms for base 10 @@ -5440,7 +5449,7 @@ >>> _ = int('2' * 5432) Traceback (most recent call last): ... - ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits. + ValueError: Exceeds the limit (4300) for integer string conversion: value has 5432 digits; use sys.set_int_max_str_digits() to increase the limit. >>> i = int('2' * 4300) >>> len(str(i)) 4300 @@ -5448,7 +5457,7 @@ >>> len(str(i_squared)) Traceback (most recent call last): ... - ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits. + ValueError: Exceeds the limit (4300) for integer string conversion: value has 8599 digits; use sys.set_int_max_str_digits() to increase the limit. >>> len(hex(i_squared)) 7144 >>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited. @@ -5481,7 +5490,7 @@ * ``int(string)`` with default base 10. * ``int(string, base)`` for all bases that are not a power of 2. * ``str(integer)``. -* ``repr(integer)`` +* ``repr(integer)``. * any other string conversion to base 10, for example ``f"{integer}"``, ``"{}".format(integer)``, or ``b"%d" % integer``. @@ -5509,7 +5518,7 @@ :envvar:`PYTHONINTMAXSTRDIGITS` or :option:`-X int_max_str_digits <-X>`. If both the env var and the ``-X`` option are set, the ``-X`` option takes precedence. A value of *-1* indicates that both were unset, thus a value of - :data:`sys.int_info.default_max_str_digits` was used during initilization. + :data:`sys.int_info.default_max_str_digits` was used during initialization. From code, you can inspect the current limit and set a new one using these :mod:`sys` APIs: diff -Nru python3.10-3.10.7/Doc/library/struct.rst python3.10-3.10.12/Doc/library/struct.rst --- python3.10-3.10.7/Doc/library/struct.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/struct.rst 2023-06-06 22:30:33.000000000 +0000 @@ -12,21 +12,25 @@ -------------- -This module performs conversions between Python values and C structs represented -as Python :class:`bytes` objects. This can be used in handling binary data -stored in files or from network connections, among other sources. It uses -:ref:`struct-format-strings` as compact descriptions of the layout of the C -structs and the intended conversion to/from Python values. +This module converts between Python values and C structs represented +as Python :class:`bytes` objects. Compact :ref:`format strings ` +describe the intended conversions to/from Python values. +The module's functions and objects can be used for two largely +distinct applications, data exchange with external sources (files or +network connections), or data transfer between the Python application +and the C layer. .. note:: - By default, the result of packing a given C struct includes pad bytes in - order to maintain proper alignment for the C types involved; similarly, - alignment is taken into account when unpacking. This behavior is chosen so - that the bytes of a packed struct correspond exactly to the layout in memory - of the corresponding C struct. To handle platform-independent data formats - or omit implicit pad bytes, use ``standard`` size and alignment instead of - ``native`` size and alignment: see :ref:`struct-alignment` for details. + When no prefix character is given, native mode is the default. It + packs or unpacks data based on the platform and compiler on which + the Python interpreter was built. + The result of packing a given C struct includes pad bytes which + maintain proper alignment for the C types involved; similarly, + alignment is taken into account when unpacking. In contrast, when + communicating data between external sources, the programmer is + responsible for defining byte ordering and padding between elements. + See :ref:`struct-alignment` for details. Several :mod:`struct` functions (and methods of :class:`Struct`) take a *buffer* argument. This refers to objects that implement the :ref:`bufferobjects` and @@ -102,10 +106,13 @@ Format Strings -------------- -Format strings are the mechanism used to specify the expected layout when -packing and unpacking data. They are built up from :ref:`format-characters`, -which specify the type of data being packed/unpacked. In addition, there are -special characters for controlling the :ref:`struct-alignment`. +Format strings describe the data layout when +packing and unpacking data. They are built up from :ref:`format characters`, +which specify the type of data being packed/unpacked. In addition, +special characters control the :ref:`byte order, size and alignment`. +Each format string consists of an optional prefix character which +describes the overall properties of the data and one or more format +characters which describe the actual data values and padding. .. _struct-alignment: @@ -116,6 +123,11 @@ By default, C types are represented in the machine's native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler). +This behavior is chosen so +that the bytes of a packed struct correspond exactly to the memory layout +of the corresponding C struct. +Whether to use native byte ordering +and padding or standard formats depends on the application. .. index:: single: @ (at); in struct format strings @@ -144,12 +156,10 @@ If the first character is not one of these, ``'@'`` is assumed. -Native byte order is big-endian or little-endian, depending on the host -system. For example, Intel x86 and AMD64 (x86-64) are little-endian; -IBM z and most legacy architectures are big-endian; -and ARM, RISC-V and IBM Power feature switchable endianness -(bi-endian, though the former two are nearly always little-endian in practice). -Use ``sys.byteorder`` to check the endianness of your system. +Native byte order is big-endian or little-endian, depending on the +host system. For example, Intel x86, AMD64 (x86-64), and Apple M1 are +little-endian; IBM z and many legacy architectures are big-endian. +Use :data:`sys.byteorder` to check the endianness of your system. Native size and alignment are determined using the C compiler's ``sizeof`` expression. This is always combined with native byte order. @@ -194,48 +204,48 @@ +--------+--------------------------+--------------------+----------------+------------+ | Format | C Type | Python type | Standard size | Notes | +========+==========================+====================+================+============+ -| ``x`` | pad byte | no value | | | +| ``x`` | pad byte | no value | | \(7) | +--------+--------------------------+--------------------+----------------+------------+ -| ``c`` | :c:type:`char` | bytes of length 1 | 1 | | +| ``c`` | :c:expr:`char` | bytes of length 1 | 1 | | +--------+--------------------------+--------------------+----------------+------------+ -| ``b`` | :c:type:`signed char` | integer | 1 | \(1), \(2) | +| ``b`` | :c:expr:`signed char` | integer | 1 | \(1), \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``B`` | :c:type:`unsigned char` | integer | 1 | \(2) | +| ``B`` | :c:expr:`unsigned char` | integer | 1 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``?`` | :c:type:`_Bool` | bool | 1 | \(1) | +| ``?`` | :c:expr:`_Bool` | bool | 1 | \(1) | +--------+--------------------------+--------------------+----------------+------------+ -| ``h`` | :c:type:`short` | integer | 2 | \(2) | +| ``h`` | :c:expr:`short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``H`` | :c:type:`unsigned short` | integer | 2 | \(2) | +| ``H`` | :c:expr:`unsigned short` | integer | 2 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``i`` | :c:type:`int` | integer | 4 | \(2) | +| ``i`` | :c:expr:`int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``I`` | :c:type:`unsigned int` | integer | 4 | \(2) | +| ``I`` | :c:expr:`unsigned int` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``l`` | :c:type:`long` | integer | 4 | \(2) | +| ``l`` | :c:expr:`long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``L`` | :c:type:`unsigned long` | integer | 4 | \(2) | +| ``L`` | :c:expr:`unsigned long` | integer | 4 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``q`` | :c:type:`long long` | integer | 8 | \(2) | +| ``q`` | :c:expr:`long long` | integer | 8 | \(2) | +--------+--------------------------+--------------------+----------------+------------+ -| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2) | +| ``Q`` | :c:expr:`unsigned long | integer | 8 | \(2) | | | long` | | | | +--------+--------------------------+--------------------+----------------+------------+ -| ``n`` | :c:type:`ssize_t` | integer | | \(3) | +| ``n`` | :c:expr:`ssize_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ -| ``N`` | :c:type:`size_t` | integer | | \(3) | +| ``N`` | :c:expr:`size_t` | integer | | \(3) | +--------+--------------------------+--------------------+----------------+------------+ | ``e`` | \(6) | float | 2 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``f`` | :c:type:`float` | float | 4 | \(4) | +| ``f`` | :c:expr:`float` | float | 4 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``d`` | :c:type:`double` | float | 8 | \(4) | +| ``d`` | :c:expr:`double` | float | 8 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ -| ``s`` | :c:type:`char[]` | bytes | | | +| ``s`` | :c:expr:`char[]` | bytes | | \(9) | +--------+--------------------------+--------------------+----------------+------------+ -| ``p`` | :c:type:`char[]` | bytes | | | +| ``p`` | :c:expr:`char[]` | bytes | | \(8) | +--------+--------------------------+--------------------+----------------+------------+ -| ``P`` | :c:type:`void \*` | integer | | \(5) | +| ``P`` | :c:expr:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 @@ -250,8 +260,8 @@ (1) .. index:: single: ? (question mark); in struct format strings - The ``'?'`` conversion code corresponds to the :c:type:`_Bool` type defined by - C99. If this type is not available, it is simulated using a :c:type:`char`. In + The ``'?'`` conversion code corresponds to the :c:expr:`_Bool` type defined by + C99. If this type is not available, it is simulated using a :c:expr:`char`. In standard mode, it is always represented by one byte. (2) @@ -291,6 +301,34 @@ operations. See the Wikipedia page on the `half-precision floating-point format `_ for more information. +(7) + When packing, ``'x'`` inserts one NUL byte. + +(8) + The ``'p'`` format character encodes a "Pascal string", meaning a short + variable-length string stored in a *fixed number of bytes*, given by the count. + The first byte stored is the length of the string, or 255, whichever is + smaller. The bytes of the string follow. If the string passed in to + :func:`pack` is too long (longer than the count minus 1), only the leading + ``count-1`` bytes of the string are stored. If the string is shorter than + ``count-1``, it is padded with null bytes so that exactly count bytes in all + are used. Note that for :func:`unpack`, the ``'p'`` format character consumes + ``count`` bytes, but that the string returned can never contain more than 255 + bytes. + +(9) + For the ``'s'`` format character, the count is interpreted as the length of the + bytes, not a repeat count like for the other format characters; for example, + ``'10s'`` means a single 10-byte string mapping to or from a single + Python byte string, while ``'10c'`` means 10 + separate one byte character elements (e.g., ``cccccccccc``) mapping + to or from ten different Python byte objects. (See :ref:`struct-examples` + for a concrete demonstration of the difference.) + If a count is not given, it defaults to 1. For packing, the string is + truncated or padded with null bytes as appropriate to make it fit. For + unpacking, the resulting bytes object always has exactly the specified number + of bytes. As a special case, ``'0s'`` means a single, empty string (while + ``'0c'`` means 0 characters). A format character may be preceded by an integral repeat count. For example, the format string ``'4h'`` means exactly the same as ``'hhhh'``. @@ -298,15 +336,6 @@ Whitespace characters between formats are ignored; a count and its format must not contain whitespace though. -For the ``'s'`` format character, the count is interpreted as the length of the -bytes, not a repeat count like for the other format characters; for example, -``'10s'`` means a single 10-byte string, while ``'10c'`` means 10 characters. -If a count is not given, it defaults to 1. For packing, the string is -truncated or padded with null bytes as appropriate to make it fit. For -unpacking, the resulting bytes object always has exactly the specified number -of bytes. As a special case, ``'0s'`` means a single, empty string (while -``'0c'`` means 0 characters). - When packing a value ``x`` using one of the integer formats (``'b'``, ``'B'``, ``'h'``, ``'H'``, ``'i'``, ``'I'``, ``'l'``, ``'L'``, ``'q'``, ``'Q'``), if ``x`` is outside the valid range for that format @@ -316,17 +345,6 @@ Previously, some of the integer formats wrapped out-of-range values and raised :exc:`DeprecationWarning` instead of :exc:`struct.error`. -The ``'p'`` format character encodes a "Pascal string", meaning a short -variable-length string stored in a *fixed number of bytes*, given by the count. -The first byte stored is the length of the string, or 255, whichever is -smaller. The bytes of the string follow. If the string passed in to -:func:`pack` is too long (longer than the count minus 1), only the leading -``count-1`` bytes of the string are stored. If the string is shorter than -``count-1``, it is padded with null bytes so that exactly count bytes in all -are used. Note that for :func:`unpack`, the ``'p'`` format character consumes -``count`` bytes, but that the string returned can never contain more than 255 -bytes. - .. index:: single: ? (question mark); in struct format strings For the ``'?'`` format character, the return value is either :const:`True` or @@ -342,18 +360,36 @@ ^^^^^^^^ .. note:: - All examples assume a native byte order, size, and alignment with a - big-endian machine. - -A basic example of packing/unpacking three integers:: - - >>> from struct import * - >>> pack('hhl', 1, 2, 3) - b'\x00\x01\x00\x02\x00\x00\x00\x03' - >>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03') - (1, 2, 3) - >>> calcsize('hhl') - 8 + Native byte order examples (designated by the ``'@'`` format prefix or + lack of any prefix character) may not match what the reader's + machine produces as + that depends on the platform and compiler. + +Pack and unpack integers of three different sizes, using big endian +ordering:: + + >>> from struct import * + >>> pack(">bhl", 1, 2, 3) + b'\x01\x00\x02\x00\x00\x00\x03' + >>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03') + (1, 2, 3) + >>> calcsize('>bhl') + 7 + +Attempt to pack an integer which is too large for the defined field:: + + >>> pack(">h", 99999) + Traceback (most recent call last): + File "", line 1, in + struct.error: 'h' format requires -32768 <= number <= 32767 + +Demonstrate the difference between ``'s'`` and ``'c'`` format +characters:: + + >>> pack("@ccc", b'1', b'2', b'3') + b'123' + >>> pack("@3s", b'123') + b'123' Unpacked fields can be named by assigning them to variables or by wrapping the result in a named tuple:: @@ -366,35 +402,132 @@ >>> Student._make(unpack('<10sHHb', record)) Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8) -The ordering of format characters may have an impact on size since the padding -needed to satisfy alignment requirements is different:: - - >>> pack('ci', b'*', 0x12131415) - b'*\x00\x00\x00\x12\x13\x14\x15' - >>> pack('ic', 0x12131415, b'*') - b'\x12\x13\x14\x15*' - >>> calcsize('ci') +The ordering of format characters may have an impact on size in native +mode since padding is implicit. In standard mode, the user is +responsible for inserting any desired padding. +Note in +the first ``pack`` call below that three NUL bytes were added after the +packed ``'#'`` to align the following integer on a four-byte boundary. +In this example, the output was produced on a little endian machine:: + + >>> pack('@ci', b'#', 0x12131415) + b'#\x00\x00\x00\x15\x14\x13\x12' + >>> pack('@ic', 0x12131415, b'#') + b'\x15\x14\x13\x12#' + >>> calcsize('@ci') 8 - >>> calcsize('ic') + >>> calcsize('@ic') 5 -The following format ``'llh0l'`` specifies two pad bytes at the end, assuming -longs are aligned on 4-byte boundaries:: +The following format ``'llh0l'`` results in two pad bytes being added +at the end, assuming the platform's longs are aligned on 4-byte boundaries:: - >>> pack('llh0l', 1, 2, 3) + >>> pack('@llh0l', 1, 2, 3) b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00' -This only works when native size and alignment are in effect; standard size and -alignment does not enforce any alignment. - .. seealso:: Module :mod:`array` Packed binary storage of homogeneous data. - Module :mod:`xdrlib` - Packing and unpacking of XDR data. + Module :mod:`json` + JSON encoder and decoder. + + Module :mod:`pickle` + Python object serialization. + + +.. _applications: + +Applications +------------ + +Two main applications for the :mod:`struct` module exist, data +interchange between Python and C code within an application or another +application compiled using the same compiler (:ref:`native formats`), and +data interchange between applications using agreed upon data layout +(:ref:`standard formats`). Generally speaking, the format strings +constructed for these two domains are distinct. + + +.. _struct-native-formats: + +Native Formats +^^^^^^^^^^^^^^ + +When constructing format strings which mimic native layouts, the +compiler and machine architecture determine byte ordering and padding. +In such cases, the ``@`` format character should be used to specify +native byte ordering and data sizes. Internal pad bytes are normally inserted +automatically. It is possible that a zero-repeat format code will be +needed at the end of a format string to round up to the correct +byte boundary for proper alignment of consective chunks of data. + +Consider these two simple examples (on a 64-bit, little-endian +machine):: + + >>> calcsize('@lhl') + 24 + >>> calcsize('@llh') + 18 + +Data is not padded to an 8-byte boundary at the end of the second +format string without the use of extra padding. A zero-repeat format +code solves that problem:: + + >>> calcsize('@llh0l') + 24 + +The ``'x'`` format code can be used to specify the repeat, but for +native formats it is better to use a zero-repeat format like ``'0l'``. + +By default, native byte ordering and alignment is used, but it is +better to be explicit and use the ``'@'`` prefix character. + + +.. _struct-standard-formats: + +Standard Formats +^^^^^^^^^^^^^^^^ + +When exchanging data beyond your process such as networking or storage, +be precise. Specify the exact byte order, size, and alignment. Do +not assume they match the native order of a particular machine. +For example, network byte order is big-endian, while many popular CPUs +are little-endian. By defining this explicitly, the user need not +care about the specifics of the platform their code is running on. +The first character should typically be ``<`` or ``>`` +(or ``!``). Padding is the responsibility of the programmer. The +zero-repeat format character won't work. Instead, the user must +explicitly add ``'x'`` pad bytes where needed. Revisiting the +examples from the previous section, we have:: + + >>> calcsize('>> pack('>> calcsize('@llh') + 18 + >>> pack('@llh', 1, 2, 3) == pack('>> calcsize('>> calcsize('@llh0l') + 24 + >>> pack('@llh0l', 1, 2, 3) == pack('>> calcsize('>> calcsize('@llh0l') + 12 + >>> pack('@llh0l', 1, 2, 3) == pack('` (:option:`configure + If Python is :ref:`built in debug mode ` (:option:`configure --with-pydebug option <--with-pydebug>`), it also performs some expensive internal consistency checks. @@ -320,7 +329,7 @@ files to (and read them from) a parallel directory tree rooted at this directory, rather than from ``__pycache__`` directories in the source code tree. Any ``__pycache__`` directories in the source code tree will be ignored - and new `.pyc` files written within the pycache prefix. Thus if you use + and new ``.pyc`` files written within the pycache prefix. Thus if you use :mod:`compileall` as a pre-build step, you must ensure you run it with the same pycache prefix (if any) that you will use at runtime. @@ -513,49 +522,55 @@ .. tabularcolumns:: |l|l|L| - +---------------------+----------------+--------------------------------------------------+ - | attribute | float.h macro | explanation | - +=====================+================+==================================================+ - | :const:`epsilon` | DBL_EPSILON | difference between 1.0 and the least value | - | | | greater than 1.0 that is representable as a float| - | | | | - | | | See also :func:`math.ulp`. | - +---------------------+----------------+--------------------------------------------------+ - | :const:`dig` | DBL_DIG | maximum number of decimal digits that can be | - | | | faithfully represented in a float; see below | - +---------------------+----------------+--------------------------------------------------+ - | :const:`mant_dig` | DBL_MANT_DIG | float precision: the number of base-``radix`` | - | | | digits in the significand of a float | - +---------------------+----------------+--------------------------------------------------+ - | :const:`max` | DBL_MAX | maximum representable positive finite float | - +---------------------+----------------+--------------------------------------------------+ - | :const:`max_exp` | DBL_MAX_EXP | maximum integer *e* such that ``radix**(e-1)`` is| - | | | a representable finite float | - +---------------------+----------------+--------------------------------------------------+ - | :const:`max_10_exp` | DBL_MAX_10_EXP | maximum integer *e* such that ``10**e`` is in the| - | | | range of representable finite floats | - +---------------------+----------------+--------------------------------------------------+ - | :const:`min` | DBL_MIN | minimum representable positive *normalized* float| - | | | | - | | | Use :func:`math.ulp(0.0) ` to get the | - | | | smallest positive *denormalized* representable | - | | | float. | - +---------------------+----------------+--------------------------------------------------+ - | :const:`min_exp` | DBL_MIN_EXP | minimum integer *e* such that ``radix**(e-1)`` is| - | | | a normalized float | - +---------------------+----------------+--------------------------------------------------+ - | :const:`min_10_exp` | DBL_MIN_10_EXP | minimum integer *e* such that ``10**e`` is a | - | | | normalized float | - +---------------------+----------------+--------------------------------------------------+ - | :const:`radix` | FLT_RADIX | radix of exponent representation | - +---------------------+----------------+--------------------------------------------------+ - | :const:`rounds` | FLT_ROUNDS | integer constant representing the rounding mode | - | | | used for arithmetic operations. This reflects | - | | | the value of the system FLT_ROUNDS macro at | - | | | interpreter startup time. See section 5.2.4.2.2 | - | | | of the C99 standard for an explanation of the | - | | | possible values and their meanings. | - +---------------------+----------------+--------------------------------------------------+ + +---------------------+---------------------+--------------------------------------------------+ + | attribute | float.h macro | explanation | + +=====================+=====================+==================================================+ + | ``epsilon`` | ``DBL_EPSILON`` | difference between 1.0 and the least value | + | | | greater than 1.0 that is representable as a float| + | | | | + | | | See also :func:`math.ulp`. | + +---------------------+---------------------+--------------------------------------------------+ + | ``dig`` | ``DBL_DIG`` | maximum number of decimal digits that can be | + | | | faithfully represented in a float; see below | + +---------------------+---------------------+--------------------------------------------------+ + | ``mant_dig`` | ``DBL_MANT_DIG`` | float precision: the number of base-``radix`` | + | | | digits in the significand of a float | + +---------------------+---------------------+--------------------------------------------------+ + | ``max`` | ``DBL_MAX`` | maximum representable positive finite float | + +---------------------+---------------------+--------------------------------------------------+ + | ``max_exp`` | ``DBL_MAX_EXP`` | maximum integer *e* such that ``radix**(e-1)`` is| + | | | a representable finite float | + +---------------------+---------------------+--------------------------------------------------+ + | ``max_10_exp`` | ``DBL_MAX_10_EXP`` | maximum integer *e* such that ``10**e`` is in the| + | | | range of representable finite floats | + +---------------------+---------------------+--------------------------------------------------+ + | ``min`` | ``DBL_MIN`` | minimum representable positive *normalized* float| + | | | | + | | | Use :func:`math.ulp(0.0) ` to get the | + | | | smallest positive *denormalized* representable | + | | | float. | + +---------------------+---------------------+--------------------------------------------------+ + | ``min_exp`` | ``DBL_MIN_EXP`` | minimum integer *e* such that ``radix**(e-1)`` is| + | | | a normalized float | + +---------------------+---------------------+--------------------------------------------------+ + | ``min_10_exp`` | ``DBL_MIN_10_EXP`` | minimum integer *e* such that ``10**e`` is a | + | | | normalized float | + +---------------------+---------------------+--------------------------------------------------+ + | ``radix`` | ``FLT_RADIX`` | radix of exponent representation | + +---------------------+---------------------+--------------------------------------------------+ + | ``rounds`` | ``FLT_ROUNDS`` | integer representing the rounding mode for | + | | | floating-point arithmetic. This reflects the | + | | | value of the system ``FLT_ROUNDS`` macro at | + | | | interpreter startup time: | + | | | ``-1`` indeterminable, | + | | | ``0`` toward zero, | + | | | ``1`` to nearest, | + | | | ``2`` toward positive infinity, | + | | | ``3`` toward negative infinity | + | | | | + | | | All other values for ``FLT_ROUNDS`` characterize | + | | | implementation-defined rounding behavior. | + +---------------------+---------------------+--------------------------------------------------+ The attribute :attr:`sys.float_info.dig` needs further explanation. If ``s`` is any string representing a decimal number with at most @@ -636,7 +651,7 @@ the encoding used with the :term:`filesystem error handler ` to convert between Unicode filenames and bytes filenames. The filesystem error handler is returned from - :func:`getfilesystemencoding`. + :func:`getfilesystemencodeerrors`. For best compatibility, str should be used for filenames in all cases, although representing filenames as bytes is also supported. Functions @@ -828,7 +843,7 @@ .. function:: get_asyncgen_hooks() Returns an *asyncgen_hooks* object, which is similar to a - :class:`~collections.namedtuple` of the form `(firstiter, finalizer)`, + :class:`~collections.namedtuple` of the form ``(firstiter, finalizer)``, where *firstiter* and *finalizer* are expected to be either ``None`` or functions which take an :term:`asynchronous generator iterator` as an argument, and are used to schedule finalization of an asynchronous @@ -1239,7 +1254,7 @@ A string giving the site-specific directory prefix where the platform independent Python files are installed; on Unix, the default is - ``'/usr/local'``. This can be set at build time with the ``--prefix`` + :file:`/usr/local`. This can be set at build time with the :option:`--prefix` argument to the :program:`configure` script. See :ref:`installation_paths` for derived paths. @@ -1278,7 +1293,7 @@ .. availability:: Unix. -.. function:: set_int_max_str_digits(n) +.. function:: set_int_max_str_digits(maxdigits) Set the :ref:`integer string conversion length limitation ` used by this interpreter. See also @@ -1741,7 +1756,7 @@ The version number used to form registry keys on Windows platforms. This is stored as string resource 1000 in the Python DLL. The value is normally the - first three characters of :const:`version`. It is provided in the :mod:`sys` + major and minor versions of the running Python interpreter. It is provided in the :mod:`sys` module for informational purposes; modifying this value has no effect on the registry keys used by Python. diff -Nru python3.10-3.10.7/Doc/library/tarfile.rst python3.10-3.10.12/Doc/library/tarfile.rst --- python3.10-3.10.7/Doc/library/tarfile.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tarfile.rst 2023-06-06 22:30:33.000000000 +0000 @@ -206,6 +206,38 @@ Is raised by :meth:`TarInfo.frombuf` if the buffer it gets is invalid. +.. exception:: FilterError + + Base class for members :ref:`refused ` by + filters. + + .. attribute:: tarinfo + + Information about the member that the filter refused to extract, + as :ref:`TarInfo `. + +.. exception:: AbsolutePathError + + Raised to refuse extracting a member with an absolute path. + +.. exception:: OutsideDestinationError + + Raised to refuse extracting a member outside the destination directory. + +.. exception:: SpecialFileError + + Raised to refuse extracting a special file (e.g. a device or pipe). + +.. exception:: AbsoluteLinkError + + Raised to refuse extracting a symbolic link with an absolute path. + +.. exception:: LinkOutsideDestinationError + + Raised to refuse extracting a symbolic link pointing outside the destination + directory. + + The following constants are available at the module level: .. data:: ENCODING @@ -276,7 +308,7 @@ .. versionadded:: 3.2 Added support for the context management protocol. -.. class:: TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors='surrogateescape', pax_headers=None, debug=0, errorlevel=0) +.. class:: TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors='surrogateescape', pax_headers=None, debug=0, errorlevel=1) All following arguments are optional and can be accessed as instance attributes as well. @@ -316,11 +348,8 @@ *debug* can be set from ``0`` (no debug messages) up to ``3`` (all debug messages). The messages are written to ``sys.stderr``. - If *errorlevel* is ``0``, all errors are ignored when using :meth:`TarFile.extract`. - Nevertheless, they appear as error messages in the debug output, when debugging - is enabled. If ``1``, all *fatal* errors are raised as :exc:`OSError` - exceptions. If ``2``, all *non-fatal* errors are raised as :exc:`TarError` - exceptions as well. + *errorlevel* controls how extraction errors are handled, + see :attr:`the corresponding attribute <~TarFile.errorlevel>`. The *encoding* and *errors* arguments define the character encoding to be used for reading or writing the archive and how conversion errors are going @@ -387,7 +416,7 @@ available. -.. method:: TarFile.extractall(path=".", members=None, *, numeric_owner=False) +.. method:: TarFile.extractall(path=".", members=None, *, numeric_owner=False, filter=None) Extract all members from the archive to the current working directory or directory *path*. If optional *members* is given, it must be a subset of the @@ -401,6 +430,12 @@ are used to set the owner/group for the extracted files. Otherwise, the named values from the tarfile are used. + The *filter* argument, which was added in Python 3.10.12, specifies how + ``members`` are modified or rejected before extraction. + See :ref:`tarfile-extraction-filter` for details. + It is recommended to set this explicitly depending on which *tar* features + you need to support. + .. warning:: Never extract archives from untrusted sources without prior inspection. @@ -408,14 +443,20 @@ that have absolute filenames starting with ``"/"`` or filenames with two dots ``".."``. + Set ``filter='data'`` to prevent the most dangerous security issues, + and read the :ref:`tarfile-extraction-filter` section for details. + .. versionchanged:: 3.5 Added the *numeric_owner* parameter. .. versionchanged:: 3.6 The *path* parameter accepts a :term:`path-like object`. + .. versionchanged:: 3.10.12 + Added the *filter* parameter. + -.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False) +.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False, filter=None) Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. *member* @@ -423,9 +464,8 @@ directory using *path*. *path* may be a :term:`path-like object`. File attributes (owner, mtime, mode) are set unless *set_attrs* is false. - If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile - are used to set the owner/group for the extracted files. Otherwise, the named - values from the tarfile are used. + The *numeric_owner* and *filter* arguments are the same as + for :meth:`extractall`. .. note:: @@ -436,6 +476,9 @@ See the warning for :meth:`extractall`. + Set ``filter='data'`` to prevent the most dangerous security issues, + and read the :ref:`tarfile-extraction-filter` section for details. + .. versionchanged:: 3.2 Added the *set_attrs* parameter. @@ -445,6 +488,9 @@ .. versionchanged:: 3.6 The *path* parameter accepts a :term:`path-like object`. + .. versionchanged:: 3.10.12 + Added the *filter* parameter. + .. method:: TarFile.extractfile(member) @@ -457,6 +503,57 @@ .. versionchanged:: 3.3 Return an :class:`io.BufferedReader` object. +.. attribute:: TarFile.errorlevel + :type: int + + If *errorlevel* is ``0``, errors are ignored when using :meth:`TarFile.extract` + and :meth:`TarFile.extractall`. + Nevertheless, they appear as error messages in the debug output when + *debug* is greater than 0. + If ``1`` (the default), all *fatal* errors are raised as :exc:`OSError` or + :exc:`FilterError` exceptions. If ``2``, all *non-fatal* errors are raised + as :exc:`TarError` exceptions as well. + + Some exceptions, e.g. ones caused by wrong argument types or data + corruption, are always raised. + + Custom :ref:`extraction filters ` + should raise :exc:`FilterError` for *fatal* errors + and :exc:`ExtractError` for *non-fatal* ones. + + Note that when an exception is raised, the archive may be partially + extracted. It is the user’s responsibility to clean up. + +.. attribute:: TarFile.extraction_filter + + .. versionadded:: 3.10.12 + + The :ref:`extraction filter ` used + as a default for the *filter* argument of :meth:`~TarFile.extract` + and :meth:`~TarFile.extractall`. + + The attribute may be ``None`` or a callable. + String names are not allowed for this attribute, unlike the *filter* + argument to :meth:`~TarFile.extract`. + + If ``extraction_filter`` is ``None`` (the default), + calling an extraction method without a *filter* argument will + use the :func:`fully_trusted ` filter for + compatibility with previous Python versions. + + In Python 3.12+, leaving ``extraction_filter=None`` will emit a + ``DeprecationWarning``. + + In Python 3.14+, leaving ``extraction_filter=None`` will cause + extraction methods to use the :func:`data ` filter by default. + + The attribute may be set on instances or overridden in subclasses. + It also is possible to set it on the ``TarFile`` class itself to set a + global default, although, since it affects all uses of *tarfile*, + it is best practice to only do so in top-level applications or + :mod:`site configuration `. + To set a global default this way, a filter function needs to be wrapped in + :func:`staticmethod()` to prevent injection of a ``self`` argument. .. method:: TarFile.add(name, arcname=None, recursive=True, *, filter=None) @@ -532,7 +629,27 @@ It does *not* contain the file's data itself. :class:`TarInfo` objects are returned by :class:`TarFile`'s methods -:meth:`getmember`, :meth:`getmembers` and :meth:`gettarinfo`. +:meth:`~TarFile.getmember`, :meth:`~TarFile.getmembers` and +:meth:`~TarFile.gettarinfo`. + +Modifying the objects returned by :meth:`~!TarFile.getmember` or +:meth:`~!TarFile.getmembers` will affect all subsequent +operations on the archive. +For cases where this is unwanted, you can use :mod:`copy.copy() ` or +call the :meth:`~TarInfo.replace` method to create a modified copy in one step. + +Several attributes can be set to ``None`` to indicate that a piece of metadata +is unused or unknown. +Different :class:`TarInfo` methods handle ``None`` differently: + +- The :meth:`~TarFile.extract` or :meth:`~TarFile.extractall` methods will + ignore the corresponding metadata, leaving it set to a default. +- :meth:`~TarFile.addfile` will fail. +- :meth:`~TarFile.list` will print a placeholder string. + + +.. versionchanged:: 3.10.12 + Added :meth:`~TarInfo.replace` and handling of ``None``. .. class:: TarInfo(name="") @@ -566,24 +683,39 @@ .. attribute:: TarInfo.name + :type: str Name of the archive member. .. attribute:: TarInfo.size + :type: int Size in bytes. .. attribute:: TarInfo.mtime + :type: int | float - Time of last modification. + Time of last modification in seconds since the :ref:`epoch `, + as in :attr:`os.stat_result.st_mtime`. + .. versionchanged:: 3.10.12 + + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.mode + :type: int + + Permission bits, as for :func:`os.chmod`. - Permission bits. + .. versionchanged:: 3.10.12 + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.type @@ -595,35 +727,76 @@ .. attribute:: TarInfo.linkname + :type: str Name of the target file name, which is only present in :class:`TarInfo` objects of type :const:`LNKTYPE` and :const:`SYMTYPE`. .. attribute:: TarInfo.uid + :type: int User ID of the user who originally stored this member. + .. versionchanged:: 3.10.12 + + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.gid + :type: int Group ID of the user who originally stored this member. + .. versionchanged:: 3.10.12 + + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.uname + :type: str User name. + .. versionchanged:: 3.10.12 + + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.gname + :type: str Group name. + .. versionchanged:: 3.10.12 + + Can be set to ``None`` for :meth:`~TarFile.extract` and + :meth:`~TarFile.extractall`, causing extraction to skip applying this + attribute. .. attribute:: TarInfo.pax_headers + :type: dict A dictionary containing key-value pairs of an associated pax extended header. +.. method:: TarInfo.replace(name=..., mtime=..., mode=..., linkname=..., + uid=..., gid=..., uname=..., gname=..., + deep=True) + + .. versionadded:: 3.10.12 + + Return a *new* copy of the :class:`!TarInfo` object with the given attributes + changed. For example, to return a ``TarInfo`` with the group name set to + ``'staff'``, use:: + + new_tarinfo = old_tarinfo.replace(gname='staff') + + By default, a deep copy is made. + If *deep* is false, the copy is shallow, i.e. ``pax_headers`` + and any custom attributes are shared with the original ``TarInfo`` object. A :class:`TarInfo` object also provides some convenient query methods: @@ -673,9 +846,259 @@ Return :const:`True` if it is one of character device, block device or FIFO. +.. _tarfile-extraction-filter: + +Extraction filters +------------------ + +.. versionadded:: 3.10.12 + +The *tar* format is designed to capture all details of a UNIX-like filesystem, +which makes it very powerful. +Unfortunately, the features make it easy to create tar files that have +unintended -- and possibly malicious -- effects when extracted. +For example, extracting a tar file can overwrite arbitrary files in various +ways (e.g. by using absolute paths, ``..`` path components, or symlinks that +affect later members). + +In most cases, the full functionality is not needed. +Therefore, *tarfile* supports extraction filters: a mechanism to limit +functionality, and thus mitigate some of the security issues. + +.. seealso:: + + :pep:`706` + Contains further motivation and rationale behind the design. + +The *filter* argument to :meth:`TarFile.extract` or :meth:`~TarFile.extractall` +can be: + +* the string ``'fully_trusted'``: Honor all metadata as specified in the + archive. + Should be used if the user trusts the archive completely, or implements + their own complex verification. + +* the string ``'tar'``: Honor most *tar*-specific features (i.e. features of + UNIX-like filesystems), but block features that are very likely to be + surprising or malicious. See :func:`tar_filter` for details. + +* the string ``'data'``: Ignore or block most features specific to UNIX-like + filesystems. Intended for extracting cross-platform data archives. + See :func:`data_filter` for details. + +* ``None`` (default): Use :attr:`TarFile.extraction_filter`. + + If that is also ``None`` (the default), the ``'fully_trusted'`` + filter will be used (for compatibility with earlier versions of Python). + + In Python 3.12, the default will emit a ``DeprecationWarning``. + + In Python 3.14, the ``'data'`` filter will become the default instead. + It's possible to switch earlier; see :attr:`TarFile.extraction_filter`. + +* A callable which will be called for each extracted member with a + :ref:`TarInfo ` describing the member and the destination + path to where the archive is extracted (i.e. the same path is used for all + members):: + + filter(/, member: TarInfo, path: str) -> TarInfo | None + + The callable is called just before each member is extracted, so it can + take the current state of the disk into account. + It can: + + - return a :class:`TarInfo` object which will be used instead of the metadata + in the archive, or + - return ``None``, in which case the member will be skipped, or + - raise an exception to abort the operation or skip the member, + depending on :attr:`~TarFile.errorlevel`. + Note that when extraction is aborted, :meth:`~TarFile.extractall` may leave + the archive partially extracted. It does not attempt to clean up. + +Default named filters +~~~~~~~~~~~~~~~~~~~~~ + +The pre-defined, named filters are available as functions, so they can be +reused in custom filters: + +.. function:: fully_trusted_filter(/, member, path) + + Return *member* unchanged. + + This implements the ``'fully_trusted'`` filter. + +.. function:: tar_filter(/, member, path) + + Implements the ``'tar'`` filter. + + - Strip leading slashes (``/`` and :attr:`os.sep`) from filenames. + - :ref:`Refuse ` to extract files with absolute + paths (in case the name is absolute + even after stripping slashes, e.g. ``C:/foo`` on Windows). + This raises :class:`~tarfile.AbsolutePathError`. + - :ref:`Refuse ` to extract files whose absolute + path (after following symlinks) would end up outside the destination. + This raises :class:`~tarfile.OutsideDestinationError`. + - Clear high mode bits (setuid, setgid, sticky) and group/other write bits + (:attr:`~stat.S_IWGRP`|:attr:`~stat.S_IWOTH`). + + Return the modified ``TarInfo`` member. + +.. function:: data_filter(/, member, path) + + Implements the ``'data'`` filter. + In addition to what ``tar_filter`` does: + + - :ref:`Refuse ` to extract links (hard or soft) + that link to absolute paths, or ones that link outside the destination. + + This raises :class:`~tarfile.AbsoluteLinkError` or + :class:`~tarfile.LinkOutsideDestinationError`. + + Note that such files are refused even on platforms that do not support + symbolic links. + + - :ref:`Refuse ` to extract device files + (including pipes). + This raises :class:`~tarfile.SpecialFileError`. + + - For regular files, including hard links: + + - Set the owner read and write permissions + (:attr:`~stat.S_IRUSR`|:attr:`~stat.S_IWUSR`). + - Remove the group & other executable permission + (:attr:`~stat.S_IXGRP`|:attr:`~stat.S_IXOTH`) + if the owner doesn’t have it (:attr:`~stat.S_IXUSR`). + + - For other files (directories), set ``mode`` to ``None``, so + that extraction methods skip applying permission bits. + - Set user and group info (``uid``, ``gid``, ``uname``, ``gname``) + to ``None``, so that extraction methods skip setting it. + + Return the modified ``TarInfo`` member. + + +.. _tarfile-extraction-refuse: + +Filter errors +~~~~~~~~~~~~~ + +When a filter refuses to extract a file, it will raise an appropriate exception, +a subclass of :class:`~tarfile.FilterError`. +This will abort the extraction if :attr:`TarFile.errorlevel` is 1 or more. +With ``errorlevel=0`` the error will be logged and the member will be skipped, +but extraction will continue. + + +Hints for further verification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Even with ``filter='data'``, *tarfile* is not suited for extracting untrusted +files without prior inspection. +Among other issues, the pre-defined filters do not prevent denial-of-service +attacks. Users should do additional checks. + +Here is an incomplete list of things to consider: + +* Extract to a :func:`new temporary directory ` + to prevent e.g. exploiting pre-existing links, and to make it easier to + clean up after a failed extraction. +* When working with untrusted data, use external (e.g. OS-level) limits on + disk, memory and CPU usage. +* Check filenames against an allow-list of characters + (to filter out control characters, confusables, foreign path separators, + etc.). +* Check that filenames have expected extensions (discouraging files that + execute when you “click on them”, or extension-less files like Windows special device names). +* Limit the number of extracted files, total size of extracted data, + filename length (including symlink length), and size of individual files. +* Check for files that would be shadowed on case-insensitive filesystems. + +Also note that: + +* Tar files may contain multiple versions of the same file. + Later ones are expected to overwrite any earlier ones. + This feature is crucial to allow updating tape archives, but can be abused + maliciously. +* *tarfile* does not protect against issues with “live” data, + e.g. an attacker tinkering with the destination (or source) directory while + extraction (or archiving) is in progress. + + +Supporting older Python versions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Extraction filters were added to Python 3.12, and are backported to older +versions as security updates. +To check whether the feature is available, use e.g. +``hasattr(tarfile, 'data_filter')`` rather than checking the Python version. + +The following examples show how to support Python versions with and without +the feature. +Note that setting ``extraction_filter`` will affect any subsequent operations. + +* Fully trusted archive:: + + my_tarfile.extraction_filter = (lambda member, path: member) + my_tarfile.extractall() + +* Use the ``'data'`` filter if available, but revert to Python 3.11 behavior + (``'fully_trusted'``) if this feature is not available:: + + my_tarfile.extraction_filter = getattr(tarfile, 'data_filter', + (lambda member, path: member)) + my_tarfile.extractall() + +* Use the ``'data'`` filter; *fail* if it is not available:: + + my_tarfile.extractall(filter=tarfile.data_filter) + + or:: + + my_tarfile.extraction_filter = tarfile.data_filter + my_tarfile.extractall() + +* Use the ``'data'`` filter; *warn* if it is not available:: + + if hasattr(tarfile, 'data_filter'): + my_tarfile.extractall(filter='data') + else: + # remove this when no longer needed + warn_the_user('Extracting may be unsafe; consider updating Python') + my_tarfile.extractall() + + +Stateful extraction filter example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While *tarfile*'s extraction methods take a simple *filter* callable, +custom filters may be more complex objects with an internal state. +It may be useful to write these as context managers, to be used like this:: + + with StatefulFilter() as filter_func: + tar.extractall(path, filter=filter_func) + +Such a filter can be written as, for example:: + + class StatefulFilter: + def __init__(self): + self.file_count = 0 + + def __enter__(self): + return self + + def __call__(self, member, path): + self.file_count += 1 + return member + + def __exit__(self, *exc_info): + print(f'{self.file_count} files extracted') + + .. _tarfile-commandline: .. program:: tarfile + Command-Line Interface ---------------------- @@ -745,6 +1168,15 @@ Verbose output. +.. cmdoption:: --filter + + Specifies the *filter* for ``--extract``. + See :ref:`tarfile-extraction-filter` for details. + Only string names are accepted (that is, ``fully_trusted``, ``tar``, + and ``data``). + + .. versionadded:: 3.10.12 + .. _tar-examples: Examples diff -Nru python3.10-3.10.7/Doc/library/test.rst python3.10-3.10.12/Doc/library/test.rst --- python3.10-3.10.7/Doc/library/test.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/test.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1066,7 +1066,7 @@ .. function:: bind_unix_socket(sock, addr) - Bind a unix socket, raising :exc:`unittest.SkipTest` if + Bind a Unix socket, raising :exc:`unittest.SkipTest` if :exc:`PermissionError` is raised. @@ -1622,6 +1622,21 @@ .. versionadded:: 3.10 +.. function:: ignore_warnings(*, category) + + Suppress warnings that are instances of *category*, + which must be :exc:`Warning` or a subclass. + Roughly equivalent to :func:`warnings.catch_warnings` + with :meth:`warnings.simplefilter('ignore', category=category) `. + For example:: + + @warning_helper.ignore_warnings(category=DeprecationWarning) + def test_suppress_warning(): + # do something + + .. versionadded:: 3.8 + + .. function:: check_no_resource_warning(testcase) Context manager to check that no :exc:`ResourceWarning` was raised. You diff -Nru python3.10-3.10.7/Doc/library/_thread.rst python3.10-3.10.12/Doc/library/_thread.rst --- python3.10-3.10.7/Doc/library/_thread.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/_thread.rst 2023-06-06 22:30:33.000000000 +0000 @@ -155,21 +155,21 @@ Lock objects have the following methods: -.. method:: lock.acquire(waitflag=1, timeout=-1) +.. method:: lock.acquire(blocking=True, timeout=-1) Without any optional argument, this method acquires the lock unconditionally, if necessary waiting until it is released by another thread (only one thread at a time can acquire a lock --- that's their reason for existence). - If the integer *waitflag* argument is present, the action depends on its - value: if it is zero, the lock is only acquired if it can be acquired - immediately without waiting, while if it is nonzero, the lock is acquired + If the *blocking* argument is present, the action depends on its + value: if it is False, the lock is only acquired if it can be acquired + immediately without waiting, while if it is True, the lock is acquired unconditionally as above. If the floating-point *timeout* argument is present and positive, it specifies the maximum wait time in seconds before returning. A negative *timeout* argument specifies an unbounded wait. You cannot specify - a *timeout* if *waitflag* is zero. + a *timeout* if *blocking* is False. The return value is ``True`` if the lock is acquired successfully, ``False`` if not. diff -Nru python3.10-3.10.7/Doc/library/tkinter.colorchooser.rst python3.10-3.10.12/Doc/library/tkinter.colorchooser.rst --- python3.10-3.10.7/Doc/library/tkinter.colorchooser.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.colorchooser.rst 2023-06-06 22:30:33.000000000 +0000 @@ -26,4 +26,4 @@ .. seealso:: Module :mod:`tkinter.commondialog` - Tkinter standard dialog module \ No newline at end of file + Tkinter standard dialog module diff -Nru python3.10-3.10.7/Doc/library/tkinter.dnd.rst python3.10-3.10.12/Doc/library/tkinter.dnd.rst --- python3.10-3.10.7/Doc/library/tkinter.dnd.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.dnd.rst 2023-06-06 22:30:33.000000000 +0000 @@ -61,4 +61,4 @@ .. seealso:: - :ref:`Bindings-and-Events` \ No newline at end of file + :ref:`Bindings-and-Events` diff -Nru python3.10-3.10.7/Doc/library/tkinter.messagebox.rst python3.10-3.10.12/Doc/library/tkinter.messagebox.rst --- python3.10-3.10.7/Doc/library/tkinter.messagebox.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.messagebox.rst 2023-06-06 22:30:33.000000000 +0000 @@ -36,4 +36,4 @@ askokcancel(title=None, message=None, **options) askretrycancel(title=None, message=None, **options) askyesno(title=None, message=None, **options) - askyesnocancel(title=None, message=None, **options) \ No newline at end of file + askyesnocancel(title=None, message=None, **options) diff -Nru python3.10-3.10.7/Doc/library/tkinter.rst python3.10-3.10.12/Doc/library/tkinter.rst --- python3.10-3.10.7/Doc/library/tkinter.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.rst 2023-06-06 22:30:33.000000000 +0000 @@ -38,7 +38,7 @@ .. seealso:: - * `TkDocs `_ + * `TkDocs `_ Extensive tutorial on creating user interfaces with Tkinter. Explains key concepts, and illustrates recommended approaches using the modern API. diff -Nru python3.10-3.10.7/Doc/library/tkinter.tix.rst python3.10-3.10.12/Doc/library/tkinter.tix.rst --- python3.10-3.10.7/Doc/library/tkinter.tix.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.tix.rst 2023-06-06 22:30:33.000000000 +0000 @@ -33,17 +33,17 @@ .. seealso:: - `Tix Homepage `_ + `Tix Homepage `_ The home page for :mod:`Tix`. This includes links to additional documentation and downloads. - `Tix Man Pages `_ + `Tix Man Pages `_ On-line version of the man pages and reference material. - `Tix Programming Guide `_ + `Tix Programming Guide `_ On-line version of the programmer's reference material. - `Tix Development Applications `_ + `Tix Development Applications `_ Tix applications for development of Tix and Tkinter programs. Tide applications work under Tk or Tkinter, and include :program:`TixInspect`, an inspector to remotely modify and debug Tix/Tk/Tkinter applications. @@ -80,7 +80,7 @@ Tix Widgets ----------- -`Tix `_ +`Tix `_ introduces over 40 widget classes to the :mod:`tkinter` repertoire. @@ -91,125 +91,125 @@ .. class:: Balloon() A `Balloon - `_ that + `_ that pops up over a widget to provide help. When the user moves the cursor inside a widget to which a Balloon widget has been bound, a small pop-up window with a descriptive message will be shown on the screen. .. Python Demo of: -.. \ulink{Balloon}{http://tix.sourceforge.net/dist/current/demos/samples/Balloon.tcl} +.. \ulink{Balloon}{https://tix.sourceforge.net/dist/current/demos/samples/Balloon.tcl} .. class:: ButtonBox() The `ButtonBox - `_ + `_ widget creates a box of buttons, such as is commonly used for ``Ok Cancel``. .. Python Demo of: -.. \ulink{ButtonBox}{http://tix.sourceforge.net/dist/current/demos/samples/BtnBox.tcl} +.. \ulink{ButtonBox}{https://tix.sourceforge.net/dist/current/demos/samples/BtnBox.tcl} .. class:: ComboBox() The `ComboBox - `_ + `_ widget is similar to the combo box control in MS Windows. The user can select a choice by either typing in the entry subwidget or selecting from the listbox subwidget. .. Python Demo of: -.. \ulink{ComboBox}{http://tix.sourceforge.net/dist/current/demos/samples/ComboBox.tcl} +.. \ulink{ComboBox}{https://tix.sourceforge.net/dist/current/demos/samples/ComboBox.tcl} .. class:: Control() The `Control - `_ + `_ widget is also known as the :class:`SpinBox` widget. The user can adjust the value by pressing the two arrow buttons or by entering the value directly into the entry. The new value will be checked against the user-defined upper and lower limits. .. Python Demo of: -.. \ulink{Control}{http://tix.sourceforge.net/dist/current/demos/samples/Control.tcl} +.. \ulink{Control}{https://tix.sourceforge.net/dist/current/demos/samples/Control.tcl} .. class:: LabelEntry() The `LabelEntry - `_ + `_ widget packages an entry widget and a label into one mega widget. It can be used to simplify the creation of "entry-form" type of interface. .. Python Demo of: -.. \ulink{LabelEntry}{http://tix.sourceforge.net/dist/current/demos/samples/LabEntry.tcl} +.. \ulink{LabelEntry}{https://tix.sourceforge.net/dist/current/demos/samples/LabEntry.tcl} .. class:: LabelFrame() The `LabelFrame - `_ + `_ widget packages a frame widget and a label into one mega widget. To create widgets inside a LabelFrame widget, one creates the new widgets relative to the :attr:`frame` subwidget and manage them inside the :attr:`frame` subwidget. .. Python Demo of: -.. \ulink{LabelFrame}{http://tix.sourceforge.net/dist/current/demos/samples/LabFrame.tcl} +.. \ulink{LabelFrame}{https://tix.sourceforge.net/dist/current/demos/samples/LabFrame.tcl} .. class:: Meter() The `Meter - `_ widget + `_ widget can be used to show the progress of a background job which may take a long time to execute. .. Python Demo of: -.. \ulink{Meter}{http://tix.sourceforge.net/dist/current/demos/samples/Meter.tcl} +.. \ulink{Meter}{https://tix.sourceforge.net/dist/current/demos/samples/Meter.tcl} .. class:: OptionMenu() The `OptionMenu - `_ + `_ creates a menu button of options. .. Python Demo of: -.. \ulink{OptionMenu}{http://tix.sourceforge.net/dist/current/demos/samples/OptMenu.tcl} +.. \ulink{OptionMenu}{https://tix.sourceforge.net/dist/current/demos/samples/OptMenu.tcl} .. class:: PopupMenu() The `PopupMenu - `_ + `_ widget can be used as a replacement of the ``tk_popup`` command. The advantage of the :mod:`Tix` :class:`PopupMenu` widget is it requires less application code to manipulate. .. Python Demo of: -.. \ulink{PopupMenu}{http://tix.sourceforge.net/dist/current/demos/samples/PopMenu.tcl} +.. \ulink{PopupMenu}{https://tix.sourceforge.net/dist/current/demos/samples/PopMenu.tcl} .. class:: Select() The `Select - `_ widget + `_ widget is a container of button subwidgets. It can be used to provide radio-box or check-box style of selection options for the user. .. Python Demo of: -.. \ulink{Select}{http://tix.sourceforge.net/dist/current/demos/samples/Select.tcl} +.. \ulink{Select}{https://tix.sourceforge.net/dist/current/demos/samples/Select.tcl} .. class:: StdButtonBox() The `StdButtonBox - `_ + `_ widget is a group of standard buttons for Motif-like dialog boxes. .. Python Demo of: -.. \ulink{StdButtonBox}{http://tix.sourceforge.net/dist/current/demos/samples/StdBBox.tcl} +.. \ulink{StdButtonBox}{https://tix.sourceforge.net/dist/current/demos/samples/StdBBox.tcl} File Selectors @@ -219,37 +219,37 @@ .. class:: DirList() The `DirList - `_ + `_ widget displays a list view of a directory, its previous directories and its sub-directories. The user can choose one of the directories displayed in the list or change to another directory. .. Python Demo of: -.. \ulink{DirList}{http://tix.sourceforge.net/dist/current/demos/samples/DirList.tcl} +.. \ulink{DirList}{https://tix.sourceforge.net/dist/current/demos/samples/DirList.tcl} .. class:: DirTree() The `DirTree - `_ + `_ widget displays a tree view of a directory, its previous directories and its sub-directories. The user can choose one of the directories displayed in the list or change to another directory. .. Python Demo of: -.. \ulink{DirTree}{http://tix.sourceforge.net/dist/current/demos/samples/DirTree.tcl} +.. \ulink{DirTree}{https://tix.sourceforge.net/dist/current/demos/samples/DirTree.tcl} .. class:: DirSelectDialog() The `DirSelectDialog - `_ + `_ widget presents the directories in the file system in a dialog window. The user can use this dialog window to navigate through the file system to select the desired directory. .. Python Demo of: -.. \ulink{DirSelectDialog}{http://tix.sourceforge.net/dist/current/demos/samples/DirDlg.tcl} +.. \ulink{DirSelectDialog}{https://tix.sourceforge.net/dist/current/demos/samples/DirDlg.tcl} .. class:: DirSelectBox() @@ -263,39 +263,39 @@ .. class:: ExFileSelectBox() The `ExFileSelectBox - `_ + `_ widget is usually embedded in a tixExFileSelectDialog widget. It provides a convenient method for the user to select files. The style of the :class:`ExFileSelectBox` widget is very similar to the standard file dialog on MS Windows 3.1. .. Python Demo of: -.. \ulink{ExFileSelectDialog}{http://tix.sourceforge.net/dist/current/demos/samples/EFileDlg.tcl} +.. \ulink{ExFileSelectDialog}{https://tix.sourceforge.net/dist/current/demos/samples/EFileDlg.tcl} .. class:: FileSelectBox() The `FileSelectBox - `_ + `_ is similar to the standard Motif(TM) file-selection box. It is generally used for the user to choose a file. FileSelectBox stores the files mostly recently selected into a :class:`ComboBox` widget so that they can be quickly selected again. .. Python Demo of: -.. \ulink{FileSelectDialog}{http://tix.sourceforge.net/dist/current/demos/samples/FileDlg.tcl} +.. \ulink{FileSelectDialog}{https://tix.sourceforge.net/dist/current/demos/samples/FileDlg.tcl} .. class:: FileEntry() The `FileEntry - `_ + `_ widget can be used to input a filename. The user can type in the filename manually. Alternatively, the user can press the button widget that sits next to the entry, which will bring up a file selection dialog. .. Python Demo of: -.. \ulink{FileEntry}{http://tix.sourceforge.net/dist/current/demos/samples/FileEnt.tcl} +.. \ulink{FileEntry}{https://tix.sourceforge.net/dist/current/demos/samples/FileEnt.tcl} Hierarchical ListBox @@ -305,42 +305,42 @@ .. class:: HList() The `HList - `_ widget + `_ widget can be used to display any data that have a hierarchical structure, for example, file system directory trees. The list entries are indented and connected by branch lines according to their places in the hierarchy. .. Python Demo of: -.. \ulink{HList}{http://tix.sourceforge.net/dist/current/demos/samples/HList1.tcl} +.. \ulink{HList}{https://tix.sourceforge.net/dist/current/demos/samples/HList1.tcl} .. class:: CheckList() The `CheckList - `_ + `_ widget displays a list of items to be selected by the user. CheckList acts similarly to the Tk checkbutton or radiobutton widgets, except it is capable of handling many more items than checkbuttons or radiobuttons. .. Python Demo of: -.. \ulink{ CheckList}{http://tix.sourceforge.net/dist/current/demos/samples/ChkList.tcl} +.. \ulink{ CheckList}{https://tix.sourceforge.net/dist/current/demos/samples/ChkList.tcl} .. Python Demo of: -.. \ulink{ScrolledHList (1)}{http://tix.sourceforge.net/dist/current/demos/samples/SHList.tcl} +.. \ulink{ScrolledHList (1)}{https://tix.sourceforge.net/dist/current/demos/samples/SHList.tcl} .. Python Demo of: -.. \ulink{ScrolledHList (2)}{http://tix.sourceforge.net/dist/current/demos/samples/SHList2.tcl} +.. \ulink{ScrolledHList (2)}{https://tix.sourceforge.net/dist/current/demos/samples/SHList2.tcl} .. class:: Tree() The `Tree - `_ widget + `_ widget can be used to display hierarchical data in a tree form. The user can adjust the view of the tree by opening or closing parts of the tree. .. Python Demo of: -.. \ulink{Tree}{http://tix.sourceforge.net/dist/current/demos/samples/Tree.tcl} +.. \ulink{Tree}{https://tix.sourceforge.net/dist/current/demos/samples/Tree.tcl} .. Python Demo of: -.. \ulink{Tree (Dynamic)}{http://tix.sourceforge.net/dist/current/demos/samples/DynTree.tcl} +.. \ulink{Tree (Dynamic)}{https://tix.sourceforge.net/dist/current/demos/samples/DynTree.tcl} Tabular ListBox @@ -350,7 +350,7 @@ .. class:: TList() The `TList - `_ widget + `_ widget can be used to display data in a tabular format. The list entries of a :class:`TList` widget are similar to the entries in the Tk listbox widget. The main differences are (1) the :class:`TList` widget can display the list entries @@ -358,17 +358,17 @@ multiple colors and fonts for the list entries. .. Python Demo of: -.. \ulink{ScrolledTList (1)}{http://tix.sourceforge.net/dist/current/demos/samples/STList1.tcl} +.. \ulink{ScrolledTList (1)}{https://tix.sourceforge.net/dist/current/demos/samples/STList1.tcl} .. Python Demo of: -.. \ulink{ScrolledTList (2)}{http://tix.sourceforge.net/dist/current/demos/samples/STList2.tcl} +.. \ulink{ScrolledTList (2)}{https://tix.sourceforge.net/dist/current/demos/samples/STList2.tcl} .. Grid has yet to be added to Python .. \subsubsection{Grid Widget} .. Python Demo of: -.. \ulink{Simple Grid}{http://tix.sourceforge.net/dist/current/demos/samples/SGrid0.tcl} +.. \ulink{Simple Grid}{https://tix.sourceforge.net/dist/current/demos/samples/SGrid0.tcl} .. Python Demo of: -.. \ulink{ScrolledGrid}{http://tix.sourceforge.net/dist/current/demos/samples/SGrid1.tcl} +.. \ulink{ScrolledGrid}{https://tix.sourceforge.net/dist/current/demos/samples/SGrid1.tcl} .. Python Demo of: -.. \ulink{Editable Grid}{http://tix.sourceforge.net/dist/current/demos/samples/EditGrid.tcl} +.. \ulink{Editable Grid}{https://tix.sourceforge.net/dist/current/demos/samples/EditGrid.tcl} Manager Widgets @@ -378,19 +378,19 @@ .. class:: PanedWindow() The `PanedWindow - `_ + `_ widget allows the user to interactively manipulate the sizes of several panes. The panes can be arranged either vertically or horizontally. The user changes the sizes of the panes by dragging the resize handle between two panes. .. Python Demo of: -.. \ulink{PanedWindow}{http://tix.sourceforge.net/dist/current/demos/samples/PanedWin.tcl} +.. \ulink{PanedWindow}{https://tix.sourceforge.net/dist/current/demos/samples/PanedWin.tcl} .. class:: ListNoteBook() The `ListNoteBook - `_ + `_ widget is very similar to the :class:`TixNoteBook` widget: it can be used to display many windows in a limited space using a notebook metaphor. The notebook is divided into a stack of pages (windows). At one time only one of these pages @@ -398,30 +398,30 @@ the desired page in the :attr:`hlist` subwidget. .. Python Demo of: -.. \ulink{ListNoteBook}{http://tix.sourceforge.net/dist/current/demos/samples/ListNBK.tcl} +.. \ulink{ListNoteBook}{https://tix.sourceforge.net/dist/current/demos/samples/ListNBK.tcl} .. class:: NoteBook() The `NoteBook - `_ + `_ widget can be used to display many windows in a limited space using a notebook metaphor. The notebook is divided into a stack of pages. At one time only one of these pages can be shown. The user can navigate through these pages by choosing the visual "tabs" at the top of the NoteBook widget. .. Python Demo of: -.. \ulink{NoteBook}{http://tix.sourceforge.net/dist/current/demos/samples/NoteBook.tcl} +.. \ulink{NoteBook}{https://tix.sourceforge.net/dist/current/demos/samples/NoteBook.tcl} .. \subsubsection{Scrolled Widgets} .. Python Demo of: -.. \ulink{ScrolledListBox}{http://tix.sourceforge.net/dist/current/demos/samples/SListBox.tcl} +.. \ulink{ScrolledListBox}{https://tix.sourceforge.net/dist/current/demos/samples/SListBox.tcl} .. Python Demo of: -.. \ulink{ScrolledText}{http://tix.sourceforge.net/dist/current/demos/samples/SText.tcl} +.. \ulink{ScrolledText}{https://tix.sourceforge.net/dist/current/demos/samples/SText.tcl} .. Python Demo of: -.. \ulink{ScrolledWindow}{http://tix.sourceforge.net/dist/current/demos/samples/SWindow.tcl} +.. \ulink{ScrolledWindow}{https://tix.sourceforge.net/dist/current/demos/samples/SWindow.tcl} .. Python Demo of: -.. \ulink{Canvas Object View}{http://tix.sourceforge.net/dist/current/demos/samples/CObjView.tcl} +.. \ulink{Canvas Object View}{https://tix.sourceforge.net/dist/current/demos/samples/CObjView.tcl} Image Types @@ -429,17 +429,17 @@ The :mod:`tkinter.tix` module adds: -* `pixmap `_ +* `pixmap `_ capabilities to all :mod:`tkinter.tix` and :mod:`tkinter` widgets to create color images from XPM files. .. Python Demo of: - .. \ulink{XPM Image In Button}{http://tix.sourceforge.net/dist/current/demos/samples/Xpm.tcl} + .. \ulink{XPM Image In Button}{https://tix.sourceforge.net/dist/current/demos/samples/Xpm.tcl} .. Python Demo of: - .. \ulink{XPM Image In Menu}{http://tix.sourceforge.net/dist/current/demos/samples/Xpm1.tcl} + .. \ulink{XPM Image In Menu}{https://tix.sourceforge.net/dist/current/demos/samples/Xpm1.tcl} * `Compound - `_ image + `_ image types can be used to create images that consists of multiple horizontal lines; each line is composed of a series of items (texts, bitmaps, images or spaces) arranged from left to right. For example, a compound image can be used to @@ -447,13 +447,13 @@ widget. .. Python Demo of: - .. \ulink{Compound Image In Buttons}{http://tix.sourceforge.net/dist/current/demos/samples/CmpImg.tcl} + .. \ulink{Compound Image In Buttons}{https://tix.sourceforge.net/dist/current/demos/samples/CmpImg.tcl} .. Python Demo of: - .. \ulink{Compound Image In NoteBook}{http://tix.sourceforge.net/dist/current/demos/samples/CmpImg2.tcl} + .. \ulink{Compound Image In NoteBook}{https://tix.sourceforge.net/dist/current/demos/samples/CmpImg2.tcl} .. Python Demo of: - .. \ulink{Compound Image Notebook Color Tabs}{http://tix.sourceforge.net/dist/current/demos/samples/CmpImg4.tcl} + .. \ulink{Compound Image Notebook Color Tabs}{https://tix.sourceforge.net/dist/current/demos/samples/CmpImg4.tcl} .. Python Demo of: - .. \ulink{Compound Image Icons}{http://tix.sourceforge.net/dist/current/demos/samples/CmpImg3.tcl} + .. \ulink{Compound Image Icons}{https://tix.sourceforge.net/dist/current/demos/samples/CmpImg3.tcl} Miscellaneous Widgets @@ -463,7 +463,7 @@ .. class:: InputOnly() The `InputOnly - `_ + `_ widgets are to accept inputs from the user, which can be done with the ``bind`` command (Unix only). @@ -477,7 +477,7 @@ .. class:: Form() The `Form - `_ geometry + `_ geometry manager based on attachment rules for all Tk widgets. @@ -488,7 +488,7 @@ .. class:: tixCommand() The `tix commands - `_ provide + `_ provide access to miscellaneous elements of :mod:`Tix`'s internal state and the :mod:`Tix` application context. Most of the information manipulated by these methods pertains to the application as a whole, or to a screen or display, diff -Nru python3.10-3.10.7/Doc/library/tkinter.ttk.rst python3.10-3.10.12/Doc/library/tkinter.ttk.rst --- python3.10-3.10.7/Doc/library/tkinter.ttk.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tkinter.ttk.rst 2023-06-06 22:30:33.000000000 +0000 @@ -58,7 +58,7 @@ .. seealso:: - `Converting existing applications to use Tile widgets `_ + `Converting existing applications to use Tile widgets `_ A monograph (using Tcl terminology) about differences typically encountered when moving applications to use the new widgets. @@ -1274,7 +1274,7 @@ .. seealso:: - `Tcl'2004 conference presentation `_ + `Tcl'2004 conference presentation `_ This document explains how the theme engine works diff -Nru python3.10-3.10.7/Doc/library/tk.rst python3.10-3.10.12/Doc/library/tk.rst --- python3.10-3.10.7/Doc/library/tk.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/tk.rst 2023-06-06 22:30:33.000000000 +0000 @@ -44,4 +44,4 @@ .. Other sections I have in mind are Tkinter internals - Freezing Tkinter applications \ No newline at end of file + Freezing Tkinter applications diff -Nru python3.10-3.10.7/Doc/library/traceback.rst python3.10-3.10.12/Doc/library/traceback.rst --- python3.10-3.10.7/Doc/library/traceback.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/traceback.rst 2023-06-06 22:30:33.000000000 +0000 @@ -20,8 +20,15 @@ the :data:`sys.last_traceback` variable and returned as the third item from :func:`sys.exc_info`. -The module defines the following functions: +.. seealso:: + + Module :mod:`faulthandler` + Used to dump Python tracebacks explicitly, on a fault, after a timeout, or on a user signal. + Module :mod:`pdb` + Interactive source code debugger for Python programs. + +The module defines the following functions: .. function:: print_tb(tb, limit=None, file=None) @@ -252,6 +259,13 @@ For syntax errors - the line number where the error occurred. + .. attribute:: end_lineno + + For syntax errors - the end line number where the error occurred. + Can be ``None`` if not present. + + .. versionadded:: 3.10 + .. attribute:: text For syntax errors - the text where the error occurred. @@ -260,6 +274,13 @@ For syntax errors - the offset into the text where the error occurred. + .. attribute:: end_offset + + For syntax errors - the end offset into the text where the error occurred. + Can be ``None`` if not present. + + .. versionadded:: 3.10 + .. attribute:: msg For syntax errors - the compiler error message. @@ -401,9 +422,9 @@ import sys, traceback def lumberjack(): - bright_side_of_death() + bright_side_of_life() - def bright_side_of_death(): + def bright_side_of_life(): return tuple()[0] try: @@ -413,9 +434,7 @@ print("*** print_tb:") traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) print("*** print_exception:") - # exc_type below is ignored on 3.5 and later - traceback.print_exception(exc_type, exc_value, exc_traceback, - limit=2, file=sys.stdout) + traceback.print_exception(exc_value, limit=2, file=sys.stdout) print("*** print_exc:") traceback.print_exc(limit=2, file=sys.stdout) print("*** format_exc, first and last line:") @@ -423,9 +442,7 @@ print(formatted_lines[0]) print(formatted_lines[-1]) print("*** format_exception:") - # exc_type below is ignored on 3.5 and later - print(repr(traceback.format_exception(exc_type, exc_value, - exc_traceback))) + print(repr(traceback.format_exception(exc_value))) print("*** extract_tb:") print(repr(traceback.extract_tb(exc_traceback))) print("*** format_tb:") @@ -445,14 +462,14 @@ File "", line 10, in lumberjack() File "", line 4, in lumberjack - bright_side_of_death() + bright_side_of_life() IndexError: tuple index out of range *** print_exc: Traceback (most recent call last): File "", line 10, in lumberjack() File "", line 4, in lumberjack - bright_side_of_death() + bright_side_of_life() IndexError: tuple index out of range *** format_exc, first and last line: Traceback (most recent call last): @@ -460,17 +477,17 @@ *** format_exception: ['Traceback (most recent call last):\n', ' File "", line 10, in \n lumberjack()\n', - ' File "", line 4, in lumberjack\n bright_side_of_death()\n', - ' File "", line 7, in bright_side_of_death\n return tuple()[0]\n', + ' File "", line 4, in lumberjack\n bright_side_of_life()\n', + ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n', 'IndexError: tuple index out of range\n'] *** extract_tb: [, line 10 in >, , line 4 in lumberjack>, - , line 7 in bright_side_of_death>] + , line 7 in bright_side_of_life>] *** format_tb: [' File "", line 10, in \n lumberjack()\n', - ' File "", line 4, in lumberjack\n bright_side_of_death()\n', - ' File "", line 7, in bright_side_of_death\n return tuple()[0]\n'] + ' File "", line 4, in lumberjack\n bright_side_of_life()\n', + ' File "", line 7, in bright_side_of_life\n return tuple()[0]\n'] *** tb_lineno: 10 diff -Nru python3.10-3.10.7/Doc/library/turtle.rst python3.10-3.10.12/Doc/library/turtle.rst --- python3.10-3.10.7/Doc/library/turtle.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/turtle.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1214,7 +1214,7 @@ will be displayed stretched according to its stretchfactors: *stretch_wid* is stretchfactor perpendicular to its orientation, *stretch_len* is stretchfactor in direction of its orientation, *outline* determines the width - of the shapes's outline. + of the shape's outline. .. doctest:: :skipif: _tkinter is None @@ -1545,7 +1545,7 @@ 1. Create an empty Shape object of type "compound". 2. Add as many components to this object as desired, using the - :meth:`addcomponent` method. + :meth:`~Shape.addcomponent` method. For example: @@ -2125,7 +2125,7 @@ :param cv: a :class:`tkinter.Canvas` - Provides screen oriented methods like :func:`setbg` etc. that are described + Provides screen oriented methods like :func:`bgcolor` etc. that are described above. .. class:: Screen() @@ -2315,7 +2315,9 @@ you can prepare a configuration file ``turtle.cfg`` which will be read at import time and modify the configuration according to its settings. -The built in configuration would correspond to the following turtle.cfg:: +The built in configuration would correspond to the following ``turtle.cfg``: + +.. code-block:: ini width = 0.5 height = 0.75 @@ -2340,15 +2342,15 @@ Short explanation of selected entries: -- The first four lines correspond to the arguments of the :meth:`Screen.setup` +- The first four lines correspond to the arguments of the :func:`Screen.setup ` method. - Line 5 and 6 correspond to the arguments of the method - :meth:`Screen.screensize`. + :func:`Screen.screensize `. - *shape* can be any of the built-in shapes, e.g: arrow, turtle, etc. For more info try ``help(shape)``. -- If you want to use no fillcolor (i.e. make the turtle transparent), you have +- If you want to use no fill color (i.e. make the turtle transparent), you have to write ``fillcolor = ""`` (but all nonempty strings must not have quotes in - the cfg-file). + the cfg file). - If you want to reflect the turtle its state, you have to use ``resizemode = auto``. - If you set e.g. ``language = italian`` the docstringdict @@ -2398,6 +2400,8 @@ The demo scripts are: +.. currentmodule:: turtle + .. tabularcolumns:: |l|L|L| +----------------+------------------------------+-----------------------+ @@ -2444,6 +2448,9 @@ | planet_and_moon| simulation of | compound shapes, | | | gravitational system | :class:`Vec2D` | +----------------+------------------------------+-----------------------+ +| rosette | a pattern from the wikipedia | :func:`clone`, | +| | article on turtle graphics | :func:`undo` | ++----------------+------------------------------+-----------------------+ | round_dance | dancing turtles rotating | compound shapes, clone| | | pairwise in opposite | shapesize, tilt, | | | direction | get_shapepoly, update | @@ -2457,9 +2464,6 @@ | two_canvases | simple design | turtles on two | | | | canvases | +----------------+------------------------------+-----------------------+ -| wikipedia | a pattern from the wikipedia | :func:`clone`, | -| | article on turtle graphics | :func:`undo` | -+----------------+------------------------------+-----------------------+ | yinyang | another elementary example | :func:`circle` | +----------------+------------------------------+-----------------------+ @@ -2469,20 +2473,20 @@ Changes since Python 2.6 ======================== -- The methods :meth:`Turtle.tracer`, :meth:`Turtle.window_width` and - :meth:`Turtle.window_height` have been eliminated. +- The methods :func:`Turtle.tracer `, :func:`Turtle.window_width ` and + :func:`Turtle.window_height ` have been eliminated. Methods with these names and functionality are now available only as methods of :class:`Screen`. The functions derived from these remain available. (In fact already in Python 2.6 these methods were merely duplications of the corresponding - :class:`TurtleScreen`/:class:`Screen`-methods.) + :class:`TurtleScreen`/:class:`Screen` methods.) -- The method :meth:`Turtle.fill` has been eliminated. - The behaviour of :meth:`begin_fill` and :meth:`end_fill` - have changed slightly: now every filling-process must be completed with an +- The method :func:`!Turtle.fill` has been eliminated. + The behaviour of :func:`begin_fill` and :func:`end_fill` + have changed slightly: now every filling process must be completed with an ``end_fill()`` call. -- A method :meth:`Turtle.filling` has been added. It returns a boolean +- A method :func:`Turtle.filling ` has been added. It returns a boolean value: ``True`` if a filling process is under way, ``False`` otherwise. This behaviour corresponds to a ``fill()`` call without arguments in Python 2.6. @@ -2490,23 +2494,23 @@ Changes since Python 3.0 ======================== -- The methods :meth:`Turtle.shearfactor`, :meth:`Turtle.shapetransform` and - :meth:`Turtle.get_shapepoly` have been added. Thus the full range of +- The :class:`Turtle` methods :func:`shearfactor`, :func:`shapetransform` and + :func:`get_shapepoly` have been added. Thus the full range of regular linear transforms is now available for transforming turtle shapes. - :meth:`Turtle.tiltangle` has been enhanced in functionality: it now can - be used to get or set the tiltangle. :meth:`Turtle.settiltangle` has been + :func:`tiltangle` has been enhanced in functionality: it now can + be used to get or set the tilt angle. :func:`settiltangle` has been deprecated. -- The method :meth:`Screen.onkeypress` has been added as a complement to - :meth:`Screen.onkey` which in fact binds actions to the keyrelease event. - Accordingly the latter has got an alias: :meth:`Screen.onkeyrelease`. - -- The method :meth:`Screen.mainloop` has been added. So when working only - with Screen and Turtle objects one must not additionally import - :func:`mainloop` anymore. +- The :class:`Screen` method :func:`onkeypress` has been added as a complement to + :func:`onkey`. As the latter binds actions to the key release event, + an alias: :func:`onkeyrelease` was also added for it. + +- The method :func:`Screen.mainloop ` has been added, + so there is no longer a need to use the standalone :func:`mainloop` function + when working with :class:`Screen` and :class:`Turtle` objects. -- Two input methods has been added :meth:`Screen.textinput` and - :meth:`Screen.numinput`. These popup input dialogs and return +- Two input methods have been added: :func:`Screen.textinput ` and + :func:`Screen.numinput `. These pop up input dialogs and return strings and numbers respectively. - Two example scripts :file:`tdemo_nim.py` and :file:`tdemo_round_dance.py` diff -Nru python3.10-3.10.7/Doc/library/types.rst python3.10-3.10.12/Doc/library/types.rst --- python3.10-3.10.7/Doc/library/types.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/types.rst 2023-06-06 22:30:33.000000000 +0000 @@ -239,7 +239,7 @@ The :term:`loader` which loaded the module. Defaults to ``None``. This attribute is to match :attr:`importlib.machinery.ModuleSpec.loader` - as stored in the attr:`__spec__` object. + as stored in the :attr:`__spec__` object. .. note:: A future version of Python may stop setting this attribute by default. @@ -264,7 +264,7 @@ :attr:`__name__` if the module is a package itself). Defaults to ``None``. This attribute is to match :attr:`importlib.machinery.ModuleSpec.parent` - as stored in the attr:`__spec__` object. + as stored in the :attr:`__spec__` object. .. note:: A future version of Python may stop setting this attribute by default. @@ -480,7 +480,7 @@ The generator-based coroutine is still a :term:`generator iterator`, but is also considered to be a :term:`coroutine` object and is :term:`awaitable`. However, it may not necessarily implement - the :meth:`__await__` method. + the :meth:`~object.__await__` method. If *gen_func* is a generator function, it will be modified in-place. diff -Nru python3.10-3.10.7/Doc/library/typing.rst python3.10-3.10.12/Doc/library/typing.rst --- python3.10-3.10.7/Doc/library/typing.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/typing.rst 2023-06-06 22:30:33.000000000 +0000 @@ -36,6 +36,19 @@ The `typing_extensions `_ package provides backports of these new features to older versions of Python. +.. seealso:: + + For a quick overview of type hints, refer to + `this cheat sheet `_. + + The "Type System Reference" section of https://mypy.readthedocs.io/ -- since + the Python typing system is standardised via PEPs, this reference should + broadly apply to most Python type checkers, although some parts may still be + specific to mypy. + + The documentation at https://typing.readthedocs.io/ serves as useful reference + for type system features, useful typing related tools and typing best practices. + .. _relevant-peps: Relevant PEPs @@ -86,7 +99,7 @@ def scale(scalar: float, vector: Vector) -> Vector: return [scalar * num for num in vector] - # typechecks; a list of floats qualifies as a Vector. + # passes type checking; a list of floats qualifies as a Vector. new_vector = scale(2.0, [1.0, -4.2, 5.4]) Type aliases are useful for simplifying complex type signatures. For example:: @@ -128,10 +141,10 @@ def get_user_name(user_id: UserId) -> str: ... - # typechecks + # passes type checking user_a = get_user_name(UserId(42351)) - # does not typecheck; an int is not a UserId + # fails type checking; an int is not a UserId user_b = get_user_name(-1) You may still perform all ``int`` operations on a variable of type ``UserId``, @@ -157,7 +170,7 @@ UserId = NewType('UserId', int) - # Fails at runtime and does not typecheck + # Fails at runtime and does not pass type checking class AdminUserId(UserId): pass However, it is possible to create a :class:`NewType` based on a 'derived' ``NewType``:: @@ -229,7 +242,7 @@ .. versionchanged:: 3.10 ``Callable`` now supports :class:`ParamSpec` and :data:`Concatenate`. - See :pep:`612` for more information. + See :pep:`612` for more details. .. seealso:: The documentation for :class:`ParamSpec` and :class:`Concatenate` provides @@ -300,7 +313,7 @@ class body. The :class:`Generic` base class defines :meth:`~object.__class_getitem__` so -that ``LoggedVar[t]`` is valid as a type:: +that ``LoggedVar[T]`` is valid as a type:: from collections.abc import Iterable @@ -420,7 +433,7 @@ A user-defined generic class can have ABCs as base classes without a metaclass conflict. Generic metaclasses are not supported. The outcome of parameterizing -generics is cached, and most types in the typing module are hashable and +generics is cached, and most types in the typing module are :term:`hashable` and comparable for equality. @@ -444,12 +457,12 @@ s = a # OK def foo(item: Any) -> int: - # Typechecks; 'item' could be any type, + # Passes type checking; 'item' could be any type, # and that type might have a 'bar' method item.bar() ... -Notice that no typechecking is performed when assigning a value of type +Notice that no type checking is performed when assigning a value of type :data:`Any` to a more precise type. For example, the static type checker did not report an error when assigning ``a`` to ``s`` even though ``s`` was declared to be of type :class:`str` and receives an :class:`int` value at @@ -481,20 +494,20 @@ it as a return value) of a more specialized type is a type error. For example:: def hash_a(item: object) -> int: - # Fails; an object does not have a 'magic' method. + # Fails type checking; an object does not have a 'magic' method. item.magic() ... def hash_b(item: Any) -> int: - # Typechecks + # Passes type checking item.magic() ... - # Typechecks, since ints and strs are subclasses of object + # Passes type checking, since ints and strs are subclasses of object hash_a(42) hash_a("foo") - # Typechecks, since Any is compatible with all types + # Passes type checking, since Any is compatible with all types hash_b(42) hash_b("foo") @@ -626,8 +639,8 @@ is equivalent to ``Tuple[Any, ...]``, and in turn to :class:`tuple`. .. deprecated:: 3.9 - :class:`builtins.tuple ` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`builtins.tuple ` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. data:: Union @@ -715,12 +728,12 @@ respectively. .. deprecated:: 3.9 - :class:`collections.abc.Callable` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.abc.Callable` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. versionchanged:: 3.10 ``Callable`` now supports :class:`ParamSpec` and :data:`Concatenate`. - See :pep:`612` for more information. + See :pep:`612` for more details. .. seealso:: The documentation for :class:`ParamSpec` and :class:`Concatenate` provide @@ -822,8 +835,8 @@ .. versionadded:: 3.5.2 .. deprecated:: 3.9 - :class:`builtins.type ` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`builtins.type ` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. data:: Literal @@ -1045,8 +1058,7 @@ is not a subtype of the former, since ``List`` is invariant. The responsibility of writing type-safe type guards is left to the user. - ``TypeGuard`` also works with type variables. For more information, see - :pep:`647` (User-Defined Type Guards). + ``TypeGuard`` also works with type variables. See :pep:`647` for more details. .. versionadded:: 3.10 @@ -1318,7 +1330,7 @@ func(C()) # Passes static type check - See :pep:`544` for details. Protocol classes decorated with + See :pep:`544` for more details. Protocol classes decorated with :func:`runtime_checkable` (described later) act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. @@ -1346,16 +1358,32 @@ assert isinstance(open('/some/file'), Closable) + @runtime_checkable + class Named(Protocol): + name: str + + import threading + assert isinstance(threading.Thread(name='Bob'), Named) + .. note:: - :func:`runtime_checkable` will check only the presence of the required - methods, not their type signatures. For example, :class:`ssl.SSLObject` + :func:`!runtime_checkable` will check only the presence of the required + methods or attributes, not their type signatures or types. + For example, :class:`ssl.SSLObject` is a class, therefore it passes an :func:`issubclass` check against :data:`Callable`. However, the - :meth:`ssl.SSLObject.__init__` method exists only to raise a + ``ssl.SSLObject.__init__`` method exists only to raise a :exc:`TypeError` with a more informative message, therefore making it impossible to call (instantiate) :class:`ssl.SSLObject`. + .. note:: + + An :func:`isinstance` check against a runtime-checkable protocol can be + surprisingly slow compared to an ``isinstance()`` check against + a non-protocol class. Consider using alternative idioms such as + :func:`hasattr` calls for structural checks in performance-sensitive + code. + .. versionadded:: 3.8 Other special directives @@ -1593,8 +1621,8 @@ ... .. deprecated:: 3.9 - :class:`builtins.dict ` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`builtins.dict ` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: List(list, MutableSequence[T]) @@ -1614,8 +1642,8 @@ return [item for item in vector if item > 0] .. deprecated:: 3.9 - :class:`builtins.list ` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`builtins.list ` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Set(set, MutableSet[T]) @@ -1624,16 +1652,17 @@ to use an abstract collection type such as :class:`AbstractSet`. .. deprecated:: 3.9 - :class:`builtins.set ` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`builtins.set ` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: FrozenSet(frozenset, AbstractSet[T_co]) A generic version of :class:`builtins.frozenset `. .. deprecated:: 3.9 - :class:`builtins.frozenset ` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`builtins.frozenset ` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. note:: :data:`Tuple` is a special form. @@ -1647,8 +1676,8 @@ .. versionadded:: 3.5.2 .. deprecated:: 3.9 - :class:`collections.defaultdict` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.defaultdict` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: OrderedDict(collections.OrderedDict, MutableMapping[KT, VT]) @@ -1657,8 +1686,8 @@ .. versionadded:: 3.7.2 .. deprecated:: 3.9 - :class:`collections.OrderedDict` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.OrderedDict` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: ChainMap(collections.ChainMap, MutableMapping[KT, VT]) @@ -1668,8 +1697,8 @@ .. versionadded:: 3.6.1 .. deprecated:: 3.9 - :class:`collections.ChainMap` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.ChainMap` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Counter(collections.Counter, Dict[T, int]) @@ -1679,8 +1708,8 @@ .. versionadded:: 3.6.1 .. deprecated:: 3.9 - :class:`collections.Counter` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.Counter` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Deque(deque, MutableSequence[T]) @@ -1690,8 +1719,8 @@ .. versionadded:: 3.6.1 .. deprecated:: 3.9 - :class:`collections.deque` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.deque` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. Other concrete types """""""""""""""""""" @@ -1705,7 +1734,7 @@ represent the types of I/O streams such as returned by :func:`open`. - .. deprecated-removed:: 3.8 3.12 + .. deprecated-removed:: 3.8 3.13 The ``typing.io`` namespace is deprecated and will be removed. These types should be directly imported from ``typing`` instead. @@ -1719,7 +1748,7 @@ ``Pattern[str]``, ``Pattern[bytes]``, ``Match[str]``, or ``Match[bytes]``. - .. deprecated-removed:: 3.8 3.12 + .. deprecated-removed:: 3.8 3.13 The ``typing.re`` namespace is deprecated and will be removed. These types should be directly imported from ``typing`` instead. @@ -1747,13 +1776,13 @@ Corresponding to collections in :mod:`collections.abc` """""""""""""""""""""""""""""""""""""""""""""""""""""" -.. class:: AbstractSet(Sized, Collection[T_co]) +.. class:: AbstractSet(Collection[T_co]) A generic version of :class:`collections.abc.Set`. .. deprecated:: 3.9 - :class:`collections.abc.Set` now supports ``[]``. See :pep:`585` and - :ref:`types-genericalias`. + :class:`collections.abc.Set` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: ByteString(Sequence[int]) @@ -1766,8 +1795,8 @@ annotate arguments of any of the types mentioned above. .. deprecated:: 3.9 - :class:`collections.abc.ByteString` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.ByteString` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Collection(Sized, Iterable[T_co], Container[T_co]) @@ -1776,34 +1805,34 @@ .. versionadded:: 3.6.0 .. deprecated:: 3.9 - :class:`collections.abc.Collection` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Collection` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Container(Generic[T_co]) A generic version of :class:`collections.abc.Container`. .. deprecated:: 3.9 - :class:`collections.abc.Container` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Container` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. -.. class:: ItemsView(MappingView, Generic[KT_co, VT_co]) +.. class:: ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]]) A generic version of :class:`collections.abc.ItemsView`. .. deprecated:: 3.9 - :class:`collections.abc.ItemsView` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.ItemsView` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. -.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co]) +.. class:: KeysView(MappingView, AbstractSet[KT_co]) A generic version of :class:`collections.abc.KeysView`. .. deprecated:: 3.9 - :class:`collections.abc.KeysView` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.KeysView` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. -.. class:: Mapping(Sized, Collection[KT], Generic[VT_co]) +.. class:: Mapping(Collection[KT], Generic[KT, VT_co]) A generic version of :class:`collections.abc.Mapping`. This type can be used as follows:: @@ -1812,56 +1841,58 @@ return word_list[word] .. deprecated:: 3.9 - :class:`collections.abc.Mapping` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Mapping` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. -.. class:: MappingView(Sized, Iterable[T_co]) +.. class:: MappingView(Sized) A generic version of :class:`collections.abc.MappingView`. .. deprecated:: 3.9 - :class:`collections.abc.MappingView` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.MappingView` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: MutableMapping(Mapping[KT, VT]) A generic version of :class:`collections.abc.MutableMapping`. .. deprecated:: 3.9 - :class:`collections.abc.MutableMapping` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`collections.abc.MutableMapping` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: MutableSequence(Sequence[T]) A generic version of :class:`collections.abc.MutableSequence`. .. deprecated:: 3.9 - :class:`collections.abc.MutableSequence` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`collections.abc.MutableSequence` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: MutableSet(AbstractSet[T]) A generic version of :class:`collections.abc.MutableSet`. .. deprecated:: 3.9 - :class:`collections.abc.MutableSet` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.MutableSet` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Sequence(Reversible[T_co], Collection[T_co]) A generic version of :class:`collections.abc.Sequence`. .. deprecated:: 3.9 - :class:`collections.abc.Sequence` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Sequence` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. -.. class:: ValuesView(MappingView[VT_co]) +.. class:: ValuesView(MappingView, Collection[_VT_co]) A generic version of :class:`collections.abc.ValuesView`. .. deprecated:: 3.9 - :class:`collections.abc.ValuesView` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.ValuesView` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. Corresponding to other types in :mod:`collections.abc` """""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -1871,16 +1902,16 @@ A generic version of :class:`collections.abc.Iterable`. .. deprecated:: 3.9 - :class:`collections.abc.Iterable` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Iterable` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Iterator(Iterable[T_co]) A generic version of :class:`collections.abc.Iterator`. .. deprecated:: 3.9 - :class:`collections.abc.Iterator` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Iterator` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]) @@ -1914,8 +1945,8 @@ start += 1 .. deprecated:: 3.9 - :class:`collections.abc.Generator` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Generator` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Hashable @@ -1926,8 +1957,8 @@ A generic version of :class:`collections.abc.Reversible`. .. deprecated:: 3.9 - :class:`collections.abc.Reversible` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Reversible` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Sized @@ -1951,8 +1982,8 @@ .. versionadded:: 3.5.3 .. deprecated:: 3.9 - :class:`collections.abc.Coroutine` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Coroutine` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra]) @@ -1988,8 +2019,9 @@ .. versionadded:: 3.6.1 .. deprecated:: 3.9 - :class:`collections.abc.AsyncGenerator` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`collections.abc.AsyncGenerator` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: AsyncIterable(Generic[T_co]) @@ -1998,8 +2030,8 @@ .. versionadded:: 3.5.2 .. deprecated:: 3.9 - :class:`collections.abc.AsyncIterable` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.AsyncIterable` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: AsyncIterator(AsyncIterable[T_co]) @@ -2008,8 +2040,8 @@ .. versionadded:: 3.5.2 .. deprecated:: 3.9 - :class:`collections.abc.AsyncIterator` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.AsyncIterator` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: Awaitable(Generic[T_co]) @@ -2018,8 +2050,8 @@ .. versionadded:: 3.5.2 .. deprecated:: 3.9 - :class:`collections.abc.Awaitable` now supports ``[]``. See :pep:`585` - and :ref:`types-genericalias`. + :class:`collections.abc.Awaitable` now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. Context manager types @@ -2033,8 +2065,9 @@ .. versionadded:: 3.6.0 .. deprecated:: 3.9 - :class:`contextlib.AbstractContextManager` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`contextlib.AbstractContextManager` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. .. class:: AsyncContextManager(Generic[T_co]) @@ -2044,8 +2077,9 @@ .. versionadded:: 3.6.2 .. deprecated:: 3.9 - :class:`contextlib.AbstractAsyncContextManager` now supports ``[]``. See - :pep:`585` and :ref:`types-genericalias`. + :class:`contextlib.AbstractAsyncContextManager` + now supports subscripting (``[]``). + See :pep:`585` and :ref:`types-genericalias`. Protocols --------- @@ -2122,7 +2156,7 @@ def process(response): - See :pep:`484` for details and comparison with other typing semantics. + See :pep:`484` for more details and comparison with other typing semantics. .. decorator:: final diff -Nru python3.10-3.10.7/Doc/library/unittest.mock-examples.rst python3.10-3.10.12/Doc/library/unittest.mock-examples.rst --- python3.10-3.10.7/Doc/library/unittest.mock-examples.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/unittest.mock-examples.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1116,7 +1116,7 @@ That aside there is a way to use ``mock`` to affect the results of an import. Importing fetches an *object* from the :data:`sys.modules` dictionary. Note that it fetches an *object*, which need not be a module. Importing a module for the -first time results in a module object being put in `sys.modules`, so usually +first time results in a module object being put in ``sys.modules``, so usually when you import something you get a module back. This need not be the case however. diff -Nru python3.10-3.10.7/Doc/library/unittest.mock.rst python3.10-3.10.12/Doc/library/unittest.mock.rst --- python3.10-3.10.7/Doc/library/unittest.mock.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/unittest.mock.rst 2023-06-06 22:30:33.000000000 +0000 @@ -406,7 +406,7 @@ False .. versionchanged:: 3.6 - Added two keyword only argument to the reset_mock function. + Added two keyword-only arguments to the reset_mock function. This can be useful where you want to make a series of assertions that reuse the same object. Note that :meth:`reset_mock` *doesn't* clear the @@ -416,8 +416,8 @@ parameter as ``True``. Child mocks and the return value mock (if any) are reset as well. - .. note:: *return_value*, and :attr:`side_effect` are keyword only - argument. + .. note:: *return_value*, and :attr:`side_effect` are keyword-only + arguments. .. method:: mock_add_spec(spec, spec_set=False) diff -Nru python3.10-3.10.7/Doc/library/unittest.rst python3.10-3.10.12/Doc/library/unittest.rst --- python3.10-3.10.7/Doc/library/unittest.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/unittest.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1738,7 +1738,7 @@ A list of the non-fatal errors encountered while loading tests. Not reset by the loader at any point. Fatal errors are signalled by the relevant - a method raising an exception to the caller. Non-fatal errors are also + method raising an exception to the caller. Non-fatal errors are also indicated by a synthetic test that will raise the original error when run. @@ -1920,12 +1920,12 @@ .. attribute:: testNamePatterns List of Unix shell-style wildcard test name patterns that test methods - have to match to be included in test suites (see ``-v`` option). + have to match to be included in test suites (see ``-k`` option). If this attribute is not ``None`` (the default), all test methods to be included in test suites must match one of the patterns in this list. Note that matches are always performed using :meth:`fnmatch.fnmatchcase`, - so unlike patterns passed to the ``-v`` option, simple substring patterns + so unlike patterns passed to the ``-k`` option, simple substring patterns will have to be converted using ``*`` wildcards. This affects all the :meth:`loadTestsFrom\*` methods. diff -Nru python3.10-3.10.7/Doc/library/urllib.parse.rst python3.10-3.10.12/Doc/library/urllib.parse.rst --- python3.10-3.10.7/Doc/library/urllib.parse.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/urllib.parse.rst 2023-06-06 22:30:33.000000000 +0000 @@ -113,7 +113,8 @@ +------------------+-------+-------------------------+------------------------+ | :attr:`path` | 2 | Hierarchical path | empty string | +------------------+-------+-------------------------+------------------------+ - | :attr:`params` | 3 | No longer used | always an empty string | + | :attr:`params` | 3 | Parameters for last | empty string | + | | | path element | | +------------------+-------+-------------------------+------------------------+ | :attr:`query` | 4 | Query component | empty string | +------------------+-------+-------------------------+------------------------+ @@ -158,6 +159,10 @@ ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', params='', query='', fragment='') + .. warning:: + + :func:`urlparse` does not perform validation. See :ref:`URL parsing + security ` for details. .. versionchanged:: 3.2 Added IPv6 URL parsing capabilities. @@ -323,8 +328,14 @@ ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is decomposed before parsing, no error will be raised. - Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline - ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL. + Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0 + control and space characters are stripped from the URL. ``\n``, + ``\r`` and tab ``\t`` characters are removed from the URL at any position. + + .. warning:: + + :func:`urlsplit` does not perform validation. See :ref:`URL parsing + security ` for details. .. versionchanged:: 3.6 Out-of-range port numbers now raise :exc:`ValueError`, instead of @@ -337,6 +348,9 @@ .. versionchanged:: 3.10 ASCII newline and tab characters are stripped from the URL. + .. versionchanged:: 3.10.12 + Leading WHATWG C0 control and space characters are stripped from the URL. + .. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser .. function:: urlunsplit(parts) @@ -413,6 +427,27 @@ or ``scheme://host/path``). If *url* is not a wrapped URL, it is returned without changes. +.. _url-parsing-security: + +URL parsing security +-------------------- + +The :func:`urlsplit` and :func:`urlparse` APIs do not perform **validation** of +inputs. They may not raise errors on inputs that other applications consider +invalid. They may also succeed on some inputs that might not be considered +URLs elsewhere. Their purpose is for practical functionality rather than +purity. + +Instead of raising an exception on unusual input, they may instead return some +component parts as empty strings. Or components may contain more than perhaps +they should. + +We recommend that users of these APIs where the values may be used anywhere +with security implications code defensively. Do some verification within your +code before trusting a returned component part. Does that ``scheme`` make +sense? Is that a sensible ``path``? Is there anything strange about that +``hostname``? etc. + .. _parsing-ascii-encoded-bytes: Parsing ASCII Encoded Bytes diff -Nru python3.10-3.10.7/Doc/library/urllib.request.rst python3.10-3.10.12/Doc/library/urllib.request.rst --- python3.10-3.10.7/Doc/library/urllib.request.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/urllib.request.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1619,7 +1619,7 @@ .. deprecated:: 3.9 Deprecated in favor of :attr:`~addinfourl.status`. - .. method:: getstatus() + .. method:: getcode() .. deprecated:: 3.9 Deprecated in favor of :attr:`~addinfourl.status`. diff -Nru python3.10-3.10.7/Doc/library/venv.rst python3.10-3.10.12/Doc/library/venv.rst --- python3.10-3.10.7/Doc/library/venv.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/venv.rst 2023-06-06 22:30:33.000000000 +0000 @@ -15,74 +15,117 @@ -------------- -The :mod:`venv` module provides support for creating lightweight "virtual -environments" with their own site directories, optionally isolated from system -site directories. Each virtual environment has its own Python binary (which -matches the version of the binary that was used to create this environment) and -can have its own independent set of installed Python packages in its site -directories. +.. _venv-def: +.. _venv-intro: + +The :mod:`!venv` module supports creating lightweight "virtual environments", +each with their own independent set of Python packages installed in +their :mod:`site` directories. +A virtual environment is created on top of an existing +Python installation, known as the virtual environment's "base" Python, and may +optionally be isolated from the packages in the base environment, +so only those explicitly installed in the virtual environment are available. + +When used from within a virtual environment, common installation tools such as +`pip`_ will install Python packages into a virtual environment +without needing to be told to do so explicitly. -See :pep:`405` for more information about Python virtual environments. +See :pep:`405` for more background on Python virtual environments. .. seealso:: `Python Packaging User Guide: Creating and using virtual environments `__ - Creating virtual environments ----------------------------- .. include:: /using/venv-create.inc +.. _venv-explanation: -.. _venv-def: +How venvs work +-------------- -.. note:: A virtual environment is a Python environment such that the Python - interpreter, libraries and scripts installed into it are isolated from those - installed in other virtual environments, and (by default) any libraries - installed in a "system" Python, i.e., one which is installed as part of your - operating system. - - A virtual environment is a directory tree which contains Python executable - files and other files which indicate that it is a virtual environment. - - Common installation tools such as setuptools_ and pip_ work as - expected with virtual environments. In other words, when a virtual - environment is active, they install Python packages into the virtual - environment without needing to be told to do so explicitly. - - When a virtual environment is active (i.e., the virtual environment's Python - interpreter is running), the attributes :attr:`sys.prefix` and - :attr:`sys.exec_prefix` point to the base directory of the virtual - environment, whereas :attr:`sys.base_prefix` and - :attr:`sys.base_exec_prefix` point to the non-virtual environment Python - installation which was used to create the virtual environment. If a virtual - environment is not active, then :attr:`sys.prefix` is the same as - :attr:`sys.base_prefix` and :attr:`sys.exec_prefix` is the same as - :attr:`sys.base_exec_prefix` (they all point to a non-virtual environment - Python installation). - - When a virtual environment is active, any options that change the - installation path will be ignored from all :mod:`distutils` configuration - files to prevent projects being inadvertently installed outside of the - virtual environment. - - When working in a command shell, users can make a virtual environment active - by running an ``activate`` script in the virtual environment's executables - directory (the precise filename and command to use the file is - shell-dependent), which prepends the virtual environment's directory for - executables to the ``PATH`` environment variable for the running shell. There - should be no need in other circumstances to activate a virtual - environment; scripts installed into virtual environments have a "shebang" - line which points to the virtual environment's Python interpreter. This means - that the script will run with that interpreter regardless of the value of - ``PATH``. On Windows, "shebang" line processing is supported if you have the - Python Launcher for Windows installed (this was added to Python in 3.3 - see - :pep:`397` for more details). Thus, double-clicking an installed script in a - Windows Explorer window should run the script with the correct interpreter - without there needing to be any reference to its virtual environment in - ``PATH``. +When a Python interpreter is running from a virtual environment, +:data:`sys.prefix` and :data:`sys.exec_prefix` +point to the directories of the virtual environment, +whereas :data:`sys.base_prefix` and :data:`sys.base_exec_prefix` +point to those of the base Python used to create the environment. +It is sufficient to check +``sys.prefix == sys.base_prefix`` to determine if the current interpreter is +running from a virtual environment. + +A virtual environment may be "activated" using a script in its binary directory +(``bin`` on POSIX; ``Scripts`` on Windows). +This will prepend that directory to your :envvar:`!PATH`, so that running +:program:`python` will invoke the environment's Python interpreter +and you can run installed scripts without having to use their full path. +The invocation of the activation script is platform-specific +(:samp:`{}` must be replaced by the path to the directory +containing the virtual environment): + ++-------------+------------+--------------------------------------------------+ +| Platform | Shell | Command to activate virtual environment | ++=============+============+==================================================+ +| POSIX | bash/zsh | :samp:`$ source {}/bin/activate` | +| +------------+--------------------------------------------------+ +| | fish | :samp:`$ source {}/bin/activate.fish` | +| +------------+--------------------------------------------------+ +| | csh/tcsh | :samp:`$ source {}/bin/activate.csh` | +| +------------+--------------------------------------------------+ +| | PowerShell | :samp:`$ {}/bin/Activate.ps1` | ++-------------+------------+--------------------------------------------------+ +| Windows | cmd.exe | :samp:`C:\\> {}\\Scripts\\activate.bat` | +| +------------+--------------------------------------------------+ +| | PowerShell | :samp:`PS C:\\> {}\\Scripts\\Activate.ps1` | ++-------------+------------+--------------------------------------------------+ + +.. versionadded:: 3.4 + :program:`fish` and :program:`csh` activation scripts. + +.. versionadded:: 3.8 + PowerShell activation scripts installed under POSIX for PowerShell Core + support. + +You don't specifically *need* to activate a virtual environment, +as you can just specify the full path to that environment's +Python interpreter when invoking Python. +Furthermore, all scripts installed in the environment +should be runnable without activating it. + +In order to achieve this, scripts installed into virtual environments have +a "shebang" line which points to the environment's Python interpreter, +i.e. :samp:`#!/{}/bin/python`. +This means that the script will run with that interpreter regardless of the +value of :envvar:`!PATH`. On Windows, "shebang" line processing is supported if +you have the :ref:`launcher` installed. Thus, double-clicking an installed +script in a Windows Explorer window should run it with the correct interpreter +without the environment needing to be activated or on the :envvar:`!PATH`. + +When a virtual environment has been activated, the :envvar:`!VIRTUAL_ENV` +environment variable is set to the path of the environment. +Since explicitly activating a virtual environment is not required to use it, +:envvar:`!VIRTUAL_ENV` cannot be relied upon to determine +whether a virtual environment is being used. + +.. warning:: Because scripts installed in environments should not expect the + environment to be activated, their shebang lines contain the absolute paths + to their environment's interpreters. Because of this, environments are + inherently non-portable, in the general case. You should always have a + simple means of recreating an environment (for example, if you have a + requirements file ``requirements.txt``, you can invoke ``pip install -r + requirements.txt`` using the environment's ``pip`` to install all of the + packages needed by the environment). If for any reason you need to move the + environment to a new location, you should recreate it at the desired + location and delete the one at the old location. If you move an environment + because you moved a parent directory of it, you should recreate the + environment in its new location. Otherwise, software installed into the + environment may not work as expected. + +You can deactivate a virtual environment by typing ``deactivate`` in your shell. +The exact mechanism is platform-specific and is an internal implementation +detail (typically, a script or shell function will be used). .. _venv-api: @@ -170,11 +213,56 @@ .. method:: ensure_directories(env_dir) - Creates the environment directory and all necessary directories, and - returns a context object. This is just a holder for attributes (such as - paths), for use by the other methods. The directories are allowed to - exist already, as long as either ``clear`` or ``upgrade`` were - specified to allow operating on an existing environment directory. + Creates the environment directory and all necessary subdirectories that + don't already exist, and returns a context object. This context object + is just a holder for attributes (such as paths) for use by the other + methods. If the :class:`EnvBuilder` is created with the arg + ``clear=True``, contents of the environment directory will be cleared + and then all necessary subdirectories will be recreated. + + The returned context object is a :class:`types.SimpleNamespace` with the + following attributes: + + * ``env_dir`` - The location of the virtual environment. Used for + ``__VENV_DIR__`` in activation scripts (see :meth:`install_scripts`). + + * ``env_name`` - The name of the virtual environment. Used for + ``__VENV_NAME__`` in activation scripts (see :meth:`install_scripts`). + + * ``prompt`` - The prompt to be used by the activation scripts. Used for + ``__VENV_PROMPT__`` in activation scripts (see :meth:`install_scripts`). + + * ``executable`` - The underlying Python executable used by the virtual + environment. This takes into account the case where a virtual environment + is created from another virtual environment. + + * ``inc_path`` - The include path for the virtual environment. + + * ``lib_path`` - The purelib path for the virtual environment. + + * ``bin_path`` - The script path for the virtual environment. + + * ``bin_name`` - The name of the script path relative to the virtual + environment location. Used for ``__VENV_BIN_NAME__`` in activation + scripts (see :meth:`install_scripts`). + + * ``env_exe`` - The name of the Python interpreter in the virtual + environment. Used for ``__VENV_PYTHON__`` in activation scripts + (see :meth:`install_scripts`). + + * ``env_exec_cmd`` - The name of the Python interpreter, taking into + account filesystem redirections. This can be used to run Python in + the virtual environment. + + + .. versionchanged:: 3.12 + The attribute ``lib_path`` was added to the context, and the context + object was documented. + + .. versionchanged:: 3.11 + The *venv* + :ref:`sysconfig installation scheme ` + is used to construct the paths of the created directories. .. method:: create_configuration(context) diff -Nru python3.10-3.10.7/Doc/library/wave.rst python3.10-3.10.12/Doc/library/wave.rst --- python3.10-3.10.7/Doc/library/wave.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/wave.rst 2023-06-06 22:30:33.000000000 +0000 @@ -12,7 +12,8 @@ -------------- The :mod:`wave` module provides a convenient interface to the WAV sound format. -It does not support compression/decompression, but it does support mono/stereo. +Only files using ``WAVE_FORMAT_PCM`` are supported. Note that this does not +include files using ``WAVE_FORMAT_EXTENSIBLE`` even if the subformat is PCM. The :mod:`wave` module defines the following function and exception: diff -Nru python3.10-3.10.7/Doc/library/weakref.rst python3.10-3.10.12/Doc/library/weakref.rst --- python3.10-3.10.7/Doc/library/weakref.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/weakref.rst 2023-06-06 22:30:33.000000000 +0000 @@ -144,6 +144,9 @@ prevent their use as dictionary keys. *callback* is the same as the parameter of the same name to the :func:`ref` function. + Accessing an attribute of the proxy object after the referent is + garbage collected raises :exc:`ReferenceError`. + .. versionchanged:: 3.8 Extended the operator support on proxy objects to include the matrix multiplication operators ``@`` and ``@=``. @@ -167,6 +170,30 @@ application without adding attributes to those objects. This can be especially useful with objects that override attribute accesses. + Note that when a key with equal value to an existing key (but not equal identity) + is inserted into the dictionary, it replaces the value but does not replace the + existing key. Due to this, when the reference to the original key is deleted, it + also deletes the entry in the dictionary:: + + >>> class T(str): pass + ... + >>> k1, k2 = T(), T() + >>> d = weakref.WeakKeyDictionary() + >>> d[k1] = 1 # d = {k1: 1} + >>> d[k2] = 2 # d = {k1: 2} + >>> del k1 # d = {} + + A workaround would be to remove the key prior to reassignment:: + + >>> class T(str): pass + ... + >>> k1, k2 = T(), T() + >>> d = weakref.WeakKeyDictionary() + >>> d[k1] = 1 # d = {k1: 1} + >>> del d[k1] + >>> d[k2] = 2 # d = {k2: 2} + >>> del k1 # d = {k2: 2} + .. versionchanged:: 3.9 Added support for ``|`` and ``|=`` operators, specified in :pep:`584`. diff -Nru python3.10-3.10.7/Doc/library/wsgiref.rst python3.10-3.10.12/Doc/library/wsgiref.rst --- python3.10-3.10.7/Doc/library/wsgiref.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/wsgiref.rst 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,8 @@ .. moduleauthor:: Phillip J. Eby .. sectionauthor:: Phillip J. Eby +**Source code:** :source:`Lib/wsgiref` + -------------- The Web Server Gateway Interface (WSGI) is a standard interface between web diff -Nru python3.10-3.10.7/Doc/library/xml.dom.minidom.rst python3.10-3.10.12/Doc/library/xml.dom.minidom.rst --- python3.10-3.10.7/Doc/library/xml.dom.minidom.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/xml.dom.minidom.rst 2023-06-06 22:30:33.000000000 +0000 @@ -148,8 +148,8 @@ Similarly, explicitly stating the *standalone* argument causes the standalone document declarations to be added to the prologue of the XML document. - If the value is set to `True`, `standalone="yes"` is added, - otherwise it is set to `"no"`. + If the value is set to ``True``, ``standalone="yes"`` is added, + otherwise it is set to ``"no"``. Not stating the argument will omit the declaration from the document. .. versionchanged:: 3.8 diff -Nru python3.10-3.10.7/Doc/library/xmlrpc.client.rst python3.10-3.10.12/Doc/library/xmlrpc.client.rst --- python3.10-3.10.7/Doc/library/xmlrpc.client.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/xmlrpc.client.rst 2023-06-06 22:30:33.000000000 +0000 @@ -58,7 +58,7 @@ may be passed to calls. The *headers* parameter is an optional sequence of HTTP headers to send with each request, expressed as a sequence of 2-tuples representing the header - name and value. (e.g. `[('Header-Name', 'value')]`). + name and value. (e.g. ``[('Header-Name', 'value')]``). The obsolete *use_datetime* flag is similar to *use_builtin_types* but it applies only to date/time values. @@ -163,7 +163,7 @@ A good description of XML-RPC operation and client software in several languages. Contains pretty much everything an XML-RPC client developer needs to know. - `XML-RPC Introspection `_ + `XML-RPC Introspection `_ Describes the XML-RPC protocol extension for introspection. `XML-RPC Specification `_ diff -Nru python3.10-3.10.7/Doc/library/xmlrpc.server.rst python3.10-3.10.12/Doc/library/xmlrpc.server.rst --- python3.10-3.10.7/Doc/library/xmlrpc.server.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/xmlrpc.server.rst 2023-06-06 22:30:33.000000000 +0000 @@ -262,7 +262,7 @@ The client that interacts with the above server is included in -`Lib/xmlrpc/client.py`:: +``Lib/xmlrpc/client.py``:: server = ServerProxy("http://localhost:8000") diff -Nru python3.10-3.10.7/Doc/library/zipapp.rst python3.10-3.10.12/Doc/library/zipapp.rst --- python3.10-3.10.7/Doc/library/zipapp.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/zipapp.rst 2023-06-06 22:30:33.000000000 +0000 @@ -215,7 +215,7 @@ >>> import zipapp >>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3') -To update the file in place, do the replacement in memory using a :class:`BytesIO` +To update the file in place, do the replacement in memory using a :class:`~io.BytesIO` object, and then overwrite the source afterwards. Note that there is a risk when overwriting a file in place that an error will result in the loss of the original file. This code does not protect against such errors, but diff -Nru python3.10-3.10.7/Doc/library/zipfile.rst python3.10-3.10.12/Doc/library/zipfile.rst --- python3.10-3.10.7/Doc/library/zipfile.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/zipfile.rst 2023-06-06 22:30:33.000000000 +0000 @@ -55,8 +55,9 @@ .. class:: Path :noindex: - A pathlib-compatible wrapper for zip files. See section - :ref:`path-objects` for details. + Class that implements a subset of the interface provided by + :class:`pathlib.Path`, including the full + :class:`importlib.resources.abc.Traversable` interface. .. versionadded:: 3.8 @@ -251,7 +252,8 @@ Access a member of the archive as a binary file-like object. *name* can be either the name of a file within the archive or a :class:`ZipInfo` object. The *mode* parameter, if included, must be ``'r'`` (the default) - or ``'w'``. *pwd* is the password used to decrypt encrypted ZIP files. + or ``'w'``. *pwd* is the password used to decrypt encrypted ZIP files as a + :class:`bytes` object. :meth:`~ZipFile.open` is also a context manager and therefore supports the :keyword:`with` statement:: @@ -264,7 +266,7 @@ (``ZipExtFile``) is read-only and provides the following methods: :meth:`~io.BufferedIOBase.read`, :meth:`~io.IOBase.readline`, :meth:`~io.IOBase.readlines`, :meth:`~io.IOBase.seek`, - :meth:`~io.IOBase.tell`, :meth:`__iter__`, :meth:`~iterator.__next__`. + :meth:`~io.IOBase.tell`, :meth:`~container.__iter__`, :meth:`~iterator.__next__`. These objects can operate independently of the ZipFile. With ``mode='w'``, a writable file handle is returned, which supports the @@ -303,7 +305,7 @@ must be its full name or a :class:`ZipInfo` object. Its file information is extracted as accurately as possible. *path* specifies a different directory to extract to. *member* can be a filename or a :class:`ZipInfo` object. - *pwd* is the password used for encrypted files. + *pwd* is the password used for encrypted files as a :class:`bytes` object. Returns the normalized path created (a directory or new file). @@ -330,7 +332,7 @@ Extract all members from the archive to the current working directory. *path* specifies a different directory to extract to. *members* is optional and must be a subset of the list returned by :meth:`namelist`. *pwd* is the password - used for encrypted files. + used for encrypted files as a :class:`bytes` object. .. warning:: @@ -355,16 +357,16 @@ .. method:: ZipFile.setpassword(pwd) - Set *pwd* as default password to extract encrypted files. + Set *pwd* (a :class:`bytes` object) as default password to extract encrypted files. .. method:: ZipFile.read(name, pwd=None) Return the bytes of the file *name* in the archive. *name* is the name of the file in the archive, or a :class:`ZipInfo` object. The archive must be open for - read or append. *pwd* is the password used for encrypted files and, if specified, - it will override the default password set with :meth:`setpassword`. Calling - :meth:`read` on a ZipFile that uses a compression method other than + read or append. *pwd* is the password used for encrypted files as a :class:`bytes` + object and, if specified, overrides the default password set with :meth:`setpassword`. + Calling :meth:`read` on a ZipFile that uses a compression method other than :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or :const:`ZIP_LZMA` will raise a :exc:`NotImplementedError`. An error will also be raised if the corresponding compression module is not available. @@ -508,6 +510,12 @@ Added support for text and binary modes for open. Default mode is now text. + .. versionchanged:: 3.10.10 + The ``encoding`` parameter can be supplied as a positional argument + without causing a :exc:`TypeError`. As it could in 3.9. Code needing to + be compatible with unpatched 3.10 and 3.11 versions must pass all + :class:`io.TextIOWrapper` arguments, ``encoding`` included, as keywords. + .. method:: Path.iterdir() Enumerate the children of the current directory. @@ -532,6 +540,12 @@ :class:`io.TextIOWrapper` (except ``buffer``, which is implied by the context). + .. versionchanged:: 3.10.10 + The ``encoding`` parameter can be supplied as a positional argument + without causing a :exc:`TypeError`. As it could in 3.9. Code needing to + be compatible with unpatched 3.10 and 3.11 versions must pass all + :class:`io.TextIOWrapper` arguments, ``encoding`` included, as keywords. + .. method:: Path.read_bytes() Read the current file as bytes. diff -Nru python3.10-3.10.7/Doc/library/zoneinfo.rst python3.10-3.10.12/Doc/library/zoneinfo.rst --- python3.10-3.10.7/Doc/library/zoneinfo.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/library/zoneinfo.rst 2023-06-06 22:30:33.000000000 +0000 @@ -9,6 +9,8 @@ .. moduleauthor:: Paul Ganssle .. sectionauthor:: Paul Ganssle +**Source code:** :source:`Lib/zoneinfo` + -------------- The :mod:`zoneinfo` module provides a concrete time zone implementation to diff -Nru python3.10-3.10.7/Doc/license.rst python3.10-3.10.12/Doc/license.rst --- python3.10-3.10.7/Doc/license.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/license.rst 2023-06-06 22:30:33.000000000 +0000 @@ -100,7 +100,7 @@ analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python |release| alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2022 Python Software Foundation; All Rights + copyright, i.e., "Copyright © 2001-2023 Python Software Foundation; All Rights Reserved" are retained in Python |release| alone or in any derivative version prepared by Licensee. @@ -984,3 +984,31 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Audioop +------- + +The audioop module uses the code base in g771.c file of the SoX project:: + + Programming the AdLib/Sound Blaster + FM Music Chips + Version 2.0 (24 Feb 1992) + Copyright (c) 1991, 1992 by Jeffrey S. Lee + jlee@smylex.uucp + Warranty and Copyright Policy + This document is provided on an "as-is" basis, and its author makes + no warranty or representation, express or implied, with respect to + its quality performance or fitness for a particular purpose. In no + event will the author of this document be liable for direct, indirect, + special, incidental, or consequential damages arising out of the use + or inability to use the information contained within. Use of this + document is at your own risk. + This file may be used and copied freely so long as the applicable + copyright notices are retained, and no modifications are made to the + text of the document. No money shall be charged for its distribution + beyond reasonable shipping, handling and duplication costs, nor shall + proprietary changes be made to this document so that it cannot be + distributed freely. This document may not be included in published + material or commercial packages without the written consent of its + author. diff -Nru python3.10-3.10.7/Doc/Makefile python3.10-3.10.12/Doc/Makefile --- python3.10-3.10.7/Doc/Makefile 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/Makefile 2023-06-06 22:30:33.000000000 +0000 @@ -8,6 +8,7 @@ VENVDIR = ./venv SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-build BLURB = PATH=$(VENVDIR)/bin:$$PATH blurb +JOBS = auto PAPER = SOURCES = DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py) @@ -17,7 +18,7 @@ PAPEROPT_a4 = -D latex_elements.papersize=a4paper PAPEROPT_letter = -D latex_elements.papersize=letterpaper -ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) -j auto \ +ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) -j $(JOBS) \ $(SPHINXOPTS) $(SPHINXERRORHANDLING) . build/$(BUILDER) $(SOURCES) .PHONY: help build html htmlhelp latex text texinfo changes linkcheck \ diff -Nru python3.10-3.10.7/Doc/README.rst python3.10-3.10.12/Doc/README.rst --- python3.10-3.10.7/Doc/README.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/README.rst 2023-06-06 22:30:33.000000000 +0000 @@ -40,7 +40,7 @@ you can specify it using the ``VENVDIR`` variable. You can also skip creating the virtual environment altogether, in which case -the Makefile will look for instances of ``sphinxbuild`` and ``blurb`` +the Makefile will look for instances of ``sphinx-build`` and ``blurb`` installed on your process ``PATH`` (configurable with the ``SPHINXBUILD`` and ``BLURB`` variables). @@ -91,7 +91,7 @@ * "pydoc-topics", which builds a Python module containing a dictionary with plain text documentation for the labels defined in - `tools/pyspecific.py` -- pydoc needs these to show topic and keyword help. + ``tools/pyspecific.py`` -- pydoc needs these to show topic and keyword help. * "suspicious", which checks the parsed markup for text that looks like malformed and thus unconverted reST. diff -Nru python3.10-3.10.7/Doc/reference/compound_stmts.rst python3.10-3.10.12/Doc/reference/compound_stmts.rst --- python3.10-3.10.7/Doc/reference/compound_stmts.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/compound_stmts.rst 2023-06-06 22:30:33.000000000 +0000 @@ -192,9 +192,8 @@ Names in the target list are not deleted when the loop is finished, but if the sequence is empty, they will not have been assigned to at all by the loop. Hint: -the built-in function :func:`range` returns an iterator of integers suitable to -emulate the effect of Pascal's ``for i := a to b do``; e.g., ``list(range(3))`` -returns the list ``[0, 1, 2]``. +the built-in type :func:`range` represents immutable arithmetic sequences of integers. +For instance, iterating ``range(3)`` successively yields 0, 1, and then 2. .. _try: @@ -416,7 +415,7 @@ method returns without an error, then :meth:`__exit__` will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would - be. See step 6 below. + be. See step 7 below. #. The suite is executed. @@ -503,6 +502,7 @@ keyword: if keyword: as pair: match; case + single: as; match statement single: : (colon); compound statement .. versionadded:: 3.10 @@ -729,7 +729,7 @@ If the OR pattern fails, the AS pattern fails. Otherwise, the AS pattern binds the subject to the name on the right of the as keyword and succeeds. -``capture_pattern`` cannot be a a ``_``. +``capture_pattern`` cannot be a ``_``. In simple terms ``P as NAME`` will match with ``P``, and on success it will set ``NAME = ``. diff -Nru python3.10-3.10.7/Doc/reference/datamodel.rst python3.10-3.10.12/Doc/reference/datamodel.rst --- python3.10-3.10.7/Doc/reference/datamodel.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/datamodel.rst 2023-06-06 22:30:33.000000000 +0000 @@ -316,7 +316,7 @@ A string is a sequence of values that represent Unicode code points. All the code points in the range ``U+0000 - U+10FFFF`` can be - represented in a string. Python doesn't have a :c:type:`char` type; + represented in a string. Python doesn't have a :c:expr:`char` type; instead, every code point in the string is represented as a string object with length ``1``. The built-in function :func:`ord` converts a code point from its string form to an integer in the @@ -1490,7 +1490,7 @@ :meth:`__hash__`, its instances will not be usable as items in hashable collections. If a class defines mutable objects and implements an :meth:`__eq__` method, it should not implement :meth:`__hash__`, since the - implementation of hashable collections requires that a key's hash value is + implementation of :term:`hashable` collections requires that a key's hash value is immutable (if the object's hash value changes, it will be in the wrong hash bucket). @@ -1837,6 +1837,8 @@ and *__weakref__* for each instance. +.. _datamodel-note-slots: + Notes on using *__slots__* """""""""""""""""""""""""" @@ -1874,8 +1876,10 @@ descriptor directly from the base class). This renders the meaning of the program undefined. In the future, a check may be added to prevent this. -* Nonempty *__slots__* does not work for classes derived from "variable-length" - built-in types such as :class:`int`, :class:`bytes` and :class:`tuple`. +* :exc:`TypeError` will be raised if nonempty *__slots__* are defined for a + class derived from a + :c:member:`"variable-length" built-in type ` such as + :class:`int`, :class:`bytes`, and :class:`tuple`. * Any non-string :term:`iterable` may be assigned to *__slots__*. @@ -2750,7 +2754,7 @@ When using a class name in a pattern, positional arguments in the pattern are not allowed by default, i.e. ``case MyClass(x, y)`` is typically invalid without special -support in ``MyClass``. To be able to use that kind of patterns, the class needs to +support in ``MyClass``. To be able to use that kind of pattern, the class needs to define a *__match_args__* attribute. .. data:: object.__match_args__ @@ -2877,6 +2881,14 @@ :term:`awaitable` objects. For instance, :class:`asyncio.Future` implements this method to be compatible with the :keyword:`await` expression. + .. note:: + + The language doesn't place any restriction on the type or value of the + objects yielded by the iterator returned by ``__await__``, as this is + specific to the implementation of the asynchronous execution framework + (e.g. :mod:`asyncio`) that will be managing the :term:`awaitable` object. + + .. versionadded:: 3.5 .. seealso:: :pep:`492` for additional information about awaitable objects. diff -Nru python3.10-3.10.7/Doc/reference/executionmodel.rst python3.10-3.10.12/Doc/reference/executionmodel.rst --- python3.10-3.10.7/Doc/reference/executionmodel.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/executionmodel.rst 2023-06-06 22:30:33.000000000 +0000 @@ -128,6 +128,8 @@ is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations. +See :ref:`the FAQ entry on UnboundLocalError ` +for examples. If the :keyword:`global` statement occurs within a block, all uses of the names specified in the statement refer to the bindings of those names in the top-level diff -Nru python3.10-3.10.7/Doc/reference/expressions.rst python3.10-3.10.12/Doc/reference/expressions.rst --- python3.10-3.10.7/Doc/reference/expressions.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/expressions.rst 2023-06-06 22:30:33.000000000 +0000 @@ -449,7 +449,9 @@ function. The execution starts when one of the generator's methods is called. At that time, the execution proceeds to the first yield expression, where it is suspended again, returning the value of :token:`~python-grammar:expression_list` -to the generator's caller. By suspended, we mean that all local state is +to the generator's caller, +or ``None`` if :token:`~python-grammar:expression_list` is omitted. +By suspended, we mean that all local state is retained, including the current bindings of local variables, the instruction pointer, the internal evaluation stack, and the state of any exception handling. When the execution is resumed by calling one of the generator's methods, the @@ -1049,10 +1051,20 @@ If the syntax ``**expression`` appears in the function call, ``expression`` must evaluate to a :term:`mapping`, the contents of which are treated as -additional keyword arguments. If a keyword is already present -(as an explicit keyword argument, or from another unpacking), +additional keyword arguments. If a parameter matching a key has already been +given a value (by an explicit keyword argument, or from another unpacking), a :exc:`TypeError` exception is raised. +When ``**expression`` is used, each key in this mapping must be +a string. +Each value from the mapping is assigned to the first formal parameter +eligible for keyword assignment whose name is equal to the key. +A key need not be a Python identifier (e.g. ``"max-temp °F"`` is acceptable, +although it will not match any formal parameter that could be declared). +If there is no match to a formal parameter +the key-value pair is collected by the ``**`` parameter, if there is one, +or if there is not, a :exc:`TypeError` exception is raised. + Formal parameters using the syntax ``*identifier`` or ``**identifier`` cannot be used as positional argument slots or as keyword argument names. @@ -1534,7 +1546,7 @@ true). * Mappings (instances of :class:`dict`) compare equal if and only if they have - equal `(key, value)` pairs. Equality comparison of the keys and values + equal ``(key, value)`` pairs. Equality comparison of the keys and values enforces reflexivity. Order comparisons (``<``, ``>``, ``<=``, and ``>=``) raise :exc:`TypeError`. @@ -1713,6 +1725,12 @@ (for example, ``not 'foo'`` produces ``False`` rather than ``''``.) +.. index:: + single: := (colon equals) + single: assignment expression + single: walrus operator + single: named expression + Assignment expressions ====================== @@ -1738,6 +1756,13 @@ while chunk := file.read(9000): process(chunk) +Assignment expressions must be surrounded by parentheses when used +as sub-expressions in slicing, conditional, lambda, +keyword-argument, and comprehension-if expressions +and in ``assert`` and ``with`` statements. +In all other places where they can be used, parentheses are not required, +including in ``if`` and ``while`` statements. + .. versionadded:: 3.8 See :pep:`572` for more details about assignment expressions. diff -Nru python3.10-3.10.7/Doc/reference/grammar.rst python3.10-3.10.12/Doc/reference/grammar.rst --- python3.10-3.10.7/Doc/reference/grammar.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/grammar.rst 2023-06-06 22:30:33.000000000 +0000 @@ -12,7 +12,7 @@ In particular, ``&`` followed by a symbol, token or parenthesized group indicates a positive lookahead (i.e., is required to match but not consumed), while ``!`` indicates a negative lookahead (i.e., is -required _not_ to match). We use the ``|`` separator to mean PEG's +required *not* to match). We use the ``|`` separator to mean PEG's "ordered choice" (written as ``/`` in traditional PEG grammars). See :pep:`617` for more details on the grammar's syntax. diff -Nru python3.10-3.10.7/Doc/reference/import.rst python3.10-3.10.12/Doc/reference/import.rst --- python3.10-3.10.7/Doc/reference/import.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/import.rst 2023-06-06 22:30:33.000000000 +0000 @@ -812,7 +812,7 @@ for each of these, looks for an appropriate :term:`path entry finder` (:class:`~importlib.abc.PathEntryFinder`) for the path entry. Because this can be an expensive operation (e.g. there may be -`stat()` call overheads for this search), the path based finder maintains +``stat()`` call overheads for this search), the path based finder maintains a cache mapping path entries to path entry finders. This cache is maintained in :data:`sys.path_importer_cache` (despite the name, this cache actually stores finder objects rather than being limited to :term:`importer` objects). @@ -1015,25 +1015,6 @@ to populate the ``__main__`` namespace, and not during normal import. -Open issues -=========== - -XXX It would be really nice to have a diagram. - -XXX * (import_machinery.rst) how about a section devoted just to the -attributes of modules and packages, perhaps expanding upon or supplanting the -related entries in the data model reference page? - -XXX runpy, pkgutil, et al in the library manual should all get "See Also" -links at the top pointing to the new import system section. - -XXX Add more explanation regarding the different ways in which -``__main__`` is initialized? - -XXX Add more info on ``__main__`` quirks/pitfalls (i.e. copy from -:pep:`395`). - - References ========== diff -Nru python3.10-3.10.7/Doc/reference/simple_stmts.rst python3.10-3.10.12/Doc/reference/simple_stmts.rst --- python3.10-3.10.7/Doc/reference/simple_stmts.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/reference/simple_stmts.rst 2023-06-06 22:30:33.000000000 +0000 @@ -330,7 +330,7 @@ annotated_assignment_stmt: `augtarget` ":" `expression` : ["=" (`starred_expression` | `yield_expression`)] -The difference from normal :ref:`assignment` is that only single target is allowed. +The difference from normal :ref:`assignment` is that only a single target is allowed. For simple names as assignment targets, if in class or module scope, the annotations are evaluated and stored in a special class or module @@ -365,8 +365,8 @@ IDEs. .. versionchanged:: 3.8 - Now annotated assignments allow same expressions in the right hand side as - the regular assignments. Previously, some expressions (like un-parenthesized + Now annotated assignments allow the same expressions in the right hand side as + regular assignments. Previously, some expressions (like un-parenthesized tuple expressions) caused a syntax error. @@ -750,7 +750,7 @@ as though the clauses had been separated out into individual import statements. -The details of the first step, finding and loading modules are described in +The details of the first step, finding and loading modules, are described in greater detail in the section on the :ref:`import system `, which also describes the various types of packages and modules that can be imported, as well as all the hooks that can be used to customize @@ -988,20 +988,12 @@ .. productionlist:: python-grammar nonlocal_stmt: "nonlocal" `identifier` ("," `identifier`)* -.. XXX add when implemented - : ["=" (`target_list` "=")+ starred_expression] - : | "nonlocal" identifier augop expression_list - The :keyword:`nonlocal` statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope. -.. XXX not implemented - The :keyword:`nonlocal` statement may prepend an assignment or augmented - assignment, but not an expression. - Names listed in a :keyword:`nonlocal` statement, unlike those listed in a :keyword:`global` statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot diff -Nru python3.10-3.10.7/Doc/tools/extensions/c_annotations.py python3.10-3.10.12/Doc/tools/extensions/c_annotations.py --- python3.10-3.10.7/Doc/tools/extensions/c_annotations.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tools/extensions/c_annotations.py 2023-06-06 22:30:33.000000000 +0000 @@ -24,6 +24,7 @@ from docutils.parsers.rst import directives from docutils.parsers.rst import Directive from docutils.statemachine import StringList +from sphinx.locale import _ as sphinx_gettext import csv from sphinx import addnodes @@ -152,11 +153,11 @@ elif not entry.result_type.endswith("Object*"): continue if entry.result_refs is None: - rc = 'Return value: Always NULL.' + rc = sphinx_gettext('Return value: Always NULL.') elif entry.result_refs: - rc = 'Return value: New reference.' + rc = sphinx_gettext('Return value: New reference.') else: - rc = 'Return value: Borrowed reference.' + rc = sphinx_gettext('Return value: Borrowed reference.') node.insert(0, nodes.emphasis(rc, rc, classes=['refcount'])) diff -Nru python3.10-3.10.7/Doc/tools/extensions/pyspecific.py python3.10-3.10.12/Doc/tools/extensions/pyspecific.py --- python3.10-3.10.7/Doc/tools/extensions/pyspecific.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tools/extensions/pyspecific.py 2023-06-06 22:30:33.000000000 +0000 @@ -26,7 +26,7 @@ from sphinx.errors import NoUri except ImportError: from sphinx.environment import NoUri -from sphinx.locale import translators +from sphinx.locale import _ as sphinx_gettext from sphinx.util import status_iterator, logging from sphinx.util.nodes import split_explicit_title from sphinx.writers.text import TextWriter, TextTranslator @@ -101,33 +101,24 @@ class ImplementationDetail(Directive): has_content = True - required_arguments = 0 - optional_arguments = 1 final_argument_whitespace = True # This text is copied to templates/dummy.html label_text = 'CPython implementation detail:' def run(self): + self.assert_has_content() pnode = nodes.compound(classes=['impl-detail']) - label = translators['sphinx'].gettext(self.label_text) + label = sphinx_gettext(self.label_text) content = self.content add_text = nodes.strong(label, label) - if self.arguments: - n, m = self.state.inline_text(self.arguments[0], self.lineno) - pnode.append(nodes.paragraph('', '', *(n + m))) self.state.nested_parse(content, self.content_offset, pnode) - if pnode.children and isinstance(pnode[0], nodes.paragraph): - content = nodes.inline(pnode[0].rawsource, translatable=True) - content.source = pnode[0].source - content.line = pnode[0].line - content += pnode[0].children - pnode[0].replace_self(nodes.paragraph('', '', content, - translatable=False)) - pnode[0].insert(0, add_text) - pnode[0].insert(1, nodes.Text(' ')) - else: - pnode.insert(0, nodes.paragraph('', '', add_text)) + content = nodes.inline(pnode[0].rawsource, translatable=True) + content.source = pnode[0].source + content.line = pnode[0].line + content += pnode[0].children + pnode[0].replace_self(nodes.paragraph( + '', '', add_text, nodes.Text(' '), content, translatable=False)) return [pnode] @@ -212,7 +203,7 @@ else: args = [] - label = translators['sphinx'].gettext(self._label[min(2, len(args))]) + label = sphinx_gettext(self._label[min(2, len(args))]) text = label.format(name="``{}``".format(name), args=", ".join("``{}``".format(a) for a in args if a)) @@ -391,7 +382,7 @@ else: label = self._removed_label - label = translators['sphinx'].gettext(label) + label = sphinx_gettext(label) text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], diff -Nru python3.10-3.10.7/Doc/tools/susp-ignored.csv python3.10-3.10.12/Doc/tools/susp-ignored.csv --- python3.10-3.10.7/Doc/tools/susp-ignored.csv 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tools/susp-ignored.csv 2023-06-06 22:30:33.000000000 +0000 @@ -12,7 +12,7 @@ extending/extending,,:set,"if (PyArg_ParseTuple(args, ""O:set_callback"", &temp)) {" extending/newtypes,,:call,"if (!PyArg_ParseTuple(args, ""sss:call"", &arg1, &arg2, &arg3)) {" faq/programming,,:chr,">=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(" -faq/programming,,:reduce,"print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y," +faq/programming,,:reduce,"print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+'\n'+y,map(lambda y," faq/programming,,:reduce,"Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro," faq/windows,,:d48eceb,"Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32" howto/curses,,:black,"colors when it activates color mode. They are: 0:black, 1:red," diff -Nru python3.10-3.10.7/Doc/tools/templates/dummy.html python3.10-3.10.12/Doc/tools/templates/dummy.html --- python3.10-3.10.7/Doc/tools/templates/dummy.html 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tools/templates/dummy.html 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,11 @@ {% trans %}Deprecated since version {deprecated}, will be removed in version {removed}{% endtrans %} {% trans %}Deprecated since version {deprecated}, removed in version {removed}{% endtrans %} +In extensions/c_annotations.py: + +{% trans %}Return value: Always NULL.{% endtrans %} +{% trans %}Return value: New reference.{% endtrans %} +{% trans %}Return value: Borrowed reference.{% endtrans %} In docsbuild-scripts, when rewriting indexsidebar.html with actual versions: diff -Nru python3.10-3.10.7/Doc/tutorial/classes.rst python3.10-3.10.12/Doc/tutorial/classes.rst --- python3.10-3.10.7/Doc/tutorial/classes.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/classes.rst 2023-06-06 22:30:33.000000000 +0000 @@ -119,12 +119,12 @@ * the innermost scope, which is searched first, contains the local names * the scopes of any enclosing functions, which are searched starting with the - nearest enclosing scope, contains non-local, but also non-global names + nearest enclosing scope, contain non-local, but also non-global names * the next-to-last scope contains the current module's global names * the outermost scope (searched last) is the namespace containing built-in names If a name is declared global, then all references and assignments go directly to -the middle scope containing the module's global names. To rebind variables +the next-to-last scope containing the module's global names. To rebind variables found outside of the innermost scope, the :keyword:`nonlocal` statement can be used; if not declared nonlocal, those variables are read-only (an attempt to write to such a variable will simply create a *new* local variable in the @@ -737,18 +737,24 @@ ============= Sometimes it is useful to have a data type similar to the Pascal "record" or C -"struct", bundling together a few named data items. An empty class definition -will do nicely:: +"struct", bundling together a few named data items. The idiomatic approach +is to use :mod:`dataclasses` for this purpose:: - class Employee: - pass + from dataclasses import dataclass - john = Employee() # Create an empty employee record - - # Fill the fields of the record - john.name = 'John Doe' - john.dept = 'computer lab' - john.salary = 1000 + @dataclass + class Employee: + name: str + dept: str + salary: int + +:: + + >>> john = Employee('john', 'computer lab', 1000) + >>> john.dept + 'computer lab' + >>> john.salary + 1000 A piece of Python code that expects a particular abstract data type can often be passed a class that emulates the methods of that data type instead. For diff -Nru python3.10-3.10.7/Doc/tutorial/datastructures.rst python3.10-3.10.12/Doc/tutorial/datastructures.rst --- python3.10-3.10.7/Doc/tutorial/datastructures.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/datastructures.rst 2023-06-06 22:30:33.000000000 +0000 @@ -122,7 +122,7 @@ You might have noticed that methods like ``insert``, ``remove`` or ``sort`` that only modify the list have no return value printed -- they return the default -``None``. [1]_ This is a design principle for all mutable data structures in +``None``. [#]_ This is a design principle for all mutable data structures in Python. Another thing you might notice is that not all data can be sorted or @@ -731,5 +731,5 @@ .. rubric:: Footnotes -.. [1] Other languages may return the mutated object, which allows method +.. [#] Other languages may return the mutated object, which allows method chaining, such as ``d->insert("a")->remove("b")->sort();``. diff -Nru python3.10-3.10.7/Doc/tutorial/errors.rst python3.10-3.10.12/Doc/tutorial/errors.rst --- python3.10-3.10.7/Doc/tutorial/errors.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/errors.rst 2023-06-06 22:30:33.000000000 +0000 @@ -275,8 +275,27 @@ Exception Chaining ================== -The :keyword:`raise` statement allows an optional :keyword:`from` which enables -chaining exceptions. For example:: +If an unhandled exception occurs inside an :keyword:`except` section, it will +have the exception being handled attached to it and included in the error +message:: + + >>> try: + ... open("database.sqlite") + ... except OSError: + ... raise RuntimeError("unable to handle error") + ... + Traceback (most recent call last): + File "", line 2, in + FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite' + + During handling of the above exception, another exception occurred: + + Traceback (most recent call last): + File "", line 4, in + RuntimeError: unable to handle error + +To indicate that an exception is a direct consequence of another, the +:keyword:`raise` statement allows an optional :keyword:`from` clause:: # exc must be exception instance or None. raise RuntimeError from exc @@ -302,9 +321,8 @@ File "", line 4, in RuntimeError: Failed to open database -Exception chaining happens automatically when an exception is raised inside an -:keyword:`except` or :keyword:`finally` section. This can be -disabled by using ``from None`` idiom: +It also allows disabling automatic exception chaining using the ``from None`` +idiom:: >>> try: ... open('database.sqlite') diff -Nru python3.10-3.10.7/Doc/tutorial/inputoutput.rst python3.10-3.10.12/Doc/tutorial/inputoutput.rst --- python3.10-3.10.7/Doc/tutorial/inputoutput.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/inputoutput.rst 2023-06-06 22:30:33.000000000 +0000 @@ -133,7 +133,17 @@ >>> print(f'My hovercraft is full of {animals!r}.') My hovercraft is full of 'eels'. -For a reference on these format specifications, see +The ``=`` specifier can be used to expand an expression to the text of the +expression, an equal sign, then the representation of the evaluated expression: + + >>> bugs = 'roaches' + >>> count = 13 + >>> area = 'living room' + >>> print(f'Debugging {bugs=} {count=} {area=}') + Debugging bugs='roaches' count=13 area='living room' + +See :ref:`self-documenting expressions ` for more information +on the ``=`` specifier. For a reference on these format specifications, see the reference guide for the :ref:`formatspec`. .. _tut-string-format: @@ -468,7 +478,7 @@ Rather than having users constantly writing and debugging code to save complicated data types to files, Python allows you to use the popular data interchange format called `JSON (JavaScript Object Notation) -`_. The standard module called :mod:`json` can take Python +`_. The standard module called :mod:`json` can take Python data hierarchies, and convert them to string representations; this process is called :dfn:`serializing`. Reconstructing the data from the string representation is called :dfn:`deserializing`. Between serializing and deserializing, the diff -Nru python3.10-3.10.7/Doc/tutorial/interpreter.rst python3.10-3.10.12/Doc/tutorial/interpreter.rst --- python3.10-3.10.7/Doc/tutorial/interpreter.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/interpreter.rst 2023-06-06 22:30:33.000000000 +0000 @@ -52,7 +52,7 @@ which executes the statement(s) in *command*, analogous to the shell's :option:`-c` option. Since Python statements often contain spaces or other characters that are special to the shell, it is usually advised to quote -*command* in its entirety with single quotes. +*command* in its entirety. Some Python modules are also useful as scripts. These can be invoked using ``python -m module [arg] ...``, which executes the source file for *module* as diff -Nru python3.10-3.10.7/Doc/tutorial/introduction.rst python3.10-3.10.12/Doc/tutorial/introduction.rst --- python3.10-3.10.7/Doc/tutorial/introduction.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/introduction.rst 2023-06-06 22:30:33.000000000 +0000 @@ -70,8 +70,8 @@ :class:`float`. We will see more about numeric types later in the tutorial. Division (``/``) always returns a float. To do :term:`floor division` and -get an integer result (discarding any fractional result) you can use the ``//`` -operator; to calculate the remainder you can use ``%``:: +get an integer result you can use the ``//`` operator; to calculate +the remainder you can use ``%``:: >>> 17 / 3 # classic division returns a float 5.666666666666667 @@ -189,6 +189,11 @@ >>> print(r'C:\some\name') # note the r before the quote C:\some\name +There is one subtle aspect to raw strings: a raw string may not end in +an odd number of ``\`` characters; see +:ref:`the FAQ entry ` for more information +and workarounds. + String literals can span multiple lines. One way is using triple-quotes: ``"""..."""`` or ``'''...'''``. End of lines are automatically included in the string, but it's possible to prevent this by adding a ``\`` at @@ -234,12 +239,12 @@ >>> prefix 'thon' # can't concatenate a variable and a string literal File "", line 1 prefix 'thon' - ^ + ^^^^^^ SyntaxError: invalid syntax >>> ('un' * 3) 'ium' File "", line 1 ('un' * 3) 'ium' - ^ + ^^^^^ SyntaxError: invalid syntax If you want to concatenate variables or a variable and a literal, use ``+``:: diff -Nru python3.10-3.10.7/Doc/tutorial/modules.rst python3.10-3.10.12/Doc/tutorial/modules.rst --- python3.10-3.10.7/Doc/tutorial/modules.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/modules.rst 2023-06-06 22:30:33.000000000 +0000 @@ -434,7 +434,7 @@ The :file:`__init__.py` files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, -such as ``string``, unintentionally hiding valid modules that occur later +such as ``string``, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, :file:`__init__.py` can just be an empty file, but it can also execute initialization code for the package or set the ``__all__`` variable, described later. diff -Nru python3.10-3.10.7/Doc/tutorial/venv.rst python3.10-3.10.12/Doc/tutorial/venv.rst --- python3.10-3.10.7/Doc/tutorial/venv.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/tutorial/venv.rst 2023-06-06 22:30:33.000000000 +0000 @@ -44,7 +44,7 @@ To create a virtual environment, decide upon a directory where you want to place it, and run the :mod:`venv` module as a script with the directory path:: - python3 -m venv tutorial-env + python -m venv tutorial-env This will create the ``tutorial-env`` directory if it doesn't exist, and also create directories inside it containing a copy of the Python @@ -93,8 +93,8 @@ ========================== You can install, upgrade, and remove packages using a program called -:program:`pip`. By default ``pip`` will install packages from the Python -Package Index, . You can browse the Python +:program:`pip`. By default ``pip`` will install packages from the `Python +Package Index `_. You can browse the Python Package Index by going to it in your web browser. ``pip`` has a number of subcommands: "install", "uninstall", diff -Nru python3.10-3.10.7/Doc/using/configure.rst python3.10-3.10.12/Doc/using/configure.rst --- python3.10-3.10.7/Doc/using/configure.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/using/configure.rst 2023-06-06 22:30:33.000000000 +0000 @@ -120,6 +120,22 @@ Install Options --------------- +.. cmdoption:: --prefix=PREFIX + + Install architecture-independent files in PREFIX. On Unix, it + defaults to :file:`/usr/local`. + + This value can be retrived at runtime using :data:`sys.prefix`. + + As an example, one can use ``--prefix="$HOME/.local/"`` to install + a Python in its home directory. + +.. cmdoption:: --exec-prefix=EPREFIX + + Install architecture-dependent files in EPREFIX, defaults to :option:`--prefix`. + + This value can be retrived at runtime using :data:`sys.exec_prefix`. + .. cmdoption:: --disable-test-modules Don't build nor install test modules, like the :mod:`test` package or the @@ -654,12 +670,12 @@ In particular, :envvar:`CFLAGS` should not contain: - * the compiler flag `-I` (for setting the search path for include files). - The `-I` flags are processed from left to right, and any flags in - :envvar:`CFLAGS` would take precedence over user- and package-supplied `-I` + * the compiler flag ``-I`` (for setting the search path for include files). + The ``-I`` flags are processed from left to right, and any flags in + :envvar:`CFLAGS` would take precedence over user- and package-supplied ``-I`` flags. - * hardening flags such as `-Werror` because distributions cannot control + * hardening flags such as ``-Werror`` because distributions cannot control whether packages installed by users conform to such heightened standards. @@ -777,9 +793,9 @@ In particular, :envvar:`LDFLAGS` should not contain: - * the compiler flag `-L` (for setting the search path for libraries). - The `-L` flags are processed from left to right, and any flags in - :envvar:`LDFLAGS` would take precedence over user- and package-supplied `-L` + * the compiler flag ``-L`` (for setting the search path for libraries). + The ``-L`` flags are processed from left to right, and any flags in + :envvar:`LDFLAGS` would take precedence over user- and package-supplied ``-L`` flags. .. envvar:: CONFIGURE_LDFLAGS_NODIST diff -Nru python3.10-3.10.7/Doc/using/unix.rst python3.10-3.10.12/Doc/using/unix.rst --- python3.10-3.10.7/Doc/using/unix.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/using/unix.rst 2023-06-06 22:30:33.000000000 +0000 @@ -93,7 +93,7 @@ ============================== These are subject to difference depending on local installation conventions; -:envvar:`prefix` (``${prefix}``) and :envvar:`exec_prefix` (``${exec_prefix}``) +:option:`prefix <--prefix>` and :option:`exec_prefix <--exec-prefix>` are installation-dependent and should be interpreted as for GNU software; they may be the same. @@ -158,19 +158,19 @@ .. code-block:: shell-session $ curl -O https://www.openssl.org/source/openssl-VERSION.tar.gz - $ tar xzf openssl-VERSION - $ pushd openssl-VERSION - $ ./config \ - --prefix=/usr/local/custom-openssl \ - --libdir=lib \ - --openssldir=/etc/ssl - $ make -j1 depend - $ make -j8 - $ make install_sw - $ popd + $ tar xzf openssl-VERSION + $ pushd openssl-VERSION + $ ./config \ + --prefix=/usr/local/custom-openssl \ + --libdir=lib \ + --openssldir=/etc/ssl + $ make -j1 depend + $ make -j8 + $ make install_sw + $ popd 3. Build Python with custom OpenSSL - (see the configure `--with-openssl` and `--with-openssl-rpath` options) + (see the configure ``--with-openssl`` and ``--with-openssl-rpath`` options) .. code-block:: shell-session diff -Nru python3.10-3.10.7/Doc/using/venv-create.inc python3.10-3.10.12/Doc/using/venv-create.inc --- python3.10-3.10.7/Doc/using/venv-create.inc 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/using/venv-create.inc 2023-06-06 22:30:33.000000000 +0000 @@ -1,7 +1,7 @@ Creation of :ref:`virtual environments ` is done by executing the command ``venv``:: - python3 -m venv /path/to/new/virtual/environment + python -m venv /path/to/new/virtual/environment Running this command creates the target directory (creating any parent directories that don't exist already) and places a ``pyvenv.cfg`` file in it @@ -16,8 +16,8 @@ .. deprecated:: 3.6 ``pyvenv`` was the recommended tool for creating virtual environments for - Python 3.3 and 3.4, and is `deprecated in Python 3.6 - `_. + Python 3.3 and 3.4, and is + :ref:`deprecated in Python 3.6 `. .. versionchanged:: 3.5 The use of ``venv`` is now recommended for creating virtual environments. @@ -105,45 +105,3 @@ environment will be created, according to the given options, at each provided path. -Once a virtual environment has been created, it can be "activated" using a -script in the virtual environment's binary directory. The invocation of the -script is platform-specific (`` must be replaced by the path of the -directory containing the virtual environment): - -+-------------+-----------------+-----------------------------------------+ -| Platform | Shell | Command to activate virtual environment | -+=============+=================+=========================================+ -| POSIX | bash/zsh | $ source /bin/activate | -+-------------+-----------------+-----------------------------------------+ -| | fish | $ source /bin/activate.fish | -+-------------+-----------------+-----------------------------------------+ -| | csh/tcsh | $ source /bin/activate.csh | -+-------------+-----------------+-----------------------------------------+ -| | PowerShell Core | $ /bin/Activate.ps1 | -+-------------+-----------------+-----------------------------------------+ -| Windows | cmd.exe | C:\\> \\Scripts\\activate.bat | -+-------------+-----------------+-----------------------------------------+ -| | PowerShell | PS C:\\> \\Scripts\\Activate.ps1 | -+-------------+-----------------+-----------------------------------------+ - -When a virtual environment is active, the :envvar:`VIRTUAL_ENV` environment -variable is set to the path of the virtual environment. This can be used to -check if one is running inside a virtual environment. - -You don't specifically *need* to activate an environment; activation just -prepends the virtual environment's binary directory to your path, so that -"python" invokes the virtual environment's Python interpreter and you can run -installed scripts without having to use their full path. However, all scripts -installed in a virtual environment should be runnable without activating it, -and run with the virtual environment's Python automatically. - -You can deactivate a virtual environment by typing "deactivate" in your shell. -The exact mechanism is platform-specific and is an internal implementation -detail (typically a script or shell function will be used). - -.. versionadded:: 3.4 - ``fish`` and ``csh`` activation scripts. - -.. versionadded:: 3.8 - PowerShell activation scripts installed under POSIX for PowerShell Core - support. diff -Nru python3.10-3.10.7/Doc/using/windows.rst python3.10-3.10.12/Doc/using/windows.rst --- python3.10-3.10.7/Doc/using/windows.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/using/windows.rst 2023-06-06 22:30:33.000000000 +0000 @@ -150,11 +150,14 @@ | | | Python X.Y` | +---------------------------+--------------------------------------+--------------------------+ | DefaultJustForMeTargetDir | The default install directory for | :file:`%LocalAppData%\\\ | -| | just-for-me installs | Programs\\PythonXY` or | +| | just-for-me installs | Programs\\Python\\\ | +| | | PythonXY` or | | | | :file:`%LocalAppData%\\\ | -| | | Programs\\PythonXY-32` or| +| | | Programs\\Python\\\ | +| | | PythonXY-32` or | | | | :file:`%LocalAppData%\\\ | -| | | Programs\\PythonXY-64` | +| | | Programs\\Python\\\ | +| | | PythonXY-64` | +---------------------------+--------------------------------------+--------------------------+ | DefaultCustomTargetDir | The default custom install directory | (empty) | | | displayed in the UI | | @@ -196,7 +199,7 @@ +---------------------------+--------------------------------------+--------------------------+ | Include_pip | Install bundled pip and setuptools | 1 | +---------------------------+--------------------------------------+--------------------------+ -| Include_symbols | Install debugging symbols (`*`.pdb) | 0 | +| Include_symbols | Install debugging symbols (``*.pdb``)| 0 | +---------------------------+--------------------------------------+--------------------------+ | Include_tcltk | Install Tcl/Tk support and IDLE | 1 | +---------------------------+--------------------------------------+--------------------------+ @@ -777,7 +780,7 @@ Re-executing the command should now print the latest Python 3.x information. As with the above command-line examples, you can specify a more explicit version qualifier. Assuming you have Python 3.7 installed, try changing -the first line to ``#! python3.7`` and you should find the |version| +the first line to ``#! python3.7`` and you should find the 3.7 version information printed. Note that unlike interactive use, a bare "python" will use the latest @@ -1165,7 +1168,7 @@ earlier are no longer supported (due to the lack of users or developers). Check :pep:`11` for details on all unsupported platforms. -* `Windows CE `_ is +* `Windows CE `_ is `no longer supported `__ since Python 3 (if it ever was). * The `Cygwin `_ installer offers to install the diff -Nru python3.10-3.10.7/Doc/whatsnew/2.0.rst python3.10-3.10.12/Doc/whatsnew/2.0.rst --- python3.10-3.10.7/Doc/whatsnew/2.0.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.0.rst 2023-06-06 22:30:33.000000000 +0000 @@ -572,7 +572,7 @@ mostly by Trent Mick of ActiveState. (Confusingly, ``sys.platform`` is still ``'win32'`` on Win64 because it seems that for ease of porting, MS Visual C++ treats code as 32 bit on Itanium.) PythonWin also supports Windows CE; see the -Python CE page at http://pythonce.sourceforge.net/ for more information. +Python CE page at https://pythonce.sourceforge.net/ for more information. Another new platform is Darwin/MacOS X; initial support for it is in Python 2.0. Dynamic loading works, if you specify "configure --with-dyld --with-suffix=.x". diff -Nru python3.10-3.10.7/Doc/whatsnew/2.2.rst python3.10-3.10.12/Doc/whatsnew/2.2.rst --- python3.10-3.10.7/Doc/whatsnew/2.2.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.2.rst 2023-06-06 22:30:33.000000000 +0000 @@ -395,7 +395,7 @@ of an explanation to start you programming, but many details have been simplified or ignored. Where should you go to get a more complete picture? -https://docs.python.org/dev/howto/descriptor.html is a lengthy tutorial introduction to +The :ref:`descriptorhowto` is a lengthy tutorial introduction to the descriptor features, written by Guido van Rossum. If my description has whetted your appetite, go read this tutorial next, because it goes into much more detail about the new features while still remaining quite easy to read. @@ -983,7 +983,7 @@ Jun-ichiro "itojun" Hagino.) * Two new format characters were added to the :mod:`struct` module for 64-bit - integers on platforms that support the C :c:type:`long long` type. ``q`` is for + integers on platforms that support the C :c:expr:`long long` type. ``q`` is for a signed 64-bit integer, and ``Q`` is for an unsigned one. The value is returned in Python's long integer type. (Contributed by Tim Peters.) @@ -1102,7 +1102,7 @@ * A different argument parsing function, :c:func:`PyArg_UnpackTuple`, has been added that's simpler and presumably faster. Instead of specifying a format string, the caller simply gives the minimum and maximum number of arguments - expected, and a set of pointers to :c:type:`PyObject\*` variables that will be + expected, and a set of pointers to :c:expr:`PyObject*` variables that will be filled in with argument values. * Two new flags :const:`METH_NOARGS` and :const:`METH_O` are available in method diff -Nru python3.10-3.10.7/Doc/whatsnew/2.3.rst python3.10-3.10.12/Doc/whatsnew/2.3.rst --- python3.10-3.10.7/Doc/whatsnew/2.3.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.3.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1231,7 +1231,7 @@ repeat an array. (Contributed by Jason Orendorff.) * The :mod:`bsddb` module has been replaced by version 4.1.6 of the `PyBSDDB - `_ package, providing a more complete interface + `_ package, providing a more complete interface to the transactional features of the BerkeleyDB library. The old version of the module has been renamed to :mod:`bsddb185` and is no @@ -1905,8 +1905,8 @@ "")`` instead, but this will be slower than using :const:`METH_NOARGS`. * :c:func:`PyArg_ParseTuple` accepts new format characters for various sizes of - unsigned integers: ``B`` for :c:type:`unsigned char`, ``H`` for :c:type:`unsigned - short int`, ``I`` for :c:type:`unsigned int`, and ``K`` for :c:type:`unsigned + unsigned integers: ``B`` for :c:expr:`unsigned char`, ``H`` for :c:expr:`unsigned + short int`, ``I`` for :c:expr:`unsigned int`, and ``K`` for :c:expr:`unsigned long long`. * A new function, ``PyObject_DelItemString(mapping, char *key)`` was added diff -Nru python3.10-3.10.7/Doc/whatsnew/2.4.rst python3.10-3.10.12/Doc/whatsnew/2.4.rst --- python3.10-3.10.7/Doc/whatsnew/2.4.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.4.rst 2023-06-06 22:30:33.000000000 +0000 @@ -472,7 +472,7 @@ ========================== Python has always supported floating-point (FP) numbers, based on the underlying -C :c:type:`double` type, as a data type. However, while most programming +C :c:expr:`double` type, as a data type. However, while most programming languages provide a floating-point type, many people (even programmers) are unaware that floating-point numbers don't represent certain decimal fractions accurately. The new :class:`Decimal` type can represent these fractions @@ -501,7 +501,7 @@ 5. Modern systems usually provide floating-point support that conforms to a -standard called IEEE 754. C's :c:type:`double` type is usually implemented as a +standard called IEEE 754. C's :c:expr:`double` type is usually implemented as a 64-bit IEEE 754 number, which uses 52 bits of space for the mantissa. This means that numbers can only be specified to 52 bits of precision. If you're trying to represent numbers whose expansion repeats endlessly, the expansion is @@ -750,10 +750,10 @@ API that perform ASCII-only conversions, ignoring the locale setting: * ``PyOS_ascii_strtod(str, ptr)`` and ``PyOS_ascii_atof(str, ptr)`` - both convert a string to a C :c:type:`double`. + both convert a string to a C :c:expr:`double`. * ``PyOS_ascii_formatd(buffer, buf_len, format, d)`` converts a - :c:type:`double` to an ASCII string. + :c:expr:`double` to an ASCII string. The code for these functions came from the GLib library (https://developer.gnome.org/glib/stable/), whose developers kindly @@ -1453,7 +1453,7 @@ extension functions: :c:macro:`Py_RETURN_NONE`, :c:macro:`Py_RETURN_TRUE`, and :c:macro:`Py_RETURN_FALSE`. (Contributed by Brett Cannon.) -* Another new macro, :c:macro:`Py_CLEAR(obj)`, decreases the reference count of +* Another new macro, :c:macro:`Py_CLEAR`, decreases the reference count of *obj* and sets *obj* to the null pointer. (Contributed by Jim Fulton.) * A new function, ``PyTuple_Pack(N, obj1, obj2, ..., objN)``, constructs @@ -1464,7 +1464,7 @@ lookups without masking exceptions raised during the look-up process. (Contributed by Raymond Hettinger.) -* The :c:macro:`Py_IS_NAN(X)` macro returns 1 if its float or double argument +* The :c:expr:`Py_IS_NAN(X)` macro returns 1 if its float or double argument *X* is a NaN. (Contributed by Tim Peters.) * C code can avoid unnecessary locking by using the new diff -Nru python3.10-3.10.7/Doc/whatsnew/2.5.rst python3.10-3.10.12/Doc/whatsnew/2.5.rst --- python3.10-3.10.7/Doc/whatsnew/2.5.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.5.rst 2023-06-06 22:30:33.000000000 +0000 @@ -872,18 +872,18 @@ ======================================== A wide-ranging change to Python's C API, using a new :c:type:`Py_ssize_t` type -definition instead of :c:type:`int`, will permit the interpreter to handle more +definition instead of :c:expr:`int`, will permit the interpreter to handle more data on 64-bit platforms. This change doesn't affect Python's capacity on 32-bit platforms. -Various pieces of the Python interpreter used C's :c:type:`int` type to store +Various pieces of the Python interpreter used C's :c:expr:`int` type to store sizes or counts; for example, the number of items in a list or tuple were stored -in an :c:type:`int`. The C compilers for most 64-bit platforms still define -:c:type:`int` as a 32-bit type, so that meant that lists could only hold up to +in an :c:expr:`int`. The C compilers for most 64-bit platforms still define +:c:expr:`int` as a 32-bit type, so that meant that lists could only hold up to ``2**31 - 1`` = 2147483647 items. (There are actually a few different programming models that 64-bit C compilers can use -- see https://unix.org/version2/whatsnew/lp64_wp.html for a discussion -- but the -most commonly available model leaves :c:type:`int` as 32 bits.) +most commonly available model leaves :c:expr:`int` as 32 bits.) A limit of 2147483647 items doesn't really matter on a 32-bit platform because you'll run out of memory before hitting the length limit. Each list item @@ -895,7 +895,7 @@ pointers for a list that size would only require 16 GiB of space, so it's not unreasonable that Python programmers might construct lists that large. Therefore, the Python interpreter had to be changed to use some type other than -:c:type:`int`, and this will be a 64-bit type on 64-bit platforms. The change +:c:expr:`int`, and this will be a 64-bit type on 64-bit platforms. The change will cause incompatibilities on 64-bit machines, so it was deemed worth making the transition now, while the number of 64-bit users is still relatively small. (In 5 or 10 years, we may *all* be on 64-bit machines, and the transition would @@ -909,7 +909,7 @@ The :c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue` functions have a new conversion code, ``n``, for :c:type:`Py_ssize_t`. :c:func:`PyArg_ParseTuple`'s -``s#`` and ``t#`` still output :c:type:`int` by default, but you can define the +``s#`` and ``t#`` still output :c:expr:`int` by default, but you can define the macro :c:macro:`PY_SSIZE_T_CLEAN` before including :file:`Python.h` to make them return :c:type:`Py_ssize_t`. @@ -1695,7 +1695,7 @@ result = libc.printf("Line of output\n") Type constructors for the various C types are provided: :func:`c_int`, -:func:`c_float`, :func:`c_double`, :func:`c_char_p` (equivalent to :c:type:`char +:func:`c_float`, :func:`c_double`, :func:`c_char_p` (equivalent to :c:expr:`char \*`), and so forth. Unlike Python's types, the C versions are all mutable; you can assign to their :attr:`value` attribute to change the wrapped value. Python integers and strings will be automatically converted to the corresponding C @@ -1725,7 +1725,7 @@ ``ctypes.pythonapi`` object. This object does *not* release the global interpreter lock before calling a function, because the lock must be held when calling into the interpreter's code. There's a :class:`py_object()` type -constructor that will create a :c:type:`PyObject \*` pointer. A simple usage:: +constructor that will create a :c:expr:`PyObject *` pointer. A simple usage:: import ctypes @@ -2093,7 +2093,7 @@ * The largest change to the C API came from :pep:`353`, which modifies the interpreter to use a :c:type:`Py_ssize_t` type definition instead of - :c:type:`int`. See the earlier section :ref:`pep-353` for a discussion of this + :c:expr:`int`. See the earlier section :ref:`pep-353` for a discussion of this change. * The design of the bytecode compiler has changed a great deal, no longer @@ -2264,15 +2264,15 @@ Setting :attr:`rpc_paths` to ``None`` or an empty tuple disables this path checking. -* C API: Many functions now use :c:type:`Py_ssize_t` instead of :c:type:`int` to +* C API: Many functions now use :c:type:`Py_ssize_t` instead of :c:expr:`int` to allow processing more data on 64-bit machines. Extension code may need to make the same change to avoid warnings and to support 64-bit machines. See the earlier section :ref:`pep-353` for a discussion of this change. * C API: The obmalloc changes mean that you must be careful to not mix usage - of the :c:func:`PyMem_\*` and :c:func:`PyObject_\*` families of functions. Memory - allocated with one family's :c:func:`\*_Malloc` must be freed with the - corresponding family's :c:func:`\*_Free` function. + of the ``PyMem_*`` and ``PyObject_*`` families of functions. Memory + allocated with one family's ``*_Malloc`` must be freed with the + corresponding family's ``*_Free`` function. .. ====================================================================== diff -Nru python3.10-3.10.7/Doc/whatsnew/2.6.rst python3.10-3.10.12/Doc/whatsnew/2.6.rst --- python3.10-3.10.7/Doc/whatsnew/2.6.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.6.rst 2023-06-06 22:30:33.000000000 +0000 @@ -217,7 +217,7 @@ During the 2.6 development cycle, Georg Brandl put a lot of effort into building a new toolchain for processing the documentation. The resulting package is called Sphinx, and is available from -http://sphinx-doc.org/. +https://www.sphinx-doc.org/. Sphinx concentrates on HTML output, producing attractively styled and modern HTML; printed output is still supported through conversion to @@ -235,7 +235,7 @@ `Documenting Python `__ Describes how to write for Python's documentation. - `Sphinx `__ + `Sphinx `__ Documentation and code for the Sphinx toolchain. `Docutils `__ @@ -717,13 +717,13 @@ PEP 3101: Advanced String Formatting ===================================================== -In Python 3.0, the `%` operator is supplemented by a more powerful string +In Python 3.0, the ``%`` operator is supplemented by a more powerful string formatting method, :meth:`format`. Support for the :meth:`str.format` method has been backported to Python 2.6. -In 2.6, both 8-bit and Unicode strings have a `.format()` method that +In 2.6, both 8-bit and Unicode strings have a ``.format()`` method that treats the string as a template and takes the arguments to be formatted. -The formatting template uses curly brackets (`{`, `}`) as special characters:: +The formatting template uses curly brackets (``{``, ``}``) as special characters:: >>> # Substitute positional argument 0 into the string. >>> "User ID: {0}".format("root") @@ -1926,7 +1926,7 @@ the left to six places. (Contributed by Skip Montanaro; :issue:`1158`.) * The :mod:`decimal` module was updated to version 1.66 of - `the General Decimal Specification `__. New features + `the General Decimal Specification `__. New features include some methods for some basic mathematical functions such as :meth:`exp` and :meth:`log10`:: @@ -2389,7 +2389,7 @@ has been updated from version 2.3.2 in Python 2.5 to version 2.4.1. -* The :mod:`struct` module now supports the C99 :c:type:`_Bool` type, +* The :mod:`struct` module now supports the C99 :c:expr:`_Bool` type, using the format character ``'?'``. (Contributed by David Remahl.) diff -Nru python3.10-3.10.7/Doc/whatsnew/2.7.rst python3.10-3.10.12/Doc/whatsnew/2.7.rst --- python3.10-3.10.7/Doc/whatsnew/2.7.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/2.7.rst 2023-06-06 22:30:33.000000000 +0000 @@ -2144,7 +2144,7 @@ * New functions: :c:func:`PyLong_AsLongAndOverflow` and :c:func:`PyLong_AsLongLongAndOverflow` approximates a Python long - integer as a C :c:type:`long` or :c:type:`long long`. + integer as a C :c:expr:`long` or :c:expr:`long long`. If the number is too large to fit into the output type, an *overflow* flag is set and returned to the caller. (Contributed by Case Van Horsen; :issue:`7528` and :issue:`7767`.) @@ -2202,7 +2202,7 @@ * New format codes: the :c:func:`PyFormat_FromString`, :c:func:`PyFormat_FromStringV`, and :c:func:`PyErr_Format` functions now accept ``%lld`` and ``%llu`` format codes for displaying - C's :c:type:`long long` types. + C's :c:expr:`long long` types. (Contributed by Mark Dickinson; :issue:`7228`.) * The complicated interaction between threads and process forking has @@ -2485,8 +2485,8 @@ * The ElementTree library, :mod:`xml.etree`, no longer escapes ampersands and angle brackets when outputting an XML processing - instruction (which looks like ``) - or comment (which looks like ``). + instruction (which looks like ````) + or comment (which looks like ````). (Patch by Neil Muller; :issue:`2746`.) * The :meth:`~StringIO.StringIO.readline` method of :class:`~StringIO.StringIO` objects now does diff -Nru python3.10-3.10.7/Doc/whatsnew/3.10.rst python3.10-3.10.12/Doc/whatsnew/3.10.rst --- python3.10-3.10.7/Doc/whatsnew/3.10.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.10.rst 2023-06-06 22:30:33.000000000 +0000 @@ -77,8 +77,9 @@ New typing features: * :pep:`604`, Allow writing union types as X | Y -* :pep:`613`, Explicit Type Aliases * :pep:`612`, Parameter Specification Variables +* :pep:`613`, Explicit Type Aliases +* :pep:`647`, User-Defined Type Guards Important deprecations, removals or restrictions: @@ -1172,7 +1173,7 @@ New in 3.10 maintenance releases. -Apply syntax highlighting to `.pyi` files. (Contributed by Alex +Apply syntax highlighting to ``.pyi`` files. (Contributed by Alex Waygood and Terry Jan Reedy in :issue:`45447`.) Include prompts when saving Shell with inputs and outputs. @@ -1705,19 +1706,6 @@ scheduled for removal in Python 3.12. (Contributed by Erlend E. Aasland in :issue:`42264`.) -* :func:`asyncio.get_event_loop` now emits a deprecation warning if there is - no running event loop. In the future it will be an alias of - :func:`~asyncio.get_running_loop`. - :mod:`asyncio` functions which implicitly create :class:`~asyncio.Future` - or :class:`~asyncio.Task` objects now emit - a deprecation warning if there is no running event loop and no explicit - *loop* argument is passed: :func:`~asyncio.ensure_future`, - :func:`~asyncio.wrap_future`, :func:`~asyncio.gather`, - :func:`~asyncio.shield`, :func:`~asyncio.as_completed` and constructors of - :class:`~asyncio.Future`, :class:`~asyncio.Task`, - :class:`~asyncio.StreamReader`, :class:`~asyncio.StreamReaderProtocol`. - (Contributed by Serhiy Storchaka in :issue:`39529`.) - * The undocumented built-in function ``sqlite3.enable_shared_cache`` is now deprecated, scheduled for removal in Python 3.12. Its use is strongly discouraged by the SQLite3 documentation. See `the SQLite3 docs @@ -2147,8 +2135,7 @@ * The ``PY_SSIZE_T_CLEAN`` macro must now be defined to use :c:func:`PyArg_ParseTuple` and :c:func:`Py_BuildValue` formats which use ``#``: ``es#``, ``et#``, ``s#``, ``u#``, ``y#``, ``z#``, ``U#`` and ``Z#``. - See :ref:`Parsing arguments and building values - ` and the :pep:`353`. + See :ref:`arg-parsing` and :pep:`353`. (Contributed by Victor Stinner in :issue:`40943`.) * Since :c:func:`Py_REFCNT()` is changed to the inline static function, @@ -2179,8 +2166,7 @@ :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and :c:func:`Py_GetProgramName` functions now return ``NULL`` if called before :c:func:`Py_Initialize` (before Python is initialized). Use the new - :ref:`Python Initialization Configuration API ` to get the - :ref:`Python Path Configuration. `. + :ref:`init-config` API to get the :ref:`init-path-config`. (Contributed by Victor Stinner in :issue:`42260`.) * :c:func:`PyList_SET_ITEM`, :c:func:`PyTuple_SET_ITEM` and @@ -2194,7 +2180,7 @@ ``picklebufobject.h``, ``pyarena.h``, ``pyctype.h``, ``pydebug.h``, ``pyfpe.h``, and ``pytime.h`` have been moved to the ``Include/cpython`` directory. These files must not be included directly, as they are already - included in ``Python.h``: :ref:`Include Files `. If they have + included in ``Python.h``; see :ref:`api-includes`. If they have been included directly, consider including ``Python.h`` instead. (Contributed by Nicholas Sim in :issue:`35134`.) @@ -2338,3 +2324,27 @@ length limitation ` documentation. The default limit is 4300 digits in string form. +Notable security feature in 3.10.8 +================================== + +The deprecated :mod:`mailcap` module now refuses to inject unsafe text +(filenames, MIME types, parameters) into shell commands. Instead of using such +text, it will warn and act as if a match was not found (or for test commands, +as if the test failed). +(Contributed by Petr Viktorin in :gh:`98966`.) + +Notable Changes in 3.10.12 +========================== + +tarfile +------- + +* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, + have a new a *filter* argument that allows limiting tar features than may be + surprising or dangerous, such as creating files outside the destination + directory. + See :ref:`tarfile-extraction-filter` for details. + In Python 3.12, use without the *filter* argument will show a + :exc:`DeprecationWarning`. + In Python 3.14, the default will switch to ``'data'``. + (Contributed by Petr Viktorin in :pep:`706`.) diff -Nru python3.10-3.10.7/Doc/whatsnew/3.1.rst python3.10-3.10.12/Doc/whatsnew/3.1.rst --- python3.10-3.10.7/Doc/whatsnew/3.1.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.1.rst 2023-06-06 22:30:33.000000000 +0000 @@ -451,7 +451,7 @@ * The :mod:`json` module now has a C extension to substantially improve its performance. In addition, the API was modified so that json works only with :class:`str`, not with :class:`bytes`. That change makes the - module closely match the `JSON specification `_ + module closely match the `JSON specification `_ which is defined in terms of Unicode. (Contributed by Bob Ippolito and converted to Py3.1 by Antoine Pitrou diff -Nru python3.10-3.10.7/Doc/whatsnew/3.2.rst python3.10-3.10.12/Doc/whatsnew/3.2.rst --- python3.10-3.10.7/Doc/whatsnew/3.2.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.2.rst 2023-06-06 22:30:33.000000000 +0000 @@ -972,7 +972,7 @@ sealed and deposited in a queue for later handling. See `Barrier Synchronization Patterns -`_ +`_ for more examples of how barriers can be used in parallel computing. Also, there is a simple but thorough explanation of barriers in `The Little Book of Semaphores `_, *section 3.6*. @@ -1745,7 +1745,7 @@ instead of module names for running specific tests (:issue:`10620`). The new test discovery can find tests within packages, locating any test importable from the top-level directory. The top-level directory can be specified with - the `-t` option, a pattern for matching files with ``-p``, and a directory to + the ``-t`` option, a pattern for matching files with ``-p``, and a directory to start discovery with ``-s``: .. code-block:: shell-session @@ -1857,7 +1857,7 @@ :class:`asyncore.dispatcher` now provides a :meth:`~asyncore.dispatcher.handle_accepted()` method -returning a `(sock, addr)` pair which is called when a connection has actually +returning a ``(sock, addr)`` pair which is called when a connection has actually been established with a new remote endpoint. This is supposed to be used as a replacement for old :meth:`~asyncore.dispatcher.handle_accept()` and avoids the user to call :meth:`~asyncore.dispatcher.accept()` directly. @@ -2418,7 +2418,7 @@ ======= Python has been updated to `Unicode 6.0.0 -`_. The update to the standard adds +`_. The update to the standard adds over 2,000 new characters including `emoji `_ symbols which are important for mobile phones. @@ -2426,7 +2426,7 @@ Kannada characters (U+0CF1, U+0CF2) and one New Tai Lue numeric character (U+19DA), making the former eligible for use in identifiers while disqualifying the latter. For more information, see `Unicode Character Database Changes -`_. +`_. Codecs diff -Nru python3.10-3.10.7/Doc/whatsnew/3.3.rst python3.10-3.10.12/Doc/whatsnew/3.3.rst --- python3.10-3.10.7/Doc/whatsnew/3.3.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.3.rst 2023-06-06 22:30:33.000000000 +0000 @@ -932,7 +932,7 @@ array ----- -The :mod:`array` module supports the :c:type:`long long` type using ``q`` and +The :mod:`array` module supports the :c:expr:`long long` type using ``q`` and ``Q`` type codes. (Contributed by Oren Tirosh and Hirokazu Yamamoto in :issue:`1172711`.) @@ -1898,7 +1898,7 @@ family on OS X. (Contributed by Michael Goderbauer in :issue:`13777`.) * New function :func:`~socket.sethostname` allows the hostname to be set - on unix systems if the calling process has sufficient privileges. + on Unix systems if the calling process has sufficient privileges. (Contributed by Ross Lagerwall in :issue:`10866`.) @@ -2267,7 +2267,7 @@ removed in Python 4. All functions using this type are deprecated: Unicode functions and methods using :c:type:`Py_UNICODE` and -:c:type:`Py_UNICODE*` types: +:c:expr:`Py_UNICODE*` types: * :c:macro:`PyUnicode_FromUnicode`: use :c:func:`PyUnicode_FromWideChar` or :c:func:`PyUnicode_FromKindAndData` @@ -2389,10 +2389,10 @@ :attr:`sys.path_importer_cache` where it represents the use of implicit finders, but semantically it should not change anything. -* :class:`importlib.abc.Finder` no longer specifies a `find_module()` abstract +* :class:`importlib.abc.Finder` no longer specifies a ``find_module()`` abstract method that must be implemented. If you were relying on subclasses to implement that method, make sure to check for the method's existence first. - You will probably want to check for `find_loader()` first, though, in the + You will probably want to check for ``find_loader()`` first, though, in the case of working with :term:`path entry finders `. * :mod:`pkgutil` has been converted to use :mod:`importlib` internally. This diff -Nru python3.10-3.10.7/Doc/whatsnew/3.4.rst python3.10-3.10.12/Doc/whatsnew/3.4.rst --- python3.10-3.10.7/Doc/whatsnew/3.4.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.4.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1963,7 +1963,7 @@ `_ will build python, run the test suite, and generate an HTML coverage report for the C codebase using ``gcov`` and `lcov - `_. + `_. * The ``-R`` option to the :ref:`python regression test suite ` now also checks for memory allocation leaks, using diff -Nru python3.10-3.10.7/Doc/whatsnew/3.5.rst python3.10-3.10.12/Doc/whatsnew/3.5.rst --- python3.10-3.10.7/Doc/whatsnew/3.5.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.5.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1977,7 +1977,7 @@ ----------- The :mod:`unicodedata` module now uses data from `Unicode 8.0.0 -`_. +`_. unittest @@ -2469,11 +2469,11 @@ ``opt-`` tag in ``.pyc`` file names. The :func:`importlib.util.cache_from_source` has gained an *optimization* parameter to help control the ``opt-`` tag. Because of this, the - *debug_override* parameter of the function is now deprecated. `.pyo` files + *debug_override* parameter of the function is now deprecated. ``.pyo`` files are also no longer supported as a file argument to the Python interpreter and thus serve no purpose when distributed on their own (i.e. sourceless code distribution). Due to the fact that the magic number for bytecode has changed - in Python 3.5, all old `.pyo` files from previous versions of Python are + in Python 3.5, all old ``.pyo`` files from previous versions of Python are invalid regardless of this PEP. * The :mod:`socket` module now exports the :data:`~socket.CAN_RAW_FD_FRAMES` diff -Nru python3.10-3.10.7/Doc/whatsnew/3.6.rst python3.10-3.10.12/Doc/whatsnew/3.6.rst --- python3.10-3.10.7/Doc/whatsnew/3.6.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.6.rst 2023-06-06 22:30:33.000000000 +0000 @@ -960,8 +960,8 @@ The :class:`contextlib.AbstractContextManager` class has been added to provide an abstract base class for context managers. It provides a -sensible default implementation for `__enter__()` which returns -``self`` and leaves `__exit__()` an abstract method. A matching +sensible default implementation for ``__enter__()`` which returns +``self`` and leaves ``__exit__()`` an abstract method. A matching class has been added to the :mod:`typing` module as :class:`typing.ContextManager`. (Contributed by Brett Cannon in :issue:`25609`.) @@ -1388,7 +1388,7 @@ site ---- -When specifying paths to add to :attr:`sys.path` in a `.pth` file, +When specifying paths to add to :attr:`sys.path` in a ``.pth`` file, you may now specify file paths on top of directories (e.g. zip files). (Contributed by Wolfgang Langner in :issue:`26587`). @@ -1422,7 +1422,7 @@ Victor Stinner.) New Linux constants ``TCP_USER_TIMEOUT`` and ``TCP_CONGESTION`` were added. -(Contributed by Omar Sandoval, issue:`26273`). +(Contributed by Omar Sandoval, :issue:`26273`). socketserver @@ -1644,7 +1644,7 @@ ----------- The :mod:`unicodedata` module now uses data from `Unicode 9.0.0 -`_. +`_. (Contributed by Benjamin Peterson.) @@ -2052,6 +2052,8 @@ The :mod:`tkinter.tix` module is now deprecated. :mod:`tkinter` users should use :mod:`tkinter.ttk` instead. +.. _whatsnew36-venv: + venv ~~~~ diff -Nru python3.10-3.10.7/Doc/whatsnew/3.7.rst python3.10-3.10.12/Doc/whatsnew/3.7.rst --- python3.10-3.10.7/Doc/whatsnew/3.7.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.7.rst 2023-06-06 22:30:33.000000000 +0000 @@ -290,21 +290,21 @@ While Python provides a C API for thread-local storage support; the existing :ref:`Thread Local Storage (TLS) API ` has used -:c:type:`int` to represent TLS keys across all platforms. This has not +:c:expr:`int` to represent TLS keys across all platforms. This has not generally been a problem for officially support platforms, but that is neither POSIX-compliant, nor portable in any practical sense. :pep:`539` changes this by providing a new :ref:`Thread Specific Storage (TSS) API ` to CPython which supersedes use of the existing TLS API within the CPython interpreter, while deprecating the existing -API. The TSS API uses a new type :c:type:`Py_tss_t` instead of :c:type:`int` +API. The TSS API uses a new type :c:type:`Py_tss_t` instead of :c:expr:`int` to represent TSS keys--an opaque type the definition of which may depend on the underlying TLS implementation. Therefore, this will allow to build CPython on platforms where the native TLS key is defined in a way that cannot be safely -cast to :c:type:`int`. +cast to :c:expr:`int`. Note that on platforms where the native TLS key is defined in a way that cannot -be safely cast to :c:type:`int`, all functions of the existing TLS API will be +be safely cast to :c:expr:`int`, all functions of the existing TLS API will be no-op and immediately return failure. This indicates clearly that the old API is not supported on platforms where it cannot be used reliably, and that no effort will be made to add such support. @@ -1507,7 +1507,7 @@ ----------- The internal :mod:`unicodedata` database has been upgraded to use `Unicode 11 -`_. (Contributed by Benjamin +`_. (Contributed by Benjamin Peterson.) @@ -1708,12 +1708,12 @@ The type of results of :c:func:`PyThread_start_new_thread` and :c:func:`PyThread_get_thread_ident`, and the *id* parameter of -:c:func:`PyThreadState_SetAsyncExc` changed from :c:type:`long` to -:c:type:`unsigned long`. +:c:func:`PyThreadState_SetAsyncExc` changed from :c:expr:`long` to +:c:expr:`unsigned long`. (Contributed by Serhiy Storchaka in :issue:`6532`.) :c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the -second argument is ``NULL`` and the :c:type:`wchar_t*` string contains null +second argument is ``NULL`` and the :c:expr:`wchar_t*` string contains null characters. (Contributed by Serhiy Storchaka in :issue:`30708`.) Changes to the startup sequence and the management of dynamic memory @@ -2497,7 +2497,7 @@ * :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding applications due to the requirement to create a Unicode object prior to - calling `Py_Initialize`. Use :c:func:`PySys_AddWarnOption` instead. + calling ``Py_Initialize``. Use :c:func:`PySys_AddWarnOption` instead. * warnings filters added by an embedding application with :c:func:`PySys_AddWarnOption` should now more consistently take precedence diff -Nru python3.10-3.10.7/Doc/whatsnew/3.8.rst python3.10-3.10.12/Doc/whatsnew/3.8.rst --- python3.10-3.10.7/Doc/whatsnew/3.8.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.8.rst 2023-06-06 22:30:33.000000000 +0000 @@ -122,8 +122,8 @@ There is a new function parameter syntax ``/`` to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments. This is the same notation shown by ``help()`` for C -functions annotated with Larry Hastings' `Argument Clinic -`_ tool. +functions annotated with Larry Hastings' +:ref:`Argument Clinic ` tool. In the following example, parameters *a* and *b* are positional-only, while *c* or *d* can be positional or keyword, and *e* or *f* are @@ -250,6 +250,7 @@ this change is backward incompatible on purpose. (Contributed by Victor Stinner in :issue:`36721`.) +.. _bpo-36817-whatsnew: f-strings support ``=`` for self-documenting expressions and debugging ---------------------------------------------------------------------- @@ -1347,7 +1348,7 @@ ----------- The :mod:`unicodedata` module has been upgraded to use the `Unicode 12.1.0 -`_ release. +`_ release. New function :func:`~unicodedata.is_normalized` can be used to verify a string is in a specific normal form, often much faster than by actually normalizing @@ -2011,7 +2012,7 @@ Changes in the C API -------------------- -* The :c:type:`PyCompilerFlags` structure got a new *cf_feature_version* +* The :c:struct:`PyCompilerFlags` structure got a new *cf_feature_version* field. It should be initialized to ``PY_MINOR_VERSION``. The field is ignored by default, and is used if and only if ``PyCF_ONLY_AST`` flag is set in *cf_flags*. diff -Nru python3.10-3.10.7/Doc/whatsnew/3.9.rst python3.10-3.10.12/Doc/whatsnew/3.9.rst --- python3.10-3.10.7/Doc/whatsnew/3.9.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Doc/whatsnew/3.9.rst 2023-06-06 22:30:33.000000000 +0000 @@ -2,8 +2,6 @@ What's New In Python 3.9 **************************** -:Release: |release| -:Date: |today| :Editor: Łukasz Langa .. Rules for maintenance: @@ -500,7 +498,7 @@ the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in :issue:`33962`.) -Apply syntax highlighting to `.pyi` files. (Contributed by Alex +Apply syntax highlighting to ``.pyi`` files. (Contributed by Alex Waygood and Terry Jan Reedy in :issue:`45447`.) imaplib @@ -773,7 +771,7 @@ Stinner in :issue:`38061`.) * :c:func:`PyLong_FromDouble` is now up to 1.87x faster for values that - fit into :c:type:`long`. + fit into :c:expr:`long`. (Contributed by Sergey Fedoseev in :issue:`37986`.) * A number of Python builtins (:class:`range`, :class:`tuple`, :class:`set`, diff -Nru python3.10-3.10.7/Include/dynamic_annotations.h python3.10-3.10.12/Include/dynamic_annotations.h --- python3.10-3.10.7/Include/dynamic_annotations.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Include/dynamic_annotations.h 2023-06-06 22:30:33.000000000 +0000 @@ -44,7 +44,7 @@ Actual implementation of these macros may differ depending on the dynamic analysis tool being used. - See http://code.google.com/p/data-race-test/ for more information. + See https://code.google.com/p/data-race-test/ for more information. This file supports the following dynamic analysis tools: - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero). @@ -140,7 +140,7 @@ of the mutex's critical sections individually using the annotations above. This annotation makes sense only for hybrid race detectors. For pure happens-before detectors this is a no-op. For more details see - http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */ + https://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */ #define _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \ AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu) diff -Nru python3.10-3.10.7/Include/patchlevel.h python3.10-3.10.12/Include/patchlevel.h --- python3.10-3.10.7/Include/patchlevel.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Include/patchlevel.h 2023-06-06 22:30:33.000000000 +0000 @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 10 -#define PY_MICRO_VERSION 7 +#define PY_MICRO_VERSION 12 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.10.7" +#define PY_VERSION "3.10.12" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff -Nru python3.10-3.10.7/Lib/argparse.py python3.10-3.10.12/Lib/argparse.py --- python3.10-3.10.7/Lib/argparse.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/argparse.py 2023-06-06 22:30:33.000000000 +0000 @@ -400,10 +400,18 @@ except ValueError: continue else: - end = start + len(group._group_actions) + group_action_count = len(group._group_actions) + end = start + group_action_count if actions[start:end] == group._group_actions: + + suppressed_actions_count = 0 for action in group._group_actions: group_actions.add(action) + if action.help is SUPPRESS: + suppressed_actions_count += 1 + + exposed_actions_count = group_action_count - suppressed_actions_count + if not group.required: if start in inserts: inserts[start] += ' [' @@ -413,7 +421,7 @@ inserts[end] += ']' else: inserts[end] = ']' - else: + elif exposed_actions_count > 1: if start in inserts: inserts[start] += ' (' else: @@ -487,7 +495,6 @@ text = _re.sub(r'(%s) ' % open, r'\1', text) text = _re.sub(r' (%s)' % close, r'\1', text) text = _re.sub(r'%s *%s' % (open, close), r'', text) - text = _re.sub(r'\(([^|]*)\)', r'\1', text) text = text.strip() # return the text @@ -1962,7 +1969,11 @@ # arguments, try to parse more single-dash options out # of the tail of the option string chars = self.prefix_chars - if arg_count == 0 and option_string[1] not in chars: + if ( + arg_count == 0 + and option_string[1] not in chars + and explicit_arg != '' + ): action_tuples.append((action, [], option_string)) char = option_string[0] option_string = char + explicit_arg[0] diff -Nru python3.10-3.10.7/Lib/ast.py python3.10-3.10.12/Lib/ast.py --- python3.10-3.10.7/Lib/ast.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/ast.py 2023-06-06 22:30:33.000000000 +0000 @@ -53,10 +53,12 @@ def literal_eval(node_or_string): """ - Safely evaluate an expression node or a string containing a Python + Evaluate an expression node or a string containing only a Python expression. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None. + + Caution: A complex expression can overflow the C stack and cause a crash. """ if isinstance(node_or_string, str): node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval') @@ -234,6 +236,12 @@ location in a file. """ for child in walk(node): + # TypeIgnore is a special case where lineno is not an attribute + # but rather a field of the node itself. + if isinstance(child, TypeIgnore): + child.lineno = getattr(child, 'lineno', 0) + n + continue + if 'lineno' in child._attributes: child.lineno = getattr(child, 'lineno', 0) + n if ( @@ -849,7 +857,7 @@ def visit_ImportFrom(self, node): self.fill("from ") - self.write("." * node.level) + self.write("." * (node.level or 0)) if node.module: self.write(node.module) self.write(" import ") diff -Nru python3.10-3.10.7/Lib/asyncio/base_events.py python3.10-3.10.12/Lib/asyncio/base_events.py --- python3.10-3.10.7/Lib/asyncio/base_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/base_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -573,9 +573,11 @@ def _do_shutdown(self, future): try: self._default_executor.shutdown(wait=True) - self.call_soon_threadsafe(future.set_result, None) + if not self.is_closed(): + self.call_soon_threadsafe(future.set_result, None) except Exception as ex: - self.call_soon_threadsafe(future.set_exception, ex) + if not self.is_closed(): + self.call_soon_threadsafe(future.set_exception, ex) def _check_running(self): if self.is_running(): @@ -589,12 +591,13 @@ self._check_closed() self._check_running() self._set_coroutine_origin_tracking(self._debug) - self._thread_id = threading.get_ident() old_agen_hooks = sys.get_asyncgen_hooks() - sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook, - finalizer=self._asyncgen_finalizer_hook) try: + self._thread_id = threading.get_ident() + sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook, + finalizer=self._asyncgen_finalizer_hook) + events._set_running_loop(self) while True: self._run_once() @@ -943,7 +946,10 @@ sock = socket.socket(family=family, type=type_, proto=proto) sock.setblocking(False) if local_addr_infos is not None: - for _, _, _, _, laddr in local_addr_infos: + for lfamily, _, _, _, laddr in local_addr_infos: + # skip local addresses of different family + if lfamily != family: + continue try: sock.bind(laddr) break @@ -956,7 +962,10 @@ exc = OSError(exc.errno, msg) my_exceptions.append(exc) else: # all bind attempts failed - raise my_exceptions.pop() + if my_exceptions: + raise my_exceptions.pop() + else: + raise OSError(f"no matching local address with {family=} found") await self.sock_connect(sock, address) return sock except OSError as exc: @@ -968,6 +977,8 @@ if sock is not None: sock.close() raise + finally: + exceptions = my_exceptions = None async def create_connection( self, protocol_factory, host=None, port=None, @@ -1060,17 +1071,20 @@ if sock is None: exceptions = [exc for sub in exceptions for exc in sub] - if len(exceptions) == 1: - raise exceptions[0] - else: - # If they all have the same str(), raise one. - model = str(exceptions[0]) - if all(str(exc) == model for exc in exceptions): + try: + if len(exceptions) == 1: raise exceptions[0] - # Raise a combined exception so the user can see all - # the various error messages. - raise OSError('Multiple exceptions: {}'.format( - ', '.join(str(exc) for exc in exceptions))) + else: + # If they all have the same str(), raise one. + model = str(exceptions[0]) + if all(str(exc) == model for exc in exceptions): + raise exceptions[0] + # Raise a combined exception so the user can see all + # the various error messages. + raise OSError('Multiple exceptions: {}'.format( + ', '.join(str(exc) for exc in exceptions))) + finally: + exceptions = None else: if sock is None: @@ -1801,12 +1815,9 @@ exc_info=True) def _add_callback(self, handle): - """Add a Handle to _scheduled (TimerHandle) or _ready.""" - assert isinstance(handle, events.Handle), 'A Handle is required here' - if handle._cancelled: - return - assert not isinstance(handle, events.TimerHandle) - self._ready.append(handle) + """Add a Handle to _ready.""" + if not handle._cancelled: + self._ready.append(handle) def _add_callback_signalsafe(self, handle): """Like _add_callback() but called from a signal handler.""" @@ -1859,6 +1870,8 @@ event_list = self._selector.select(timeout) self._process_events(event_list) + # Needed to break cycles when an exception occurs. + event_list = None # Handle 'later' callbacks that are ready. end_time = self.time() + self._clock_resolution diff -Nru python3.10-3.10.7/Lib/asyncio/events.py python3.10-3.10.12/Lib/asyncio/events.py --- python3.10-3.10.7/Lib/asyncio/events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/events.py 2023-06-06 22:30:33.000000000 +0000 @@ -763,12 +763,13 @@ def _get_event_loop(stacklevel=3): + # This internal method is going away in Python 3.12, left here only for + # backwards compatibility with 3.10.0 - 3.10.8 and 3.11.0. + # Similarly, this method's C equivalent in _asyncio is going away as well. + # See GH-99949 for more details. current_loop = _get_running_loop() if current_loop is not None: return current_loop - import warnings - warnings.warn('There is no current event loop', - DeprecationWarning, stacklevel=stacklevel) return get_event_loop_policy().get_event_loop() diff -Nru python3.10-3.10.7/Lib/asyncio/futures.py python3.10-3.10.12/Lib/asyncio/futures.py --- python3.10-3.10.7/Lib/asyncio/futures.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/futures.py 2023-06-06 22:30:33.000000000 +0000 @@ -396,6 +396,8 @@ if dest_loop is None or dest_loop is source_loop: _set_state(destination, source) else: + if dest_loop.is_closed(): + return dest_loop.call_soon_threadsafe(_set_state, destination, source) destination.add_done_callback(_call_check_cancel) diff -Nru python3.10-3.10.7/Lib/asyncio/locks.py python3.10-3.10.12/Lib/asyncio/locks.py --- python3.10-3.10.7/Lib/asyncio/locks.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/locks.py 2023-06-06 22:30:33.000000000 +0000 @@ -349,9 +349,8 @@ super().__init__(loop=loop) if value < 0: raise ValueError("Semaphore initial value must be >= 0") + self._waiters = None self._value = value - self._waiters = collections.deque() - self._wakeup_scheduled = False def __repr__(self): res = super().__repr__() @@ -360,17 +359,10 @@ extra = f'{extra}, waiters:{len(self._waiters)}' return f'<{res[1:-1]} [{extra}]>' - def _wake_up_next(self): - while self._waiters: - waiter = self._waiters.popleft() - if not waiter.done(): - waiter.set_result(None) - self._wakeup_scheduled = True - return - def locked(self): - """Returns True if semaphore can not be acquired immediately.""" - return self._value == 0 + """Returns True if semaphore cannot be acquired immediately.""" + return self._value == 0 or ( + any(not w.cancelled() for w in (self._waiters or ()))) async def acquire(self): """Acquire a semaphore. @@ -381,29 +373,53 @@ called release() to make it larger than 0, and then return True. """ - # _wakeup_scheduled is set if *another* task is scheduled to wakeup - # but its acquire() is not resumed yet - while self._wakeup_scheduled or self._value <= 0: - fut = self._get_loop().create_future() - self._waiters.append(fut) + if not self.locked(): + self._value -= 1 + return True + + if self._waiters is None: + self._waiters = collections.deque() + fut = self._get_loop().create_future() + self._waiters.append(fut) + + # Finally block should be called before the CancelledError + # handling as we don't want CancelledError to call + # _wake_up_first() and attempt to wake up itself. + try: try: await fut - # reset _wakeup_scheduled *after* waiting for a future - self._wakeup_scheduled = False - except exceptions.CancelledError: + finally: + self._waiters.remove(fut) + except exceptions.CancelledError: + if not fut.cancelled(): + self._value += 1 self._wake_up_next() - raise - self._value -= 1 + raise + + if self._value > 0: + self._wake_up_next() return True def release(self): """Release a semaphore, incrementing the internal counter by one. + When it was zero on entry and another coroutine is waiting for it to become larger than zero again, wake up that coroutine. """ self._value += 1 self._wake_up_next() + def _wake_up_next(self): + """Wake up the first waiter that isn't done.""" + if not self._waiters: + return + + for fut in self._waiters: + if not fut.done(): + self._value -= 1 + fut.set_result(True) + return + class BoundedSemaphore(Semaphore): """A bounded semaphore implementation. diff -Nru python3.10-3.10.7/Lib/asyncio/proactor_events.py python3.10-3.10.12/Lib/asyncio/proactor_events.py --- python3.10-3.10.7/Lib/asyncio/proactor_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/proactor_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -60,6 +60,7 @@ self._pending_write = 0 self._conn_lost = 0 self._closing = False # Set when close() called. + self._called_connection_lost = False self._eof_written = False if self._server is not None: self._server._attach() @@ -136,7 +137,7 @@ self._empty_waiter.set_result(None) else: self._empty_waiter.set_exception(exc) - if self._closing: + if self._closing and self._called_connection_lost: return self._closing = True self._conn_lost += 1 @@ -151,6 +152,8 @@ self._loop.call_soon(self._call_connection_lost, exc) def _call_connection_lost(self, exc): + if self._called_connection_lost: + return try: self._protocol.connection_lost(exc) finally: @@ -166,6 +169,7 @@ if server is not None: server._detach() self._server = None + self._called_connection_lost = True def get_write_buffer_size(self): size = self._pending_write diff -Nru python3.10-3.10.7/Lib/asyncio/selector_events.py python3.10-3.10.12/Lib/asyncio/selector_events.py --- python3.10-3.10.7/Lib/asyncio/selector_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/selector_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -497,7 +497,11 @@ fut = self.create_future() self._sock_connect(fut, sock, address) - return await fut + try: + return await fut + finally: + # Needed to break cycles when an exception occurs. + fut = None def _sock_connect(self, fut, sock, address): fd = sock.fileno() @@ -519,6 +523,8 @@ fut.set_exception(exc) else: fut.set_result(None) + finally: + fut = None def _sock_write_done(self, fd, fut, handle=None): if handle is None or not handle.cancelled(): @@ -542,6 +548,8 @@ fut.set_exception(exc) else: fut.set_result(None) + finally: + fut = None async def sock_accept(self, sock): """Accept a connection. diff -Nru python3.10-3.10.7/Lib/asyncio/streams.py python3.10-3.10.12/Lib/asyncio/streams.py --- python3.10-3.10.7/Lib/asyncio/streams.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/streams.py 2023-06-06 22:30:33.000000000 +0000 @@ -2,6 +2,7 @@ 'StreamReader', 'StreamWriter', 'StreamReaderProtocol', 'open_connection', 'start_server') +import collections import socket import sys import warnings @@ -129,7 +130,7 @@ else: self._loop = loop self._paused = False - self._drain_waiter = None + self._drain_waiters = collections.deque() self._connection_lost = False def pause_writing(self): @@ -144,38 +145,34 @@ if self._loop.get_debug(): logger.debug("%r resumes writing", self) - waiter = self._drain_waiter - if waiter is not None: - self._drain_waiter = None + for waiter in self._drain_waiters: if not waiter.done(): waiter.set_result(None) def connection_lost(self, exc): self._connection_lost = True - # Wake up the writer if currently paused. + # Wake up the writer(s) if currently paused. if not self._paused: return - waiter = self._drain_waiter - if waiter is None: - return - self._drain_waiter = None - if waiter.done(): - return - if exc is None: - waiter.set_result(None) - else: - waiter.set_exception(exc) + + for waiter in self._drain_waiters: + if not waiter.done(): + if exc is None: + waiter.set_result(None) + else: + waiter.set_exception(exc) async def _drain_helper(self): if self._connection_lost: raise ConnectionResetError('Connection lost') if not self._paused: return - waiter = self._drain_waiter - assert waiter is None or waiter.cancelled() waiter = self._loop.create_future() - self._drain_waiter = waiter - await waiter + self._drain_waiters.append(waiter) + try: + await waiter + finally: + self._drain_waiters.remove(waiter) def _get_close_waiter(self, stream): raise NotImplementedError @@ -206,6 +203,7 @@ self._strong_reader = stream_reader self._reject_connection = False self._stream_writer = None + self._task = None self._transport = None self._client_connected_cb = client_connected_cb self._over_ssl = False @@ -241,7 +239,7 @@ res = self._client_connected_cb(reader, self._stream_writer) if coroutines.iscoroutine(res): - self._loop.create_task(res) + self._task = self._loop.create_task(res) self._strong_reader = None def connection_lost(self, exc): @@ -259,6 +257,7 @@ super().connection_lost(exc) self._stream_reader_wr = None self._stream_writer = None + self._task = None self._transport = None def data_received(self, data): @@ -628,16 +627,17 @@ async def read(self, n=-1): """Read up to `n` bytes from the stream. - If n is not provided, or set to -1, read until EOF and return all read - bytes. If the EOF was received and the internal buffer is empty, return - an empty bytes object. - - If n is zero, return empty bytes object immediately. - - If n is positive, this function try to read `n` bytes, and may return - less or equal bytes than requested, but at least one byte. If EOF was - received before any byte is read, this function returns empty byte - object. + If `n` is not provided or set to -1, + read until EOF, then return all read bytes. + If EOF was received and the internal buffer is empty, + return an empty bytes object. + + If `n` is 0, return an empty bytes object immediately. + + If `n` is positive, return at most `n` available bytes + as soon as at least 1 byte is available in the internal buffer. + If EOF is received before any byte is read, return an empty + bytes object. Returned value is not limited with limit, configured at stream creation. diff -Nru python3.10-3.10.7/Lib/asyncio/tasks.py python3.10-3.10.12/Lib/asyncio/tasks.py --- python3.10-3.10.7/Lib/asyncio/tasks.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/tasks.py 2023-06-06 22:30:33.000000000 +0000 @@ -809,7 +809,8 @@ The statement - res = await shield(something()) + task = asyncio.create_task(something()) + res = await shield(task) is exactly equivalent to the statement @@ -825,10 +826,16 @@ If you want to completely ignore cancellation (not recommended) you can combine shield() with a try/except clause, as follows: + task = asyncio.create_task(something()) try: - res = await shield(something()) + res = await shield(task) except CancelledError: res = None + + Save a reference to tasks passed to this function, to avoid + a task disappearing mid-execution. The event loop only keeps + weak references to tasks. A task that isn't referenced elsewhere + may get garbage collected at any time, even before it's done. """ inner = _ensure_future(arg) if inner.done(): diff -Nru python3.10-3.10.7/Lib/asyncio/unix_events.py python3.10-3.10.12/Lib/asyncio/unix_events.py --- python3.10-3.10.7/Lib/asyncio/unix_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/unix_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -223,7 +223,8 @@ return transp def _child_watcher_callback(self, pid, returncode, transp): - self.call_soon_threadsafe(transp._process_exited, returncode) + # Skip one iteration for callbacks to be executed + self.call_soon_threadsafe(self.call_soon, transp._process_exited, returncode) async def create_unix_connection( self, protocol_factory, path=None, *, @@ -788,12 +789,11 @@ def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs): stdin_w = None - if stdin == subprocess.PIPE: - # Use a socket pair for stdin, since not all platforms + if stdin == subprocess.PIPE and sys.platform.startswith('aix'): + # Use a socket pair for stdin on AIX, since it does not # support selecting read events on the write end of a # socket (which we use in order to detect closing of the - # other end). Notably this is needed on AIX, and works - # just fine on other platforms. + # other end). stdin, stdin_w = socket.socketpair() try: self._proc = subprocess.Popen( diff -Nru python3.10-3.10.7/Lib/asyncio/windows_events.py python3.10-3.10.12/Lib/asyncio/windows_events.py --- python3.10-3.10.7/Lib/asyncio/windows_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/asyncio/windows_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -366,6 +366,10 @@ return f = self._proactor.accept_pipe(pipe) + except BrokenPipeError: + if pipe and pipe.fileno() != -1: + pipe.close() + self.call_soon(loop_accept_pipe) except OSError as exc: if pipe and pipe.fileno() != -1: self.call_exception_handler({ @@ -377,6 +381,7 @@ elif self._debug: logger.warning("Accept pipe failed on pipe %r", pipe, exc_info=True) + self.call_soon(loop_accept_pipe) except exceptions.CancelledError: if pipe: pipe.close() @@ -439,7 +444,11 @@ self._poll(timeout) tmp = self._results self._results = [] - return tmp + try: + return tmp + finally: + # Needed to break cycles when an exception occurs. + tmp = None def _result(self, value): fut = self._loop.create_future() @@ -821,6 +830,8 @@ else: f.set_result(value) self._results.append(f) + finally: + f = None # Remove unregistered futures for ov in self._unregistered: diff -Nru python3.10-3.10.7/Lib/bdb.py python3.10-3.10.12/Lib/bdb.py --- python3.10-3.10.7/Lib/bdb.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/bdb.py 2023-06-06 22:30:33.000000000 +0000 @@ -570,9 +570,10 @@ rv = frame.f_locals['__return__'] s += '->' s += reprlib.repr(rv) - line = linecache.getline(filename, lineno, frame.f_globals) - if line: - s += lprefix + line.strip() + if lineno is not None: + line = linecache.getline(filename, lineno, frame.f_globals) + if line: + s += lprefix + line.strip() return s # The following methods can be called by clients to use diff -Nru python3.10-3.10.7/Lib/codecs.py python3.10-3.10.12/Lib/codecs.py --- python3.10-3.10.7/Lib/codecs.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/codecs.py 2023-06-06 22:30:33.000000000 +0000 @@ -878,7 +878,8 @@ codecs. Output is also codec dependent and will usually be Unicode as well. - Underlying encoded files are always opened in binary mode. + If encoding is not None, then the + underlying encoded files are always opened in binary mode. The default file mode is 'r', meaning to open the file in read mode. encoding specifies the encoding which is to be used for the diff -Nru python3.10-3.10.7/Lib/codeop.py python3.10-3.10.12/Lib/codeop.py --- python3.10-3.10.7/Lib/codeop.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/codeop.py 2023-06-06 22:30:33.000000000 +0000 @@ -56,22 +56,22 @@ if symbol != "eval": source = "pass" # Replace it with a 'pass' statement - try: - return compiler(source, filename, symbol) - except SyntaxError: # Let other compile() errors propagate. - pass - - # Catch syntax warnings after the first compile - # to emit warnings (SyntaxWarning, DeprecationWarning) at most once. + # Disable compiler warnings when checking for incomplete input. with warnings.catch_warnings(): - warnings.simplefilter("error") - + warnings.simplefilter("ignore", (SyntaxWarning, DeprecationWarning)) try: - compiler(source + "\n", filename, symbol) - except SyntaxError as e: - if "incomplete input" in str(e): + compiler(source, filename, symbol) + except SyntaxError: # Let other compile() errors propagate. + try: + compiler(source + "\n", filename, symbol) return None - raise + except SyntaxError as e: + if "incomplete input" in str(e): + return None + # fallthrough + + return compiler(source, filename, symbol) + def _is_syntax_error(err1, err2): rep1 = repr(err1) diff -Nru python3.10-3.10.7/Lib/_collections_abc.py python3.10-3.10.12/Lib/_collections_abc.py --- python3.10-3.10.7/Lib/_collections_abc.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/_collections_abc.py 2023-06-06 22:30:33.000000000 +0000 @@ -441,6 +441,8 @@ def __parameters__(self): params = [] for arg in self.__args__: + if isinstance(arg, type) and not isinstance(arg, GenericAlias): + continue # Looks like a genericalias if hasattr(arg, "__parameters__") and isinstance(arg.__parameters__, tuple): params.extend(arg.__parameters__) @@ -486,6 +488,9 @@ subst = dict(zip(self.__parameters__, item)) new_args = [] for arg in self.__args__: + if isinstance(arg, type) and not isinstance(arg, GenericAlias): + new_args.append(arg) + continue if _is_typevarlike(arg): if _is_param_expr(arg): arg = subst[arg] diff -Nru python3.10-3.10.7/Lib/compileall.py python3.10-3.10.12/Lib/compileall.py --- python3.10-3.10.7/Lib/compileall.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/compileall.py 2023-06-06 22:30:33.000000000 +0000 @@ -154,8 +154,8 @@ "in combination with stripdir or prependdir")) success = True - if quiet < 2 and isinstance(fullname, os.PathLike): - fullname = os.fspath(fullname) + fullname = os.fspath(fullname) + stripdir = os.fspath(stripdir) if stripdir is not None else None name = os.path.basename(fullname) dfile = None diff -Nru python3.10-3.10.7/Lib/concurrent/futures/process.py python3.10-3.10.12/Lib/concurrent/futures/process.py --- python3.10-3.10.7/Lib/concurrent/futures/process.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/concurrent/futures/process.py 2023-06-06 22:30:33.000000000 +0000 @@ -337,6 +337,11 @@ if self.is_shutting_down(): self.flag_executor_shutting_down() + # When only canceled futures remain in pending_work_items, our + # next call to wait_result_broken_or_wakeup would hang forever. + # This makes sure we have some running futures or none at all. + self.add_call_item_to_queue() + # Since no new work items can be added, it is safe to shutdown # this thread if there are no pending work items. if not self.pending_work_items: diff -Nru python3.10-3.10.7/Lib/configparser.py python3.10-3.10.12/Lib/configparser.py --- python3.10-3.10.7/Lib/configparser.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/configparser.py 2023-06-06 22:30:33.000000000 +0000 @@ -19,36 +19,37 @@ inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section='DEFAULT', interpolation=, converters=): - Create the parser. When `defaults' is given, it is initialized into the + + Create the parser. When `defaults` is given, it is initialized into the dictionary or intrinsic defaults. The keys must be strings, the values must be appropriate for %()s string interpolation. - When `dict_type' is given, it will be used to create the dictionary + When `dict_type` is given, it will be used to create the dictionary objects for the list of sections, for the options within a section, and for the default values. - When `delimiters' is given, it will be used as the set of substrings + When `delimiters` is given, it will be used as the set of substrings that divide keys from values. - When `comment_prefixes' is given, it will be used as the set of + When `comment_prefixes` is given, it will be used as the set of substrings that prefix comments in empty lines. Comments can be indented. - When `inline_comment_prefixes' is given, it will be used as the set of + When `inline_comment_prefixes` is given, it will be used as the set of substrings that prefix comments in non-empty lines. When `strict` is True, the parser won't allow for any section or option duplicates while reading from a single source (file, string or dictionary). Default is True. - When `empty_lines_in_values' is False (default: True), each empty line + When `empty_lines_in_values` is False (default: True), each empty line marks the end of an option. Otherwise, internal empty lines of a multiline option are kept as part of the value. - When `allow_no_value' is True (default: False), options without + When `allow_no_value` is True (default: False), options without values are accepted; the value presented for these is None. - When `default_section' is given, the name of the special section is + When `default_section` is given, the name of the special section is named accordingly. By default it is called ``"DEFAULT"`` but this can be customized to point to any other valid section name. Its current value can be retrieved using the ``parser_instance.default_section`` @@ -87,7 +88,7 @@ read_file(f, filename=None) Read and parse one configuration file, given as a file object. The filename defaults to f.name; it is only used in error - messages (if f has no `name' attribute, the string `' is used). + messages (if f has no `name` attribute, the string `` is used). read_string(string) Read configuration from a given string. @@ -103,9 +104,9 @@ Return a string value for the named option. All % interpolations are expanded in the return values, based on the defaults passed into the constructor and the DEFAULT section. Additional substitutions may be - provided using the `vars' argument, which must be a dictionary whose - contents override any pre-existing defaults. If `option' is a key in - `vars', the value from `vars' is used. + provided using the `vars` argument, which must be a dictionary whose + contents override any pre-existing defaults. If `option` is a key in + `vars`, the value from `vars` is used. getint(section, options, raw=False, vars=None, fallback=_UNSET) Like get(), but convert value to an integer. @@ -134,7 +135,7 @@ write(fp, space_around_delimiters=True) Write the configuration state in .ini format. If - `space_around_delimiters' is True (the default), delimiters + `space_around_delimiters` is True (the default), delimiters between keys and values are surrounded by spaces. """ @@ -352,7 +353,7 @@ # Used in parser getters to indicate the default behaviour when a specific -# option is not found it to raise an exception. Created to enable `None' as +# option is not found it to raise an exception. Created to enable `None` as # a valid fallback value. _UNSET = object() @@ -386,7 +387,7 @@ would resolve the "%(dir)s" to the value of dir. All reference expansions are done late, on demand. If a user needs to use a bare % in a configuration file, she can escape it by writing %%. Other % usage - is considered a user error and raises `InterpolationSyntaxError'.""" + is considered a user error and raises `InterpolationSyntaxError`.""" _KEYCRE = re.compile(r"%\(([^)]+)\)s") @@ -447,7 +448,7 @@ class ExtendedInterpolation(Interpolation): """Advanced variant of interpolation, supports the syntax used by - `zc.buildout'. Enables interpolation between sections.""" + `zc.buildout`. Enables interpolation between sections.""" _KEYCRE = re.compile(r"\$\{([^}]+)\}") @@ -706,10 +707,10 @@ def read_file(self, f, source=None): """Like read() but the argument must be a file-like object. - The `f' argument must be iterable, returning one line at a time. - Optional second argument is the `source' specifying the name of the - file being read. If not given, it is taken from f.name. If `f' has no - `name' attribute, `' is used. + The `f` argument must be iterable, returning one line at a time. + Optional second argument is the `source` specifying the name of the + file being read. If not given, it is taken from f.name. If `f` has no + `name` attribute, `` is used. """ if source is None: try: @@ -733,7 +734,7 @@ All types held in the dictionary are converted to strings during reading, including section names, option names and keys. - Optional second argument is the `source' specifying the name of the + Optional second argument is the `source` specifying the name of the dictionary being read. """ elements_added = set() @@ -766,15 +767,15 @@ def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET): """Get an option value for a given section. - If `vars' is provided, it must be a dictionary. The option is looked up - in `vars' (if provided), `section', and in `DEFAULTSECT' in that order. - If the key is not found and `fallback' is provided, it is used as - a fallback value. `None' can be provided as a `fallback' value. + If `vars` is provided, it must be a dictionary. The option is looked up + in `vars` (if provided), `section`, and in `DEFAULTSECT` in that order. + If the key is not found and `fallback` is provided, it is used as + a fallback value. `None` can be provided as a `fallback` value. - If interpolation is enabled and the optional argument `raw' is False, + If interpolation is enabled and the optional argument `raw` is False, all interpolations are expanded in the return values. - Arguments `raw', `vars', and `fallback' are keyword only. + Arguments `raw`, `vars`, and `fallback` are keyword only. The section DEFAULT is special. """ @@ -834,8 +835,8 @@ All % interpolations are expanded in the return values, based on the defaults passed into the constructor, unless the optional argument - `raw' is true. Additional substitutions may be provided using the - `vars' argument, which must be a dictionary whose contents overrides + `raw` is true. Additional substitutions may be provided using the + `vars` argument, which must be a dictionary whose contents overrides any pre-existing defaults. The section DEFAULT is special. @@ -877,8 +878,8 @@ def has_option(self, section, option): """Check for the existence of a given option in a given section. - If the specified `section' is None or an empty string, DEFAULT is - assumed. If the specified `section' does not exist, returns False.""" + If the specified `section` is None or an empty string, DEFAULT is + assumed. If the specified `section` does not exist, returns False.""" if not section or section == self.default_section: option = self.optionxform(option) return option in self._defaults @@ -906,7 +907,7 @@ def write(self, fp, space_around_delimiters=True): """Write an .ini-format representation of the configuration state. - If `space_around_delimiters' is True (the default), delimiters + If `space_around_delimiters` is True (the default), delimiters between keys and values are surrounded by spaces. Please note that comments in the original configuration file are not @@ -924,7 +925,7 @@ self._sections[section].items(), d) def _write_section(self, fp, section_name, section_items, delimiter): - """Write a single section to the specified `fp'.""" + """Write a single section to the specified `fp`.""" fp.write("[{}]\n".format(section_name)) for key, value in section_items: value = self._interpolation.before_write(self, section_name, key, @@ -998,8 +999,8 @@ """Parse a sectioned configuration file. Each section in a configuration file contains a header, indicated by - a name in square brackets (`[]'), plus key/value options, indicated by - `name' and `value' delimited with a specific substring (`=' or `:' by + a name in square brackets (`[]`), plus key/value options, indicated by + `name` and `value` delimited with a specific substring (`=` or `:` by default). Values can span multiple lines, as long as they are indented deeper @@ -1007,7 +1008,7 @@ lines may be treated as parts of multiline values or ignored. Configuration files may include comments, prefixed by specific - characters (`#' and `;' by default). Comments may appear on their own + characters (`#` and `;` by default). Comments may appear on their own in an otherwise empty line or may be entered in lines holding values or section names. Please note that comments get stripped off when reading configuration files. """ diff -Nru python3.10-3.10.7/Lib/cProfile.py python3.10-3.10.12/Lib/cProfile.py --- python3.10-3.10.7/Lib/cProfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/cProfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,7 @@ __all__ = ["run", "runctx", "Profile"] import _lsprof +import io import profile as _pyprofile # ____________________________________________________________ @@ -167,7 +168,7 @@ else: progname = args[0] sys.path.insert(0, os.path.dirname(progname)) - with open(progname, 'rb') as fp: + with io.open_code(progname) as fp: code = compile(fp.read(), progname, 'exec') globs = { '__file__': progname, diff -Nru python3.10-3.10.7/Lib/ctypes/test/test_parameters.py python3.10-3.10.12/Lib/ctypes/test/test_parameters.py --- python3.10-3.10.7/Lib/ctypes/test/test_parameters.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/ctypes/test/test_parameters.py 2023-06-06 22:30:33.000000000 +0000 @@ -244,6 +244,58 @@ self.assertRegex(repr(c_wchar_p.from_param('hihi')), r"^$") self.assertRegex(repr(c_void_p.from_param(0x12)), r"^$") + @test.support.cpython_only + def test_from_param_result_refcount(self): + # Issue #99952 + import _ctypes_test + from ctypes import PyDLL, c_int, c_void_p, py_object, Structure + + class X(Structure): + """This struct size is <= sizeof(void*).""" + _fields_ = [("a", c_void_p)] + + def __del__(self): + trace.append(4) + + @classmethod + def from_param(cls, value): + trace.append(2) + return cls() + + PyList_Append = PyDLL(_ctypes_test.__file__)._testfunc_pylist_append + PyList_Append.restype = c_int + PyList_Append.argtypes = [py_object, py_object, X] + + trace = [] + trace.append(1) + PyList_Append(trace, 3, "dummy") + trace.append(5) + + self.assertEqual(trace, [1, 2, 3, 4, 5]) + + class Y(Structure): + """This struct size is > sizeof(void*).""" + _fields_ = [("a", c_void_p), ("b", c_void_p)] + + def __del__(self): + trace.append(4) + + @classmethod + def from_param(cls, value): + trace.append(2) + return cls() + + PyList_Append = PyDLL(_ctypes_test.__file__)._testfunc_pylist_append + PyList_Append.restype = c_int + PyList_Append.argtypes = [py_object, py_object, Y] + + trace = [] + trace.append(1) + PyList_Append(trace, 3, "dummy") + trace.append(5) + + self.assertEqual(trace, [1, 2, 3, 4, 5]) + ################################################################ if __name__ == '__main__': diff -Nru python3.10-3.10.7/Lib/ctypes/test/test_pep3118.py python3.10-3.10.12/Lib/ctypes/test/test_pep3118.py --- python3.10-3.10.7/Lib/ctypes/test/test_pep3118.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/ctypes/test/test_pep3118.py 2023-06-06 22:30:33.000000000 +0000 @@ -176,7 +176,9 @@ ## arrays and pointers (c_double * 4, ": " + "(Phone) TypeError: " "expected bytes, int found") cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c")) self.assertEqual(cls, RuntimeError) self.assertEqual(msg, - "(Phone) : too many initializers") + "(Phone) TypeError: too many initializers") def test_huge_field_name(self): # issue12881: segfault with large structure field names diff -Nru python3.10-3.10.7/Lib/dataclasses.py python3.10-3.10.12/Lib/dataclasses.py --- python3.10-3.10.7/Lib/dataclasses.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/dataclasses.py 2023-06-06 22:30:33.000000000 +0000 @@ -222,6 +222,26 @@ # https://bugs.python.org/issue33453 for details. _MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') +# This function's logic is copied from "recursive_repr" function in +# reprlib module to avoid dependency. +def _recursive_repr(user_function): + # Decorator to make a repr function return "..." for a recursive + # call. + repr_running = set() + + @functools.wraps(user_function) + def wrapper(self): + key = id(self), _thread.get_ident() + if key in repr_running: + return '...' + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + return wrapper + class InitVar: __slots__ = ('type', ) @@ -279,6 +299,7 @@ self.kw_only = kw_only self._field_type = None + @_recursive_repr def __repr__(self): return ('Field(' f'name={self.name!r},' @@ -388,36 +409,13 @@ return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)' -# This function's logic is copied from "recursive_repr" function in -# reprlib module to avoid dependency. -def _recursive_repr(user_function): - # Decorator to make a repr function return "..." for a recursive - # call. - repr_running = set() - - @functools.wraps(user_function) - def wrapper(self): - key = id(self), _thread.get_ident() - if key in repr_running: - return '...' - repr_running.add(key) - try: - result = user_function(self) - finally: - repr_running.discard(key) - return result - return wrapper - - def _create_fn(name, args, body, *, globals=None, locals=None, return_type=MISSING): - # Note that we mutate locals when exec() is called. Caller - # beware! The only callers are internal to this module, so no + # Note that we may mutate locals. Callers beware! + # The only callers are internal to this module, so no # worries about external callers. if locals is None: locals = {} - if 'BUILTINS' not in locals: - locals['BUILTINS'] = builtins return_annotation = '' if return_type is not MISSING: locals['_return_type'] = return_type @@ -443,7 +441,7 @@ # self_name is what "self" is called in this function: don't # hard-code "self", since that might be a field name. if frozen: - return f'BUILTINS.object.__setattr__({self_name},{name!r},{value})' + return f'__dataclass_builtins_object__.__setattr__({self_name},{name!r},{value})' return f'{self_name}.{name}={value}' @@ -550,6 +548,7 @@ locals.update({ 'MISSING': MISSING, '_HAS_DEFAULT_FACTORY': _HAS_DEFAULT_FACTORY, + '__dataclass_builtins_object__': object, }) body_lines = [] @@ -1196,7 +1195,7 @@ try: fields = getattr(class_or_instance, _FIELDS) except AttributeError: - raise TypeError('must be called with a dataclass type or instance') + raise TypeError('must be called with a dataclass type or instance') from None # Exclude pseudo-fields. Note that fields is sorted by insertion # order, so the order of the tuple is as the fields were defined. diff -Nru python3.10-3.10.7/Lib/email/mime/application.py python3.10-3.10.12/Lib/email/mime/application.py --- python3.10-3.10.7/Lib/email/mime/application.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/email/mime/application.py 2023-06-06 22:30:33.000000000 +0000 @@ -17,7 +17,7 @@ _encoder=encoders.encode_base64, *, policy=None, **_params): """Create an application/* type MIME document. - _data is a string containing the raw application data. + _data contains the bytes for the raw application data. _subtype is the MIME content type subtype, defaulting to 'octet-stream'. diff -Nru python3.10-3.10.7/Lib/email/mime/audio.py python3.10-3.10.12/Lib/email/mime/audio.py --- python3.10-3.10.7/Lib/email/mime/audio.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/email/mime/audio.py 2023-06-06 22:30:33.000000000 +0000 @@ -46,7 +46,7 @@ _encoder=encoders.encode_base64, *, policy=None, **_params): """Create an audio/* type MIME document. - _audiodata is a string containing the raw audio data. If this data + _audiodata contains the bytes for the raw audio data. If this data can be decoded by the standard Python `sndhdr' module, then the subtype will be automatically included in the Content-Type header. Otherwise, you can specify the specific audio subtype via the diff -Nru python3.10-3.10.7/Lib/email/mime/image.py python3.10-3.10.12/Lib/email/mime/image.py --- python3.10-3.10.7/Lib/email/mime/image.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/email/mime/image.py 2023-06-06 22:30:33.000000000 +0000 @@ -20,7 +20,7 @@ _encoder=encoders.encode_base64, *, policy=None, **_params): """Create an image/* type MIME document. - _imagedata is a string containing the raw image data. If this data + _imagedata contains the bytes for the raw image data. If the data can be decoded by the standard Python `imghdr' module, then the subtype will be automatically included in the Content-Type header. Otherwise, you can specify the specific image subtype via the _subtype diff -Nru python3.10-3.10.7/Lib/encodings/idna.py python3.10-3.10.12/Lib/encodings/idna.py --- python3.10-3.10.7/Lib/encodings/idna.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/encodings/idna.py 2023-06-06 22:30:33.000000000 +0000 @@ -39,23 +39,21 @@ # Check bidi RandAL = [stringprep.in_table_d1(x) for x in label] - for c in RandAL: - if c: - # There is a RandAL char in the string. Must perform further - # tests: - # 1) The characters in section 5.8 MUST be prohibited. - # This is table C.8, which was already checked - # 2) If a string contains any RandALCat character, the string - # MUST NOT contain any LCat character. - if any(stringprep.in_table_d2(x) for x in label): - raise UnicodeError("Violation of BIDI requirement 2") - - # 3) If a string contains any RandALCat character, a - # RandALCat character MUST be the first character of the - # string, and a RandALCat character MUST be the last - # character of the string. - if not RandAL[0] or not RandAL[-1]: - raise UnicodeError("Violation of BIDI requirement 3") + if any(RandAL): + # There is a RandAL char in the string. Must perform further + # tests: + # 1) The characters in section 5.8 MUST be prohibited. + # This is table C.8, which was already checked + # 2) If a string contains any RandALCat character, the string + # MUST NOT contain any LCat character. + if any(stringprep.in_table_d2(x) for x in label): + raise UnicodeError("Violation of BIDI requirement 2") + # 3) If a string contains any RandALCat character, a + # RandALCat character MUST be the first character of the + # string, and a RandALCat character MUST be the last + # character of the string. + if not RandAL[0] or not RandAL[-1]: + raise UnicodeError("Violation of BIDI requirement 3") return label Binary files /tmp/tmp6obe659n/GM3bjMz8ne/python3.10-3.10.7/Lib/ensurepip/_bundled/pip-22.2.2-py3-none-any.whl and /tmp/tmp6obe659n/sXiciXjoWW/python3.10-3.10.12/Lib/ensurepip/_bundled/pip-22.2.2-py3-none-any.whl differ Binary files /tmp/tmp6obe659n/GM3bjMz8ne/python3.10-3.10.7/Lib/ensurepip/_bundled/pip-23.0.1-py3-none-any.whl and /tmp/tmp6obe659n/sXiciXjoWW/python3.10-3.10.12/Lib/ensurepip/_bundled/pip-23.0.1-py3-none-any.whl differ Binary files /tmp/tmp6obe659n/GM3bjMz8ne/python3.10-3.10.7/Lib/ensurepip/_bundled/setuptools-63.2.0-py3-none-any.whl and /tmp/tmp6obe659n/sXiciXjoWW/python3.10-3.10.12/Lib/ensurepip/_bundled/setuptools-63.2.0-py3-none-any.whl differ Binary files /tmp/tmp6obe659n/GM3bjMz8ne/python3.10-3.10.7/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl and /tmp/tmp6obe659n/sXiciXjoWW/python3.10-3.10.12/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl differ diff -Nru python3.10-3.10.7/Lib/ensurepip/__init__.py python3.10-3.10.12/Lib/ensurepip/__init__.py --- python3.10-3.10.7/Lib/ensurepip/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/ensurepip/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -11,8 +11,8 @@ __all__ = ["version", "bootstrap"] _PACKAGE_NAMES = ('setuptools', 'pip') -_SETUPTOOLS_VERSION = "63.2.0" -_PIP_VERSION = "22.2.2" +_SETUPTOOLS_VERSION = "65.5.0" +_PIP_VERSION = "23.0.1" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), ("pip", _PIP_VERSION, "py3"), diff -Nru python3.10-3.10.7/Lib/fileinput.py python3.10-3.10.12/Lib/fileinput.py --- python3.10-3.10.7/Lib/fileinput.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/fileinput.py 2023-06-06 22:30:33.000000000 +0000 @@ -419,7 +419,7 @@ def hook_compressed(filename, mode, *, encoding=None, errors=None): - if encoding is None: # EncodingWarning is emitted in FileInput() already. + if encoding is None and "b" not in mode: # EncodingWarning is emitted in FileInput() already. encoding = "locale" ext = os.path.splitext(filename)[1] if ext == '.gz': diff -Nru python3.10-3.10.7/Lib/html/__init__.py python3.10-3.10.12/Lib/html/__init__.py --- python3.10-3.10.7/Lib/html/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/html/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -25,7 +25,7 @@ return s -# see http://www.w3.org/TR/html5/syntax.html#tokenizing-character-references +# see https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state _invalid_charrefs = { 0x00: '\ufffd', # REPLACEMENT CHARACTER diff -Nru python3.10-3.10.7/Lib/http/client.py python3.10-3.10.12/Lib/http/client.py --- python3.10-3.10.7/Lib/http/client.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/http/client.py 2023-06-06 22:30:33.000000000 +0000 @@ -448,6 +448,7 @@ return self.fp is None def read(self, amt=None): + """Read and return the response body, or up to the next amt bytes.""" if self.fp is None: return b"" diff -Nru python3.10-3.10.7/Lib/http/cookiejar.py python3.10-3.10.12/Lib/http/cookiejar.py --- python3.10-3.10.7/Lib/http/cookiejar.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/http/cookiejar.py 2023-06-06 22:30:33.000000000 +0000 @@ -1990,7 +1990,7 @@ This class differs from CookieJar only in the format it uses to save and load cookies to and from a file. This class uses the Mozilla/Netscape - `cookies.txt' format. lynx uses this file format, too. + `cookies.txt' format. curl and lynx use this file format, too. Don't expect cookies saved while the browser is running to be noticed by the browser (in fact, Mozilla on unix will overwrite your saved cookies if diff -Nru python3.10-3.10.7/Lib/http/server.py python3.10-3.10.12/Lib/http/server.py --- python3.10-3.10.7/Lib/http/server.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/http/server.py 2023-06-06 22:30:33.000000000 +0000 @@ -93,6 +93,7 @@ import html import http.client import io +import itertools import mimetypes import os import posixpath @@ -563,6 +564,11 @@ self.log_message(format, *args) + # https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes + _control_char_table = str.maketrans( + {c: fr'\x{c:02x}' for c in itertools.chain(range(0x20), range(0x7f,0xa0))}) + _control_char_table[ord('\\')] = r'\\' + def log_message(self, format, *args): """Log an arbitrary message. @@ -578,12 +584,16 @@ The client ip and current date/time are prefixed to every message. + Unicode control characters are replaced with escaped hex + before writing the output to stderr. + """ + message = format % args sys.stderr.write("%s - - [%s] %s\n" % (self.address_string(), self.log_date_time_string(), - format%args)) + message.translate(self._control_char_table))) def version_string(self): """Return the server software version string.""" @@ -699,7 +709,7 @@ return None for index in "index.html", "index.htm": index = os.path.join(path, index) - if os.path.exists(index): + if os.path.isfile(index): path = index break else: @@ -781,7 +791,7 @@ displaypath = urllib.parse.unquote(self.path, errors='surrogatepass') except UnicodeDecodeError: - displaypath = urllib.parse.unquote(path) + displaypath = urllib.parse.unquote(self.path) displaypath = html.escape(displaypath, quote=False) enc = sys.getfilesystemencoding() title = 'Directory listing for %s' % displaypath diff -Nru python3.10-3.10.7/Lib/idlelib/configdialog.py python3.10-3.10.12/Lib/idlelib/configdialog.py --- python3.10-3.10.7/Lib/idlelib/configdialog.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/configdialog.py 2023-06-06 22:30:33.000000000 +0000 @@ -24,7 +24,7 @@ from tkinter import messagebox from idlelib.config import idleConf, ConfigChanges -from idlelib.config_key import GetKeysDialog +from idlelib.config_key import GetKeysWindow from idlelib.dynoption import DynOptionMenu from idlelib import macosx from idlelib.query import SectionName, HelpSource @@ -1397,7 +1397,7 @@ for event in key_set_changes: current_bindings[event] = key_set_changes[event].split() current_key_sequences = list(current_bindings.values()) - new_keys = GetKeysDialog(self, 'Get New Keys', bind_name, + new_keys = GetKeysWindow(self, 'Get New Keys', bind_name, current_key_sequences).result if new_keys: if self.keyset_source.get(): # Current key set is a built-in. diff -Nru python3.10-3.10.7/Lib/idlelib/config_key.py python3.10-3.10.12/Lib/idlelib/config_key.py --- python3.10-3.10.7/Lib/idlelib/config_key.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/config_key.py 2023-06-06 22:30:33.000000000 +0000 @@ -41,32 +41,22 @@ return f'Key-{key}' -class GetKeysDialog(Toplevel): +class GetKeysFrame(Frame): # Dialog title for invalid key sequence keyerror_title = 'Key Sequence Error' - def __init__(self, parent, title, action, current_key_sequences, - *, _htest=False, _utest=False): + def __init__(self, parent, action, current_key_sequences): """ parent - parent of this dialog - title - string which is the title of the popup dialog - action - string, the name of the virtual event these keys will be + action - the name of the virtual event these keys will be mapped to - current_key_sequences - list, a list of all key sequence lists + current_key_sequences - a list of all key sequence lists currently mapped to virtual events, for overlap checking - _htest - bool, change box location when running htest - _utest - bool, do not wait when running unittest """ - Toplevel.__init__(self, parent) - self.withdraw() # Hide while setting geometry. - self.configure(borderwidth=5) - self.resizable(height=False, width=False) - self.title(title) - self.transient(parent) - _setup_dialog(self) - self.grab_set() - self.protocol("WM_DELETE_WINDOW", self.cancel) + super().__init__(parent) + self['borderwidth'] = 2 + self['relief'] = 'sunken' self.parent = parent self.action = action self.current_key_sequences = current_key_sequences @@ -82,39 +72,14 @@ self.modifier_vars.append(variable) self.advanced = False self.create_widgets() - self.update_idletasks() - self.geometry( - "+%d+%d" % ( - parent.winfo_rootx() + - (parent.winfo_width()/2 - self.winfo_reqwidth()/2), - parent.winfo_rooty() + - ((parent.winfo_height()/2 - self.winfo_reqheight()/2) - if not _htest else 150) - ) ) # Center dialog over parent (or below htest box). - if not _utest: - self.deiconify() # Geometry set, unhide. - self.wait_window() def showerror(self, *args, **kwargs): # Make testing easier. Replace in #30751. messagebox.showerror(*args, **kwargs) def create_widgets(self): - self.frame = frame = Frame(self, borderwidth=2, relief='sunken') - frame.pack(side='top', expand=True, fill='both') - - frame_buttons = Frame(self) - frame_buttons.pack(side='bottom', fill='x') - - self.button_ok = Button(frame_buttons, text='OK', - width=8, command=self.ok) - self.button_ok.grid(row=0, column=0, padx=5, pady=5) - self.button_cancel = Button(frame_buttons, text='Cancel', - width=8, command=self.cancel) - self.button_cancel.grid(row=0, column=1, padx=5, pady=5) - # Basic entry key sequence. - self.frame_keyseq_basic = Frame(frame, name='keyseq_basic') + self.frame_keyseq_basic = Frame(self, name='keyseq_basic') self.frame_keyseq_basic.grid(row=0, column=0, sticky='nsew', padx=5, pady=5) basic_title = Label(self.frame_keyseq_basic, @@ -127,7 +92,7 @@ basic_keys.pack(ipadx=5, ipady=5, fill='x') # Basic entry controls. - self.frame_controls_basic = Frame(frame) + self.frame_controls_basic = Frame(self) self.frame_controls_basic.grid(row=1, column=0, sticky='nsew', padx=5) # Basic entry modifiers. @@ -169,7 +134,7 @@ self.button_clear.grid(row=2, column=0, columnspan=4) # Advanced entry key sequence. - self.frame_keyseq_advanced = Frame(frame, name='keyseq_advanced') + self.frame_keyseq_advanced = Frame(self, name='keyseq_advanced') self.frame_keyseq_advanced.grid(row=0, column=0, sticky='nsew', padx=5, pady=5) advanced_title = Label(self.frame_keyseq_advanced, justify='left', @@ -181,7 +146,7 @@ self.advanced_keys.pack(fill='x') # Advanced entry help text. - self.frame_help_advanced = Frame(frame) + self.frame_help_advanced = Frame(self) self.frame_help_advanced.grid(row=1, column=0, sticky='nsew', padx=5) help_advanced = Label(self.frame_help_advanced, justify='left', text="Key bindings are specified using Tkinter keysyms as\n"+ @@ -196,7 +161,7 @@ help_advanced.grid(row=0, column=0, sticky='nsew') # Switch between basic and advanced. - self.button_level = Button(frame, command=self.toggle_level, + self.button_level = Button(self, command=self.toggle_level, text='<< Basic Key Binding Entry') self.button_level.grid(row=2, column=0, stick='ew', padx=5, pady=5) self.toggle_level() @@ -257,7 +222,8 @@ variable.set('') self.key_string.set('') - def ok(self, event=None): + def ok(self): + self.result = '' keys = self.key_string.get().strip() if not keys: self.showerror(title=self.keyerror_title, parent=self, @@ -265,13 +231,7 @@ return if (self.advanced or self.keys_ok(keys)) and self.bind_ok(keys): self.result = keys - self.grab_release() - self.destroy() - - def cancel(self, event=None): - self.result = '' - self.grab_release() - self.destroy() + return def keys_ok(self, keys): """Validity check on user's 'basic' keybinding selection. @@ -319,6 +279,73 @@ return True +class GetKeysWindow(Toplevel): + + def __init__(self, parent, title, action, current_key_sequences, + *, _htest=False, _utest=False): + """ + parent - parent of this dialog + title - string which is the title of the popup dialog + action - string, the name of the virtual event these keys will be + mapped to + current_key_sequences - list, a list of all key sequence lists + currently mapped to virtual events, for overlap checking + _htest - bool, change box location when running htest + _utest - bool, do not wait when running unittest + """ + super().__init__(parent) + self.withdraw() # Hide while setting geometry. + self['borderwidth'] = 5 + self.resizable(height=False, width=False) + # Needed for winfo_reqwidth(). + self.update_idletasks() + # Center dialog over parent (or below htest box). + x = (parent.winfo_rootx() + + (parent.winfo_width()//2 - self.winfo_reqwidth()//2)) + y = (parent.winfo_rooty() + + ((parent.winfo_height()//2 - self.winfo_reqheight()//2) + if not _htest else 150)) + self.geometry(f"+{x}+{y}") + + self.title(title) + self.frame = frame = GetKeysFrame(self, action, current_key_sequences) + self.protocol("WM_DELETE_WINDOW", self.cancel) + frame_buttons = Frame(self) + self.button_ok = Button(frame_buttons, text='OK', + width=8, command=self.ok) + self.button_cancel = Button(frame_buttons, text='Cancel', + width=8, command=self.cancel) + self.button_ok.grid(row=0, column=0, padx=5, pady=5) + self.button_cancel.grid(row=0, column=1, padx=5, pady=5) + frame.pack(side='top', expand=True, fill='both') + frame_buttons.pack(side='bottom', fill='x') + + self.transient(parent) + _setup_dialog(self) + self.grab_set() + if not _utest: + self.deiconify() # Geometry set, unhide. + self.wait_window() + + @property + def result(self): + return self.frame.result + + @result.setter + def result(self, value): + self.frame.result = value + + def ok(self, event=None): + self.frame.ok() + self.grab_release() + self.destroy() + + def cancel(self, event=None): + self.result = '' + self.grab_release() + self.destroy() + + if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_config_key', verbosity=2, exit=False) diff -Nru python3.10-3.10.7/Lib/idlelib/dynoption.py python3.10-3.10.12/Lib/idlelib/dynoption.py --- python3.10-3.10.7/Lib/idlelib/dynoption.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/dynoption.py 2023-06-06 22:30:33.000000000 +0000 @@ -2,24 +2,19 @@ OptionMenu widget modified to allow dynamic menu reconfiguration and setting of highlightthickness """ -import copy - from tkinter import OptionMenu, _setit, StringVar, Button class DynOptionMenu(OptionMenu): - """ - unlike OptionMenu, our kwargs can include highlightthickness + """Add SetMenu and highlightthickness to OptionMenu. + + Highlightthickness adds space around menu button. """ def __init__(self, master, variable, value, *values, **kwargs): - # TODO copy value instead of whole dict - kwargsCopy=copy.copy(kwargs) - if 'highlightthickness' in list(kwargs.keys()): - del(kwargs['highlightthickness']) + highlightthickness = kwargs.pop('highlightthickness', None) OptionMenu.__init__(self, master, variable, value, *values, **kwargs) - self.config(highlightthickness=kwargsCopy.get('highlightthickness')) - #self.menu=self['menu'] - self.variable=variable - self.command=kwargs.get('command') + self['highlightthickness'] = highlightthickness + self.variable = variable + self.command = kwargs.get('command') def SetMenu(self,valueList,value=None): """ @@ -38,14 +33,15 @@ from tkinter import Toplevel # + StringVar, Button top = Toplevel(parent) - top.title("Tets dynamic option menu") + top.title("Test dynamic option menu") x, y = map(int, parent.geometry().split('+')[1:]) top.geometry("200x100+%d+%d" % (x + 250, y + 175)) top.focus_set() var = StringVar(top) var.set("Old option set") #Set the default value - dyn = DynOptionMenu(top,var, "old1","old2","old3","old4") + dyn = DynOptionMenu(top, var, "old1","old2","old3","old4", + highlightthickness=5) dyn.pack() def update(): @@ -54,5 +50,6 @@ button.pack() if __name__ == '__main__': + # Only module without unittests because of intention to replace. from idlelib.idle_test.htest import run run(_dyn_option_menu) diff -Nru python3.10-3.10.7/Lib/idlelib/idle_test/test_browser.py python3.10-3.10.12/Lib/idlelib/idle_test/test_browser.py --- python3.10-3.10.7/Lib/idlelib/idle_test/test_browser.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/idle_test/test_browser.py 2023-06-06 22:30:33.000000000 +0000 @@ -170,8 +170,7 @@ with mock.patch('os.path.exists', return_value=True): mbt.OnDoubleClick() - fopen.assert_called() - fopen.called_with(fname) + fopen.assert_called_once_with(fname) class ChildBrowserTreeItemTest(unittest.TestCase): diff -Nru python3.10-3.10.7/Lib/idlelib/idle_test/test_configdialog.py python3.10-3.10.12/Lib/idlelib/idle_test/test_configdialog.py --- python3.10-3.10.7/Lib/idlelib/idle_test/test_configdialog.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/idle_test/test_configdialog.py 2023-06-06 22:30:33.000000000 +0000 @@ -954,8 +954,8 @@ def test_get_new_keys(self): eq = self.assertEqual d = self.page - orig_getkeysdialog = configdialog.GetKeysDialog - gkd = configdialog.GetKeysDialog = Func(return_self=True) + orig_getkeysdialog = configdialog.GetKeysWindow + gkd = configdialog.GetKeysWindow = Func(return_self=True) gnkn = d.get_new_keys_name = Func() d.button_new_keys.state(('!disabled',)) @@ -997,7 +997,7 @@ eq(d.keybinding.get(), '') del d.get_new_keys_name - configdialog.GetKeysDialog = orig_getkeysdialog + configdialog.GetKeysWindow = orig_getkeysdialog def test_get_new_keys_name(self): orig_sectionname = configdialog.SectionName diff -Nru python3.10-3.10.7/Lib/idlelib/idle_test/test_config_key.py python3.10-3.10.12/Lib/idlelib/idle_test/test_config_key.py --- python3.10-3.10.7/Lib/idlelib/idle_test/test_config_key.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/idle_test/test_config_key.py 2023-06-06 22:30:33.000000000 +0000 @@ -13,15 +13,13 @@ from idlelib.idle_test.mock_idle import Func from idlelib.idle_test.mock_tk import Mbox_func -gkd = config_key.GetKeysDialog - class ValidationTest(unittest.TestCase): "Test validation methods: ok, keys_ok, bind_ok." - class Validator(gkd): + class Validator(config_key.GetKeysFrame): def __init__(self, *args, **kwargs): - config_key.GetKeysDialog.__init__(self, *args, **kwargs) + super().__init__(*args, **kwargs) class list_keys_final: get = Func() self.list_keys_final = list_keys_final @@ -34,15 +32,14 @@ cls.root = Tk() cls.root.withdraw() keylist = [[''], ['', '']] - cls.dialog = cls.Validator( - cls.root, 'Title', '<>', keylist, _utest=True) + cls.dialog = cls.Validator(cls.root, '<>', keylist) @classmethod def tearDownClass(cls): - cls.dialog.cancel() + del cls.dialog cls.root.update_idletasks() cls.root.destroy() - del cls.dialog, cls.root + del cls.root def setUp(self): self.dialog.showerror.message = '' @@ -111,14 +108,14 @@ requires('gui') cls.root = Tk() cls.root.withdraw() - cls.dialog = gkd(cls.root, 'Title', '<>', [], _utest=True) + cls.dialog = config_key.GetKeysFrame(cls.root, '<>', []) @classmethod def tearDownClass(cls): - cls.dialog.cancel() + del cls.dialog cls.root.update_idletasks() cls.root.destroy() - del cls.dialog, cls.root + del cls.root def test_toggle_level(self): dialog = self.dialog @@ -130,7 +127,7 @@ this can be used to check whether a frame is above or below another one. """ - for index, child in enumerate(dialog.frame.winfo_children()): + for index, child in enumerate(dialog.winfo_children()): if child._name == 'keyseq_basic': basic = index if child._name == 'keyseq_advanced': @@ -161,7 +158,7 @@ class KeySelectionTest(unittest.TestCase): "Test selecting key on Basic frames." - class Basic(gkd): + class Basic(config_key.GetKeysFrame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) class list_keys_final: @@ -179,14 +176,14 @@ requires('gui') cls.root = Tk() cls.root.withdraw() - cls.dialog = cls.Basic(cls.root, 'Title', '<>', [], _utest=True) + cls.dialog = cls.Basic(cls.root, '<>', []) @classmethod def tearDownClass(cls): - cls.dialog.cancel() + del cls.dialog cls.root.update_idletasks() cls.root.destroy() - del cls.dialog, cls.root + del cls.root def setUp(self): self.dialog.clear_key_seq() @@ -206,7 +203,7 @@ dialog.modifier_checkbuttons['foo'].invoke() eq(gm(), ['BAZ']) - @mock.patch.object(gkd, 'get_modifiers') + @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') def test_build_key_string(self, mock_modifiers): dialog = self.dialog key = dialog.list_keys_final @@ -227,7 +224,7 @@ dialog.build_key_string() eq(string(), '') - @mock.patch.object(gkd, 'get_modifiers') + @mock.patch.object(config_key.GetKeysFrame, 'get_modifiers') def test_final_key_selected(self, mock_modifiers): dialog = self.dialog key = dialog.list_keys_final @@ -240,7 +237,7 @@ eq(string(), '') -class CancelTest(unittest.TestCase): +class CancelWindowTest(unittest.TestCase): "Simulate user clicking [Cancel] button." @classmethod @@ -248,21 +245,89 @@ requires('gui') cls.root = Tk() cls.root.withdraw() - cls.dialog = gkd(cls.root, 'Title', '<>', [], _utest=True) + cls.dialog = config_key.GetKeysWindow( + cls.root, 'Title', '<>', [], _utest=True) @classmethod def tearDownClass(cls): cls.dialog.cancel() + del cls.dialog cls.root.update_idletasks() cls.root.destroy() - del cls.dialog, cls.root + del cls.root - def test_cancel(self): + @mock.patch.object(config_key.GetKeysFrame, 'ok') + def test_cancel(self, mock_frame_ok): self.assertEqual(self.dialog.winfo_class(), 'Toplevel') self.dialog.button_cancel.invoke() with self.assertRaises(TclError): self.dialog.winfo_class() self.assertEqual(self.dialog.result, '') + mock_frame_ok.assert_not_called() + + +class OKWindowTest(unittest.TestCase): + "Simulate user clicking [OK] button." + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + cls.dialog = config_key.GetKeysWindow( + cls.root, 'Title', '<>', [], _utest=True) + + @classmethod + def tearDownClass(cls): + cls.dialog.cancel() + del cls.dialog + cls.root.update_idletasks() + cls.root.destroy() + del cls.root + + @mock.patch.object(config_key.GetKeysFrame, 'ok') + def test_ok(self, mock_frame_ok): + self.assertEqual(self.dialog.winfo_class(), 'Toplevel') + self.dialog.button_ok.invoke() + with self.assertRaises(TclError): + self.dialog.winfo_class() + mock_frame_ok.assert_called() + + +class WindowResultTest(unittest.TestCase): + "Test window result get and set." + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + cls.dialog = config_key.GetKeysWindow( + cls.root, 'Title', '<>', [], _utest=True) + + @classmethod + def tearDownClass(cls): + cls.dialog.cancel() + del cls.dialog + cls.root.update_idletasks() + cls.root.destroy() + del cls.root + + def test_result(self): + dialog = self.dialog + eq = self.assertEqual + + dialog.result = '' + eq(dialog.result, '') + eq(dialog.frame.result,'') + + dialog.result = 'bar' + eq(dialog.result,'bar') + eq(dialog.frame.result,'bar') + + dialog.frame.result = 'foo' + eq(dialog.result, 'foo') + eq(dialog.frame.result,'foo') class HelperTest(unittest.TestCase): diff -Nru python3.10-3.10.7/Lib/idlelib/idle_test/test_text.py python3.10-3.10.12/Lib/idlelib/idle_test/test_text.py --- python3.10-3.10.7/Lib/idlelib/idle_test/test_text.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/idle_test/test_text.py 2023-06-06 22:30:33.000000000 +0000 @@ -6,7 +6,7 @@ from test.support import requires from _tkinter import TclError -class TextTest(object): +class TextTest: "Define items common to both sets of tests." hw = 'hello\nworld' # Several tests insert this after initialization. diff -Nru python3.10-3.10.7/Lib/idlelib/idle_test/test_zzdummy.py python3.10-3.10.12/Lib/idlelib/idle_test/test_zzdummy.py --- python3.10-3.10.7/Lib/idlelib/idle_test/test_zzdummy.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/idle_test/test_zzdummy.py 2023-06-06 22:30:33.000000000 +0000 @@ -19,7 +19,7 @@ } code_sample = """\ -class C1(): +class C1: # Class comment. def __init__(self, a, b): self.a = a diff -Nru python3.10-3.10.7/Lib/idlelib/macosx.py python3.10-3.10.12/Lib/idlelib/macosx.py --- python3.10-3.10.7/Lib/idlelib/macosx.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/macosx.py 2023-06-06 22:30:33.000000000 +0000 @@ -14,12 +14,25 @@ _tk_type = None def _init_tk_type(): - """ - Initializes OS X Tk variant values for - isAquaTk(), isCarbonTk(), isCocoaTk(), and isXQuartz(). + """ Initialize _tk_type for isXyzTk functions. + + This function is only called once, when _tk_type is still None. """ global _tk_type if platform == 'darwin': + + # When running IDLE, GUI is present, test/* may not be. + # When running tests, test/* is present, GUI may not be. + # If not, guess most common. Does not matter for testing. + from idlelib.__init__ import testing + if testing: + from test.support import requires, ResourceDenied + try: + requires('gui') + except ResourceDenied: + _tk_type = "cocoa" + return + root = tkinter.Tk() ws = root.tk.call('tk', 'windowingsystem') if 'x11' in ws: @@ -33,6 +46,7 @@ root.destroy() else: _tk_type = "other" + return def isAquaTk(): """ diff -Nru python3.10-3.10.7/Lib/idlelib/NEWS.txt python3.10-3.10.12/Lib/idlelib/NEWS.txt --- python3.10-3.10.7/Lib/idlelib/NEWS.txt 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/idlelib/NEWS.txt 2023-06-06 22:30:33.000000000 +0000 @@ -4,6 +4,11 @@ ========================= +gh-97527: Fix a bug in the previous bugfix that caused IDLE to not +start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python +3.10.2288.0 installed without the Lib/test package. 3.11.0 was never +affected. + gh-65802: Document handling of extensions in Save As dialogs. gh-95191: Include prompts when saving Shell (interactive input/output). diff -Nru python3.10-3.10.7/Lib/importlib/metadata/_functools.py python3.10-3.10.12/Lib/importlib/metadata/_functools.py --- python3.10-3.10.7/Lib/importlib/metadata/_functools.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/importlib/metadata/_functools.py 2023-06-06 22:30:33.000000000 +0000 @@ -83,3 +83,22 @@ wrapper.cache_clear = lambda: None return wrapper + + +# From jaraco.functools 3.3 +def pass_none(func): + """ + Wrap func so it's not called if its first param is None + + >>> print_text = pass_none(print) + >>> print_text('text') + text + >>> print_text(None) + """ + + @functools.wraps(func) + def wrapper(param, *args, **kwargs): + if param is not None: + return func(param, *args, **kwargs) + + return wrapper diff -Nru python3.10-3.10.7/Lib/importlib/metadata/__init__.py python3.10-3.10.12/Lib/importlib/metadata/__init__.py --- python3.10-3.10.7/Lib/importlib/metadata/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/importlib/metadata/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -17,7 +17,7 @@ from . import _adapters, _meta from ._meta import PackageMetadata from ._collections import FreezableDefaultDict, Pair -from ._functools import method_cache +from ._functools import method_cache, pass_none from ._itertools import unique_everseen from ._meta import PackageMetadata, SimplePath @@ -938,13 +938,25 @@ normalized name from the file system path. """ stem = os.path.basename(str(self._path)) - return self._name_from_stem(stem) or super()._normalized_name + return ( + pass_none(Prepared.normalize)(self._name_from_stem(stem)) + or super()._normalized_name + ) - def _name_from_stem(self, stem): - name, ext = os.path.splitext(stem) + @staticmethod + def _name_from_stem(stem): + """ + >>> PathDistribution._name_from_stem('foo-3.0.egg-info') + 'foo' + >>> PathDistribution._name_from_stem('CherryPy-3.0.dist-info') + 'CherryPy' + >>> PathDistribution._name_from_stem('face.egg-info') + 'face' + """ + filename, ext = os.path.splitext(stem) if ext not in ('.dist-info', '.egg-info'): return - name, sep, rest = stem.partition('-') + name, sep, rest = filename.partition('-') return name diff -Nru python3.10-3.10.7/Lib/inspect.py python3.10-3.10.12/Lib/inspect.py --- python3.10-3.10.7/Lib/inspect.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/inspect.py 2023-06-06 22:30:33.000000000 +0000 @@ -1052,7 +1052,6 @@ self.started = False self.passline = False self.indecorator = False - self.decoratorhasargs = False self.last = 1 self.body_col0 = None @@ -1067,13 +1066,6 @@ self.islambda = True self.started = True self.passline = True # skip to the end of the line - elif token == "(": - if self.indecorator: - self.decoratorhasargs = True - elif token == ")": - if self.indecorator: - self.indecorator = False - self.decoratorhasargs = False elif type == tokenize.NEWLINE: self.passline = False # stop skipping when a NEWLINE is seen self.last = srowcol[0] @@ -1081,7 +1073,7 @@ raise EndOfBlock # hitting a NEWLINE when in a decorator without args # ends the decorator - if self.indecorator and not self.decoratorhasargs: + if self.indecorator: self.indecorator = False elif self.passline: pass @@ -1356,7 +1348,10 @@ def formatannotation(annotation, base_module=None): if getattr(annotation, '__module__', None) == 'typing': - return repr(annotation).replace('typing.', '') + def repl(match): + text = match.group() + return text.removeprefix('typing.') + return re.sub(r'[\w\.]+', repl, repr(annotation)) if isinstance(annotation, types.GenericAlias): return str(annotation) if isinstance(annotation, type): @@ -2066,7 +2061,7 @@ self_parameter = None last_positional_only = None - lines = [l.encode('ascii') for l in signature.split('\n')] + lines = [l.encode('ascii') for l in signature.split('\n') if l] generator = iter(lines).__next__ token_stream = tokenize.tokenize(generator) @@ -2146,7 +2141,6 @@ parameters = [] empty = Parameter.empty - invalid = object() module = None module_dict = {} @@ -2170,11 +2164,11 @@ try: value = eval(s, sys_module_dict) except NameError: - raise RuntimeError() + raise ValueError if isinstance(value, (str, int, float, bytes, bool, type(None))): return ast.Constant(value) - raise RuntimeError() + raise ValueError class RewriteSymbolics(ast.NodeTransformer): def visit_Attribute(self, node): @@ -2184,7 +2178,7 @@ a.append(n.attr) n = n.value if not isinstance(n, ast.Name): - raise RuntimeError() + raise ValueError a.append(n.id) value = ".".join(reversed(a)) return wrap_value(value) @@ -2194,19 +2188,29 @@ raise ValueError() return wrap_value(node.id) + def visit_BinOp(self, node): + # Support constant folding of a couple simple binary operations + # commonly used to define default values in text signatures + left = self.visit(node.left) + right = self.visit(node.right) + if not isinstance(left, ast.Constant) or not isinstance(right, ast.Constant): + raise ValueError + if isinstance(node.op, ast.Add): + return ast.Constant(left.value + right.value) + elif isinstance(node.op, ast.Sub): + return ast.Constant(left.value - right.value) + elif isinstance(node.op, ast.BitOr): + return ast.Constant(left.value | right.value) + raise ValueError + def p(name_node, default_node, default=empty): name = parse_name(name_node) - if name is invalid: - return None if default_node and default_node is not _empty: try: default_node = RewriteSymbolics().visit(default_node) - o = ast.literal_eval(default_node) + default = ast.literal_eval(default_node) except ValueError: - o = invalid - if o is invalid: - return None - default = o if o is not invalid else default + raise ValueError("{!r} builtin has invalid signature".format(obj)) from None parameters.append(Parameter(name, kind, default=default, annotation=empty)) # non-keyword-only parameters @@ -2403,7 +2407,10 @@ # Was this function wrapped by a decorator? if follow_wrapper_chains: - obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + # Unwrap until we find an explicit signature or a MethodType (which will be + # handled explicitly below). + obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__") + or isinstance(f, types.MethodType))) if isinstance(obj, types.MethodType): # If the unwrapped object is a *method*, we might want to # skip its first parameter (self). diff -Nru python3.10-3.10.7/Lib/json/decoder.py python3.10-3.10.12/Lib/json/decoder.py --- python3.10-3.10.7/Lib/json/decoder.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/json/decoder.py 2023-06-06 22:30:33.000000000 +0000 @@ -252,7 +252,7 @@ class JSONDecoder(object): - """Simple JSON decoder + """Simple JSON decoder Performs the following translations in decoding by default: diff -Nru python3.10-3.10.7/Lib/json/encoder.py python3.10-3.10.12/Lib/json/encoder.py --- python3.10-3.10.7/Lib/json/encoder.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/json/encoder.py 2023-06-06 22:30:33.000000000 +0000 @@ -71,7 +71,7 @@ c_encode_basestring_ascii or py_encode_basestring_ascii) class JSONEncoder(object): - """Extensible JSON encoder for Python data structures. + """Extensible JSON encoder for Python data structures. Supports the following objects and types by default: diff -Nru python3.10-3.10.7/Lib/json/__init__.py python3.10-3.10.12/Lib/json/__init__.py --- python3.10-3.10.7/Lib/json/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/json/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,4 +1,4 @@ -r"""JSON (JavaScript Object Notation) is a subset of +r"""JSON (JavaScript Object Notation) is a subset of JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data interchange format. diff -Nru python3.10-3.10.7/Lib/logging/__init__.py python3.10-3.10.12/Lib/logging/__init__.py --- python3.10-3.10.7/Lib/logging/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/logging/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -487,7 +487,7 @@ def usesTime(self): fmt = self._fmt - return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0 + return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_search) >= 0 def validate(self): pattern = Template.pattern diff -Nru python3.10-3.10.7/Lib/mailcap.py python3.10-3.10.12/Lib/mailcap.py --- python3.10-3.10.7/Lib/mailcap.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/mailcap.py 2023-06-06 22:30:33.000000000 +0000 @@ -2,6 +2,7 @@ import os import warnings +import re __all__ = ["getcaps","findmatch"] @@ -13,6 +14,11 @@ else: return 1, 0 +_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search + +class UnsafeMailcapInput(Warning): + """Warning raised when refusing unsafe input""" + # Part 1: top-level interface. @@ -165,15 +171,22 @@ entry to use. """ + if _find_unsafe(filename): + msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,) + warnings.warn(msg, UnsafeMailcapInput) + return None, None entries = lookup(caps, MIMEtype, key) # XXX This code should somehow check for the needsterminal flag. for e in entries: if 'test' in e: test = subst(e['test'], filename, plist) + if test is None: + continue if test and os.system(test) != 0: continue command = subst(e[key], MIMEtype, filename, plist) - return command, e + if command is not None: + return command, e return None, None def lookup(caps, MIMEtype, key=None): @@ -206,6 +219,10 @@ elif c == 's': res = res + filename elif c == 't': + if _find_unsafe(MIMEtype): + msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,) + warnings.warn(msg, UnsafeMailcapInput) + return None res = res + MIMEtype elif c == '{': start = i @@ -213,7 +230,12 @@ i = i+1 name = field[start:i] i = i+1 - res = res + findparam(name, plist) + param = findparam(name, plist) + if _find_unsafe(param): + msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name) + warnings.warn(msg, UnsafeMailcapInput) + return None + res = res + param # XXX To do: # %n == number of parts if type is multipart/* # %F == list of alternating type and filename for parts diff -Nru python3.10-3.10.7/Lib/multiprocessing/connection.py python3.10-3.10.12/Lib/multiprocessing/connection.py --- python3.10-3.10.7/Lib/multiprocessing/connection.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/multiprocessing/connection.py 2023-06-06 22:30:33.000000000 +0000 @@ -73,11 +73,6 @@ if family == 'AF_INET': return ('localhost', 0) elif family == 'AF_UNIX': - # Prefer abstract sockets if possible to avoid problems with the address - # size. When coding portable applications, some implementations have - # sun_path as short as 92 bytes in the sockaddr_un struct. - if util.abstract_sockets_supported: - return f"\0listener-{os.getpid()}-{next(_mmap_counter)}" return tempfile.mktemp(prefix='listener-', dir=util.get_temp_dir()) elif family == 'AF_PIPE': return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' % diff -Nru python3.10-3.10.7/Lib/multiprocessing/resource_tracker.py python3.10-3.10.12/Lib/multiprocessing/resource_tracker.py --- python3.10-3.10.7/Lib/multiprocessing/resource_tracker.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/multiprocessing/resource_tracker.py 2023-06-06 22:30:33.000000000 +0000 @@ -161,10 +161,10 @@ def _send(self, cmd, name, rtype): self.ensure_running() msg = '{0}:{1}:{2}\n'.format(cmd, name, rtype).encode('ascii') - if len(name) > 512: + if len(msg) > 512: # posix guarantees that writes to a pipe of less than PIPE_BUF # bytes are atomic, and that PIPE_BUF >= 512 - raise ValueError('name too long') + raise ValueError('msg too long') nbytes = os.write(self._fd, msg) assert nbytes == len(msg), "nbytes {0:n} but len(msg) {1:n}".format( nbytes, len(msg)) diff -Nru python3.10-3.10.7/Lib/multiprocessing/shared_memory.py python3.10-3.10.12/Lib/multiprocessing/shared_memory.py --- python3.10-3.10.7/Lib/multiprocessing/shared_memory.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/multiprocessing/shared_memory.py 2023-06-06 22:30:33.000000000 +0000 @@ -173,7 +173,10 @@ ) finally: _winapi.CloseHandle(h_map) - size = _winapi.VirtualQuerySize(p_buf) + try: + size = _winapi.VirtualQuerySize(p_buf) + finally: + _winapi.UnmapViewOfFile(p_buf) self._mmap = mmap.mmap(-1, size, tagname=name) self._size = size diff -Nru python3.10-3.10.7/Lib/ntpath.py python3.10-3.10.12/Lib/ntpath.py --- python3.10-3.10.7/Lib/ntpath.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/ntpath.py 2023-06-06 22:30:33.000000000 +0000 @@ -625,12 +625,15 @@ # 21: ERROR_NOT_READY (implies drive with no media) # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file) # 50: ERROR_NOT_SUPPORTED + # 53: ERROR_BAD_NETPATH + # 65: ERROR_NETWORK_ACCESS_DENIED # 67: ERROR_BAD_NET_NAME (implies remote server unavailable) # 87: ERROR_INVALID_PARAMETER # 123: ERROR_INVALID_NAME + # 161: ERROR_BAD_PATHNAME # 1920: ERROR_CANT_ACCESS_FILE # 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink) - allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1920, 1921 + allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 53, 65, 67, 87, 123, 161, 1920, 1921 # Non-strict algorithm is to find as much of the target directory # as we can and join the rest. diff -Nru python3.10-3.10.7/Lib/os.py python3.10-3.10.12/Lib/os.py --- python3.10-3.10.7/Lib/os.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/os.py 2023-06-06 22:30:33.000000000 +0000 @@ -288,7 +288,8 @@ dirpath, dirnames, filenames dirpath is a string, the path to the directory. dirnames is a list of - the names of the subdirectories in dirpath (excluding '.' and '..'). + the names of the subdirectories in dirpath (including symlinks to directories, + and excluding '.' and '..'). filenames is a list of the names of the non-directory files in dirpath. Note that the names in the lists are just names, with no path components. To get a full path (which begins with top) to a file or directory in diff -Nru python3.10-3.10.7/Lib/pdb.py python3.10-3.10.12/Lib/pdb.py --- python3.10-3.10.7/Lib/pdb.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/pdb.py 2023-06-06 22:30:33.000000000 +0000 @@ -104,15 +104,6 @@ return funcname, filename, lineno return None -def getsourcelines(obj): - lines, lineno = inspect.findsource(obj) - if inspect.isframe(obj) and obj.f_globals is obj.f_locals: - # must be a module frame: do not try to cut a block out of it - return lines, 1 - elif inspect.ismodule(obj): - return lines, 1 - return inspect.getblock(lines[lineno:]), lineno+1 - def lasti2lineno(code, lasti): linestarts = list(dis.findlinestarts(code)) linestarts.reverse() @@ -1248,6 +1239,12 @@ if last is None: last = first + 10 filename = self.curframe.f_code.co_filename + # gh-93696: stdlib frozen modules provide a useful __file__ + # this workaround can be removed with the closure of gh-89815 + if filename.startswith("", someMoreData = b"" * 10, - aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())), + aDate = datetime.datetime.now() ) - with open(fileName, 'wb') as fp: - dump(pl, fp) + print(plistlib.dumps(pl).decode()) Parse Plist example: - with open(fileName, 'rb') as fp: - pl = load(fp) - print(pl["aKey"]) + import plistlib + + plist = b''' + + foo + bar + + ''' + pl = plistlib.loads(plist) + print(pl["foo"]) """ __all__ = [ "InvalidFileException", "FMT_XML", "FMT_BINARY", "load", "dump", "loads", "dumps", "UID" @@ -152,7 +161,7 @@ def _escape(text): m = _controlCharPat.search(text) if m is not None: - raise ValueError("strings can't contains control characters; " + raise ValueError("strings can't contain control characters; " "use bytes instead") text = text.replace("\r\n", "\n") # convert DOS line endings text = text.replace("\r", "\n") # convert Mac line endings diff -Nru python3.10-3.10.7/Lib/posixpath.py python3.10-3.10.12/Lib/posixpath.py --- python3.10-3.10.7/Lib/posixpath.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/posixpath.py 2023-06-06 22:30:33.000000000 +0000 @@ -195,6 +195,7 @@ if stat.S_ISLNK(s1.st_mode): return False + path = os.fspath(path) if isinstance(path, bytes): parent = join(path, b'..') else: diff -Nru python3.10-3.10.7/Lib/profile.py python3.10-3.10.12/Lib/profile.py --- python3.10-3.10.7/Lib/profile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/profile.py 2023-06-06 22:30:33.000000000 +0000 @@ -24,6 +24,7 @@ # governing permissions and limitations under the License. +import io import sys import time import marshal @@ -587,7 +588,7 @@ else: progname = args[0] sys.path.insert(0, os.path.dirname(progname)) - with open(progname, 'rb') as fp: + with io.open_code(progname) as fp: code = compile(fp.read(), progname, 'exec') globs = { '__file__': progname, diff -Nru python3.10-3.10.7/Lib/pstats.py python3.10-3.10.12/Lib/pstats.py --- python3.10-3.10.7/Lib/pstats.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/pstats.py 2023-06-06 22:30:33.000000000 +0000 @@ -56,7 +56,7 @@ @dataclass(unsafe_hash=True) class FunctionProfile: - ncalls: int + ncalls: str tottime: float percall_tottime: float cumtime: float diff -Nru python3.10-3.10.7/Lib/pydoc_data/topics.py python3.10-3.10.12/Lib/pydoc_data/topics.py --- python3.10-3.10.7/Lib/pydoc_data/topics.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/pydoc_data/topics.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Mon Sep 5 13:02:42 2022 +# Autogenerated by Sphinx on Tue Jun 6 23:30:19 2023 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -358,7 +358,7 @@ 'yield_expression)]\n' '\n' 'The difference from normal Assignment statements is that only ' - 'single\n' + 'a single\n' 'target is allowed.\n' '\n' 'For simple names as assignment targets, if in class or module ' @@ -408,12 +408,13 @@ 'analysis\n' ' tools and IDEs.\n' '\n' - 'Changed in version 3.8: Now annotated assignments allow same\n' - 'expressions in the right hand side as the regular ' - 'assignments.\n' - 'Previously, some expressions (like un-parenthesized tuple ' - 'expressions)\n' - 'caused a syntax error.\n', + 'Changed in version 3.8: Now annotated assignments allow the ' + 'same\n' + 'expressions in the right hand side as regular assignments. ' + 'Previously,\n' + 'some expressions (like un-parenthesized tuple expressions) ' + 'caused a\n' + 'syntax error.\n', 'async': 'Coroutines\n' '**********\n' '\n' @@ -1135,10 +1136,11 @@ 'future, a\n' ' check may be added to prevent this.\n' '\n' - '* Nonempty *__slots__* does not work for classes derived ' - 'from\n' - ' “variable-length” built-in types such as "int", ' - '"bytes" and "tuple".\n' + '* "TypeError" will be raised if nonempty *__slots__* are ' + 'defined for a\n' + ' class derived from a ""variable-length" built-in type" ' + 'such as\n' + ' "int", "bytes", and "tuple".\n' '\n' '* Any non-string *iterable* may be assigned to ' '*__slots__*.\n' @@ -1674,10 +1676,26 @@ 'If the syntax "**expression" appears in the function call,\n' '"expression" must evaluate to a *mapping*, the contents of which ' 'are\n' - 'treated as additional keyword arguments. If a keyword is already\n' - 'present (as an explicit keyword argument, or from another ' - 'unpacking),\n' - 'a "TypeError" exception is raised.\n' + 'treated as additional keyword arguments. If a parameter matching a ' + 'key\n' + 'has already been given a value (by an explicit keyword argument, ' + 'or\n' + 'from another unpacking), a "TypeError" exception is raised.\n' + '\n' + 'When "**expression" is used, each key in this mapping must be a\n' + 'string. Each value from the mapping is assigned to the first ' + 'formal\n' + 'parameter eligible for keyword assignment whose name is equal to ' + 'the\n' + 'key. A key need not be a Python identifier (e.g. ""max-temp °F"" ' + 'is\n' + 'acceptable, although it will not match any formal parameter that ' + 'could\n' + 'be declared). If there is no match to a formal parameter the ' + 'key-value\n' + 'pair is collected by the "**" parameter, if there is one, or if ' + 'there\n' + 'is not, a "TypeError" exception is raised.\n' '\n' 'Formal parameters using the syntax "*identifier" or "**identifier"\n' 'cannot be used as positional argument slots or as keyword argument\n' @@ -2025,7 +2043,7 @@ '\n' '* Mappings (instances of "dict") compare equal if and only if ' 'they\n' - ' have equal *(key, value)* pairs. Equality comparison of the ' + ' have equal "(key, value)" pairs. Equality comparison of the ' 'keys and\n' ' values enforces reflexivity.\n' '\n' @@ -2374,12 +2392,10 @@ 'finished,\n' 'but if the sequence is empty, they will not have been assigned ' 'to at\n' - 'all by the loop. Hint: the built-in function "range()" returns ' - 'an\n' - 'iterator of integers suitable to emulate the effect of Pascal’s ' - '"for i\n' - ':= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, ' - '2]".\n' + 'all by the loop. Hint: the built-in type "range()" represents\n' + 'immutable arithmetic sequences of integers. For instance, ' + 'iterating\n' + '"range(3)" successively yields 0, 1, and then 2.\n' '\n' '\n' 'The "try" statement\n' @@ -2627,7 +2643,7 @@ 'the\n' ' target list, it will be treated the same as an error ' 'occurring\n' - ' within the suite would be. See step 6 below.\n' + ' within the suite would be. See step 7 below.\n' '\n' '6. The suite is executed.\n' '\n' @@ -2984,7 +3000,7 @@ 'AS\n' 'pattern binds the subject to the name on the right of the as ' 'keyword\n' - 'and succeeds. "capture_pattern" cannot be a a "_".\n' + 'and succeeds. "capture_pattern" cannot be a "_".\n' '\n' 'In simple terms "P as NAME" will match with "P", and on success ' 'it\n' @@ -4436,7 +4452,7 @@ 'objects and\n' ' implements an "__eq__()" method, it should not ' 'implement\n' - ' "__hash__()", since the implementation of hashable ' + ' "__hash__()", since the implementation of *hashable* ' 'collections\n' ' requires that a key’s hash value is immutable (if the ' 'object’s hash\n' @@ -4550,6 +4566,18 @@ 'the source. The extension interface uses the modules "bdb" and ' '"cmd".\n' '\n' + 'See also:\n' + '\n' + ' Module "faulthandler"\n' + ' Used to dump Python tracebacks explicitly, on a fault, ' + 'after a\n' + ' timeout, or on a user signal.\n' + '\n' + ' Module "traceback"\n' + ' Standard interface to extract, format and print stack ' + 'traces of\n' + ' Python programs.\n' + '\n' 'The debugger’s prompt is "(Pdb)". Typical usage to run a program ' 'under\n' 'control of the debugger is:\n' @@ -4575,7 +4603,7 @@ 'scripts. For\n' 'example:\n' '\n' - ' python3 -m pdb myscript.py\n' + ' python -m pdb myscript.py\n' '\n' 'When invoked as a script, pdb will automatically enter ' 'post-mortem\n' @@ -4595,7 +4623,7 @@ '\n' 'New in version 3.7: "pdb.py" now accepts a "-m" option that ' 'execute\n' - 'modules similar to the way "python3 -m" does. As with a script, ' + 'modules similar to the way "python -m" does. As with a script, ' 'the\n' 'debugger will pause execution just before the first line of the\n' 'module.\n' @@ -4659,8 +4687,8 @@ 'object)\n' ' under debugger control. When "runeval()" returns, it returns ' 'the\n' - ' value of the expression. Otherwise this function is similar ' - 'to\n' + ' value of the *expression*. Otherwise this function is ' + 'similar to\n' ' "run()".\n' '\n' 'pdb.runcall(function, *args, **kwds)\n' @@ -4917,14 +4945,15 @@ 'ignore bpnumber [count]\n' '\n' ' Set the ignore count for the given breakpoint number. If ' - 'count is\n' - ' omitted, the ignore count is set to 0. A breakpoint becomes ' - 'active\n' - ' when the ignore count is zero. When non-zero, the count is\n' - ' decremented each time the breakpoint is reached and the ' - 'breakpoint\n' - ' is not disabled and any associated condition evaluates to ' - 'true.\n' + '*count*\n' + ' is omitted, the ignore count is set to 0. A breakpoint ' + 'becomes\n' + ' active when the ignore count is zero. When non-zero, the ' + '*count*\n' + ' is decremented each time the breakpoint is reached and the\n' + ' breakpoint is not disabled and any associated condition ' + 'evaluates\n' + ' to true.\n' '\n' 'condition bpnumber [condition]\n' '\n' @@ -4974,7 +5003,7 @@ ' breakpoint—which could have its own command list, leading to\n' ' ambiguities about which list to execute.\n' '\n' - ' If you use the ‘silent’ command in the command list, the ' + ' If you use the "silent" command in the command list, the ' 'usual\n' ' message about stopping at a breakpoint is not printed. This ' 'may be\n' @@ -5009,11 +5038,10 @@ 'number\n' ' greater than the current one is reached.\n' '\n' - ' With a line number, continue execution until a line with a ' - 'number\n' - ' greater or equal to that is reached. In both cases, also ' - 'stop when\n' - ' the current frame returns.\n' + ' With *lineno*, continue execution until a line with a number\n' + ' greater or equal to *lineno* is reached. In both cases, also ' + 'stop\n' + ' when the current frame returns.\n' '\n' ' Changed in version 3.2: Allow giving an explicit line ' 'number.\n' @@ -5077,9 +5105,8 @@ '\n' 'p expression\n' '\n' - ' Evaluate the *expression* in the current context and print ' - 'its\n' - ' value.\n' + ' Evaluate *expression* in the current context and print its ' + 'value.\n' '\n' ' Note:\n' '\n' @@ -5089,26 +5116,26 @@ '\n' 'pp expression\n' '\n' - ' Like the "p" command, except the value of the expression is ' + ' Like the "p" command, except the value of *expression* is ' 'pretty-\n' ' printed using the "pprint" module.\n' '\n' 'whatis expression\n' '\n' - ' Print the type of the *expression*.\n' + ' Print the type of *expression*.\n' '\n' 'source expression\n' '\n' - ' Try to get source code for the given object and display it.\n' + ' Try to get source code of *expression* and display it.\n' '\n' ' New in version 3.2.\n' '\n' 'display [expression]\n' '\n' - ' Display the value of the expression if it changed, each time\n' + ' Display the value of *expression* if it changed, each time\n' ' execution stops in the current frame.\n' '\n' - ' Without expression, list all display expressions for the ' + ' Without *expression*, list all display expressions for the ' 'current\n' ' frame.\n' '\n' @@ -5116,10 +5143,10 @@ '\n' 'undisplay [expression]\n' '\n' - ' Do not display the expression any more in the current frame.\n' - ' Without expression, clear all display expressions for the ' - 'current\n' - ' frame.\n' + ' Do not display *expression* anymore in the current frame. ' + 'Without\n' + ' *expression*, clear all display expressions for the current ' + 'frame.\n' '\n' ' New in version 3.2.\n' '\n' @@ -5135,16 +5162,16 @@ '\n' 'alias [name [command]]\n' '\n' - ' Create an alias called *name* that executes *command*. The ' - 'command\n' - ' must *not* be enclosed in quotes. Replaceable parameters can ' - 'be\n' - ' indicated by "%1", "%2", and so on, while "%*" is replaced by ' - 'all\n' - ' the parameters. If no command is given, the current alias ' - 'for\n' - ' *name* is shown. If no arguments are given, all aliases are ' - 'listed.\n' + ' Create an alias called *name* that executes *command*. The\n' + ' *command* must *not* be enclosed in quotes. Replaceable ' + 'parameters\n' + ' can be indicated by "%1", "%2", and so on, while "%*" is ' + 'replaced\n' + ' by all the parameters. If *command* is omitted, the current ' + 'alias\n' + ' for *name* is shown. If no arguments are given, all aliases ' + 'are\n' + ' listed.\n' '\n' ' Aliases may be nested and can contain anything that can be ' 'legally\n' @@ -5163,14 +5190,14 @@ ' in the ".pdbrc" file):\n' '\n' ' # Print instance variables (usage "pi classInst")\n' - ' alias pi for k in %1.__dict__.keys(): ' - 'print("%1.",k,"=",%1.__dict__[k])\n' + ' alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = ' + '{%1.__dict__[k]}")\n' ' # Print instance variables in self\n' ' alias ps pi self\n' '\n' 'unalias name\n' '\n' - ' Delete the specified alias.\n' + ' Delete the specified alias *name*.\n' '\n' '! statement\n' '\n' @@ -5190,12 +5217,13 @@ 'run [args ...]\n' 'restart [args ...]\n' '\n' - ' Restart the debugged Python program. If an argument is ' - 'supplied,\n' - ' it is split with "shlex" and the result is used as the new\n' - ' "sys.argv". History, breakpoints, actions and debugger ' - 'options are\n' - ' preserved. "restart" is an alias for "run".\n' + ' Restart the debugged Python program. If *args* is supplied, ' + 'it is\n' + ' split with "shlex" and the result is used as the new ' + '"sys.argv".\n' + ' History, breakpoints, actions and debugger options are ' + 'preserved.\n' + ' "restart" is an alias for "run".\n' '\n' 'q(uit)\n' '\n' @@ -5204,11 +5232,11 @@ '\n' 'debug code\n' '\n' - ' Enter a recursive debugger that steps through the code ' - 'argument\n' - ' (which is an arbitrary expression or statement to be executed ' - 'in\n' - ' the current environment).\n' + ' Enter a recursive debugger that steps through *code* (which ' + 'is an\n' + ' arbitrary expression or statement to be executed in the ' + 'current\n' + ' environment).\n' '\n' 'retval\n' '\n' @@ -5563,7 +5591,8 @@ 'be\n' 'determined by scanning the entire text of the block for name ' 'binding\n' - 'operations.\n' + 'operations. See the FAQ entry on UnboundLocalError for ' + 'examples.\n' '\n' 'If the "global" statement occurs within a block, all uses of ' 'the names\n' @@ -5871,10 +5900,9 @@ '\n' 'Names in the target list are not deleted when the loop is finished,\n' 'but if the sequence is empty, they will not have been assigned to at\n' - 'all by the loop. Hint: the built-in function "range()" returns an\n' - 'iterator of integers suitable to emulate the effect of Pascal’s "for ' - 'i\n' - ':= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n', + 'all by the loop. Hint: the built-in type "range()" represents\n' + 'immutable arithmetic sequences of integers. For instance, iterating\n' + '"range(3)" successively yields 0, 1, and then 2.\n', 'formatstrings': 'Format String Syntax\n' '********************\n' '\n' @@ -7209,7 +7237,7 @@ 'the clauses had been separated out into individual import ' 'statements.\n' '\n' - 'The details of the first step, finding and loading modules are\n' + 'The details of the first step, finding and loading modules, are\n' 'described in greater detail in the section on the import system, ' 'which\n' 'also describes the various types of packages and modules that can ' @@ -7670,7 +7698,7 @@ 'within a code block. The local variables of a code block can be\n' 'determined by scanning the entire text of the block for name ' 'binding\n' - 'operations.\n' + 'operations. See the FAQ entry on UnboundLocalError for examples.\n' '\n' 'If the "global" statement occurs within a block, all uses of the ' 'names\n' @@ -9320,7 +9348,7 @@ ' hashable collections. If a class defines mutable objects ' 'and\n' ' implements an "__eq__()" method, it should not implement\n' - ' "__hash__()", since the implementation of hashable ' + ' "__hash__()", since the implementation of *hashable* ' 'collections\n' ' requires that a key’s hash value is immutable (if the ' 'object’s hash\n' @@ -9858,10 +9886,11 @@ 'future, a\n' ' check may be added to prevent this.\n' '\n' - '* Nonempty *__slots__* does not work for classes derived ' - 'from\n' - ' “variable-length” built-in types such as "int", "bytes" ' - 'and "tuple".\n' + '* "TypeError" will be raised if nonempty *__slots__* are ' + 'defined for a\n' + ' class derived from a ""variable-length" built-in type" ' + 'such as\n' + ' "int", "bytes", and "tuple".\n' '\n' '* Any non-string *iterable* may be assigned to *__slots__*.\n' '\n' @@ -10983,8 +11012,9 @@ 'y)" is\n' 'typically invalid without special support in "MyClass". To ' 'be able to\n' - 'use that kind of patterns, the class needs to define a\n' - '*__match_args__* attribute.\n' + 'use that kind of pattern, the class needs to define a ' + '*__match_args__*\n' + 'attribute.\n' '\n' 'object.__match_args__\n' '\n' @@ -11189,37 +11219,41 @@ '*start* and\n' ' *end* are interpreted as in slice notation.\n' '\n' + ' If *sub* is empty, returns the number of empty strings ' + 'between\n' + ' characters which is the length of the string plus one.\n' + '\n' "str.encode(encoding='utf-8', errors='strict')\n" '\n' - ' Return an encoded version of the string as a bytes ' - 'object. Default\n' - ' encoding is "\'utf-8\'". *errors* may be given to set a ' - 'different\n' - ' error handling scheme. The default for *errors* is ' - '"\'strict\'",\n' - ' meaning that encoding errors raise a "UnicodeError". ' + ' Return the string encoded to "bytes".\n' + '\n' + ' *encoding* defaults to "\'utf-8\'"; see Standard ' + 'Encodings for\n' + ' possible values.\n' + '\n' + ' *errors* controls how encoding errors are handled. If ' + '"\'strict\'"\n' + ' (the default), a "UnicodeError" exception is raised. ' 'Other possible\n' ' values are "\'ignore\'", "\'replace\'", ' '"\'xmlcharrefreplace\'",\n' ' "\'backslashreplace\'" and any other name registered ' 'via\n' - ' "codecs.register_error()", see section Error Handlers. ' - 'For a list\n' - ' of possible encodings, see section Standard Encodings.\n' - '\n' - ' By default, the *errors* argument is not checked for ' - 'best\n' - ' performances, but only used at the first encoding ' - 'error. Enable the\n' - ' Python Development Mode, or use a debug build to check ' - '*errors*.\n' - '\n' - ' Changed in version 3.1: Support for keyword arguments ' - 'added.\n' - '\n' - ' Changed in version 3.9: The *errors* is now checked in ' - 'development\n' - ' mode and in debug mode.\n' + ' "codecs.register_error()". See Error Handlers for ' + 'details.\n' + '\n' + ' For performance reasons, the value of *errors* is not ' + 'checked for\n' + ' validity unless an encoding error actually occurs, ' + 'Python\n' + ' Development Mode is enabled or a debug build is used.\n' + '\n' + ' Changed in version 3.1: Added support for keyword ' + 'arguments.\n' + '\n' + ' Changed in version 3.9: The value of the *errors* ' + 'argument is now\n' + ' checked in Python Development Mode and in debug mode.\n' '\n' 'str.endswith(suffix[, start[, end]])\n' '\n' @@ -12768,7 +12802,7 @@ ' points. All the code points in the range "U+0000 - ' 'U+10FFFF"\n' ' can be represented in a string. Python doesn’t have a ' - '*char*\n' + '"char"\n' ' type; instead, every code point in the string is ' 'represented\n' ' as a string object with length "1". The built-in ' @@ -13717,17 +13751,11 @@ 'dictionaries or\n' 'other mutable types (that are compared by value rather than ' 'by object\n' - 'identity) may not be used as keys. Numeric types used for ' - 'keys obey\n' - 'the normal rules for numeric comparison: if two numbers ' - 'compare equal\n' - '(such as "1" and "1.0") then they can be used ' - 'interchangeably to index\n' - 'the same dictionary entry. (Note however, that since ' - 'computers store\n' - 'floating-point numbers as approximations it is usually ' - 'unwise to use\n' - 'them as dictionary keys.)\n' + 'identity) may not be used as keys. Values that compare equal ' + '(such as\n' + '"1", "1.0", and "True") can be used interchangeably to index ' + 'the same\n' + 'dictionary entry.\n' '\n' 'class dict(**kwargs)\n' 'class dict(mapping, **kwargs)\n' @@ -14134,7 +14162,7 @@ ' New in version 3.10.\n' '\n' 'Keys views are set-like since their entries are unique and ' - 'hashable.\n' + '*hashable*.\n' 'If all values are hashable, so that "(key, value)" pairs are ' 'unique\n' 'and hashable, then the items view is also set-like. (Values ' @@ -14183,8 +14211,7 @@ ' >>> # get back a read-only proxy for the original ' 'dictionary\n' ' >>> values.mapping\n' - " mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, " - "'spam': 500})\n" + " mappingproxy({'bacon': 1, 'spam': 500})\n" " >>> values.mapping['spam']\n" ' 500\n', 'typesmethods': 'Methods\n' @@ -15230,7 +15257,7 @@ ' returns without an error, then "__exit__()" will always be\n' ' called. Thus, if an error occurs during the assignment to the\n' ' target list, it will be treated the same as an error occurring\n' - ' within the suite would be. See step 6 below.\n' + ' within the suite would be. See step 7 below.\n' '\n' '6. The suite is executed.\n' '\n' diff -Nru python3.10-3.10.7/Lib/shutil.py python3.10-3.10.12/Lib/shutil.py --- python3.10-3.10.7/Lib/shutil.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/shutil.py 2023-06-06 22:30:33.000000000 +0000 @@ -487,12 +487,13 @@ # otherwise let the copy occur. copy2 will raise an error if srcentry.is_dir(): copytree(srcobj, dstname, symlinks, ignore, - copy_function, dirs_exist_ok=dirs_exist_ok) + copy_function, ignore_dangling_symlinks, + dirs_exist_ok) else: copy_function(srcobj, dstname) elif srcentry.is_dir(): copytree(srcobj, dstname, symlinks, ignore, copy_function, - dirs_exist_ok=dirs_exist_ok) + ignore_dangling_symlinks, dirs_exist_ok) else: # Will raise a SpecialFileError for unsupported file types copy_function(srcobj, dstname) @@ -1221,7 +1222,7 @@ finally: zip.close() -def _unpack_tarfile(filename, extract_dir): +def _unpack_tarfile(filename, extract_dir, *, filter=None): """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir` """ import tarfile # late import for breaking circular dependency @@ -1231,7 +1232,7 @@ raise ReadError( "%s is not a compressed or uncompressed tar file" % filename) try: - tarobj.extractall(extract_dir) + tarobj.extractall(extract_dir, filter=filter) finally: tarobj.close() @@ -1264,7 +1265,7 @@ return name return None -def unpack_archive(filename, extract_dir=None, format=None): +def unpack_archive(filename, extract_dir=None, format=None, *, filter=None): """Unpack an archive. `filename` is the name of the archive. @@ -1278,6 +1279,9 @@ was registered for that extension. In case none is found, a ValueError is raised. + + If `filter` is given, it is passed to the underlying + extraction function. """ sys.audit("shutil.unpack_archive", filename, extract_dir, format) @@ -1287,6 +1291,10 @@ extract_dir = os.fspath(extract_dir) filename = os.fspath(filename) + if filter is None: + filter_kwargs = {} + else: + filter_kwargs = {'filter': filter} if format is not None: try: format_info = _UNPACK_FORMATS[format] @@ -1294,7 +1302,7 @@ raise ValueError("Unknown unpack format '{0}'".format(format)) from None func = format_info[1] - func(filename, extract_dir, **dict(format_info[2])) + func(filename, extract_dir, **dict(format_info[2]), **filter_kwargs) else: # we need to look at the registered unpackers supported extensions format = _find_unpack_format(filename) @@ -1302,7 +1310,7 @@ raise ReadError("Unknown archive format '{0}'".format(filename)) func = _UNPACK_FORMATS[format][1] - kwargs = dict(_UNPACK_FORMATS[format][2]) + kwargs = dict(_UNPACK_FORMATS[format][2]) | filter_kwargs func(filename, extract_dir, **kwargs) diff -Nru python3.10-3.10.7/Lib/socket.py python3.10-3.10.12/Lib/socket.py --- python3.10-3.10.7/Lib/socket.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/socket.py 2023-06-06 22:30:33.000000000 +0000 @@ -783,11 +783,11 @@ First the hostname returned by gethostbyaddr() is checked, then possibly existing aliases. In case no FQDN is available and `name` - was given, it is returned unchanged. If `name` was empty or '0.0.0.0', + was given, it is returned unchanged. If `name` was empty, '0.0.0.0' or '::', hostname from gethostname() is returned. """ name = name.strip() - if not name or name == '0.0.0.0': + if not name or name in ('0.0.0.0', '::'): name = gethostname() try: hostname, aliases, ipaddrs = gethostbyaddr(name) @@ -902,7 +902,7 @@ # address, effectively preventing this one from accepting # connections. Also, it may set the process in a state where # it'll no longer respond to any signals or graceful kills. - # See: msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx + # See: https://learn.microsoft.com/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse if os.name not in ('nt', 'cygwin') and \ hasattr(_socket, 'SO_REUSEADDR'): try: diff -Nru python3.10-3.10.7/Lib/sqlite3/test/factory.py python3.10-3.10.12/Lib/sqlite3/test/factory.py --- python3.10-3.10.7/Lib/sqlite3/test/factory.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/sqlite3/test/factory.py 2023-06-06 22:30:33.000000000 +0000 @@ -155,8 +155,14 @@ """Checks if the row object is iterable""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() - for col in row: - pass + + # Is iterable in correct order and produces valid results: + items = [col for col in row] + self.assertEqual(items, [1, 2]) + + # Is iterable the second time: + items = [col for col in row] + self.assertEqual(items, [1, 2]) def test_sqlite_row_as_tuple(self): """Checks if the row object can be converted to a tuple""" diff -Nru python3.10-3.10.7/Lib/statistics.py python3.10-3.10.12/Lib/statistics.py --- python3.10-3.10.7/Lib/statistics.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/statistics.py 2023-06-06 22:30:33.000000000 +0000 @@ -1265,3 +1265,9 @@ def __repr__(self): return f'{type(self).__name__}(mu={self._mu!r}, sigma={self._sigma!r})' + + def __getstate__(self): + return self._mu, self._sigma + + def __setstate__(self, state): + self._mu, self._sigma = state diff -Nru python3.10-3.10.7/Lib/subprocess.py python3.10-3.10.12/Lib/subprocess.py --- python3.10-3.10.7/Lib/subprocess.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/subprocess.py 2023-06-06 22:30:33.000000000 +0000 @@ -411,7 +411,8 @@ if 'input' in kwargs and kwargs['input'] is None: # Explicitly passing input=None was previously equivalent to passing an # empty string. That is maintained here for backwards compatibility. - if kwargs.get('universal_newlines') or kwargs.get('text'): + if kwargs.get('universal_newlines') or kwargs.get('text') or kwargs.get('encoding') \ + or kwargs.get('errors'): empty = '' else: empty = b'' @@ -463,7 +464,8 @@ The returned instance will have attributes args, returncode, stdout and stderr. By default, stdout and stderr are not captured, and those attributes - will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them. + will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them, + or pass capture_output=True to capture both. If check is True and the exit code was non-zero, it raises a CalledProcessError. The CalledProcessError object will have the return code @@ -1425,7 +1427,23 @@ if shell: startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW startupinfo.wShowWindow = _winapi.SW_HIDE - comspec = os.environ.get("COMSPEC", "cmd.exe") + if not executable: + # gh-101283: without a fully-qualified path, before Windows + # checks the system directories, it first looks in the + # application directory, and also the current directory if + # NeedCurrentDirectoryForExePathW(ExeName) is true, so try + # to avoid executing unqualified "cmd.exe". + comspec = os.environ.get('ComSpec') + if not comspec: + system_root = os.environ.get('SystemRoot', '') + comspec = os.path.join(system_root, 'System32', 'cmd.exe') + if not os.path.isabs(comspec): + raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set') + if os.path.isabs(comspec): + executable = comspec + else: + comspec = executable + args = '{} /c "{}"'.format (comspec, args) if cwd is not None: diff -Nru python3.10-3.10.7/Lib/tabnanny.py python3.10-3.10.12/Lib/tabnanny.py --- python3.10-3.10.7/Lib/tabnanny.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/tabnanny.py 2023-06-06 22:30:33.000000000 +0000 @@ -23,8 +23,6 @@ import os import sys import tokenize -if not hasattr(tokenize, 'NL'): - raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") __all__ = ["check", "NannyNag", "process_tokens"] diff -Nru python3.10-3.10.7/Lib/tarfile.py python3.10-3.10.12/Lib/tarfile.py --- python3.10-3.10.7/Lib/tarfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/tarfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -46,6 +46,7 @@ import struct import copy import re +import warnings try: import pwd @@ -71,6 +72,7 @@ "ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT", "DEFAULT_FORMAT", "open"] + #--------------------------------------------------------- # tar constants #--------------------------------------------------------- @@ -158,6 +160,8 @@ def stn(s, length, encoding, errors): """Convert a string to a null-terminated bytes object. """ + if s is None: + raise ValueError("metadata cannot contain None") s = s.encode(encoding, errors) return s[:length] + (length - len(s)) * NUL @@ -709,9 +713,127 @@ super().__init__(fileobj) #class ExFileObject + +#----------------------------- +# extraction filters (PEP 706) +#----------------------------- + +class FilterError(TarError): + pass + +class AbsolutePathError(FilterError): + def __init__(self, tarinfo): + self.tarinfo = tarinfo + super().__init__(f'member {tarinfo.name!r} has an absolute path') + +class OutsideDestinationError(FilterError): + def __init__(self, tarinfo, path): + self.tarinfo = tarinfo + self._path = path + super().__init__(f'{tarinfo.name!r} would be extracted to {path!r}, ' + + 'which is outside the destination') + +class SpecialFileError(FilterError): + def __init__(self, tarinfo): + self.tarinfo = tarinfo + super().__init__(f'{tarinfo.name!r} is a special file') + +class AbsoluteLinkError(FilterError): + def __init__(self, tarinfo): + self.tarinfo = tarinfo + super().__init__(f'{tarinfo.name!r} is a symlink to an absolute path') + +class LinkOutsideDestinationError(FilterError): + def __init__(self, tarinfo, path): + self.tarinfo = tarinfo + self._path = path + super().__init__(f'{tarinfo.name!r} would link to {path!r}, ' + + 'which is outside the destination') + +def _get_filtered_attrs(member, dest_path, for_data=True): + new_attrs = {} + name = member.name + dest_path = os.path.realpath(dest_path) + # Strip leading / (tar's directory separator) from filenames. + # Include os.sep (target OS directory separator) as well. + if name.startswith(('/', os.sep)): + name = new_attrs['name'] = member.path.lstrip('/' + os.sep) + if os.path.isabs(name): + # Path is absolute even after stripping. + # For example, 'C:/foo' on Windows. + raise AbsolutePathError(member) + # Ensure we stay in the destination + target_path = os.path.realpath(os.path.join(dest_path, name)) + if os.path.commonpath([target_path, dest_path]) != dest_path: + raise OutsideDestinationError(member, target_path) + # Limit permissions (no high bits, and go-w) + mode = member.mode + if mode is not None: + # Strip high bits & group/other write bits + mode = mode & 0o755 + if for_data: + # For data, handle permissions & file types + if member.isreg() or member.islnk(): + if not mode & 0o100: + # Clear executable bits if not executable by user + mode &= ~0o111 + # Ensure owner can read & write + mode |= 0o600 + elif member.isdir() or member.issym(): + # Ignore mode for directories & symlinks + mode = None + else: + # Reject special files + raise SpecialFileError(member) + if mode != member.mode: + new_attrs['mode'] = mode + if for_data: + # Ignore ownership for 'data' + if member.uid is not None: + new_attrs['uid'] = None + if member.gid is not None: + new_attrs['gid'] = None + if member.uname is not None: + new_attrs['uname'] = None + if member.gname is not None: + new_attrs['gname'] = None + # Check link destination for 'data' + if member.islnk() or member.issym(): + if os.path.isabs(member.linkname): + raise AbsoluteLinkError(member) + target_path = os.path.realpath(os.path.join(dest_path, member.linkname)) + if os.path.commonpath([target_path, dest_path]) != dest_path: + raise LinkOutsideDestinationError(member, target_path) + return new_attrs + +def fully_trusted_filter(member, dest_path): + return member + +def tar_filter(member, dest_path): + new_attrs = _get_filtered_attrs(member, dest_path, False) + if new_attrs: + return member.replace(**new_attrs, deep=False) + return member + +def data_filter(member, dest_path): + new_attrs = _get_filtered_attrs(member, dest_path, True) + if new_attrs: + return member.replace(**new_attrs, deep=False) + return member + +_NAMED_FILTERS = { + "fully_trusted": fully_trusted_filter, + "tar": tar_filter, + "data": data_filter, +} + #------------------ # Exported Classes #------------------ + +# Sentinel for replace() defaults, meaning "don't change the attribute" +_KEEP = object() + class TarInfo(object): """Informational class which holds the details about an archive member given by a tar header block. @@ -792,12 +914,44 @@ def __repr__(self): return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + def replace(self, *, + name=_KEEP, mtime=_KEEP, mode=_KEEP, linkname=_KEEP, + uid=_KEEP, gid=_KEEP, uname=_KEEP, gname=_KEEP, + deep=True, _KEEP=_KEEP): + """Return a deep copy of self with the given attributes replaced. + """ + if deep: + result = copy.deepcopy(self) + else: + result = copy.copy(self) + if name is not _KEEP: + result.name = name + if mtime is not _KEEP: + result.mtime = mtime + if mode is not _KEEP: + result.mode = mode + if linkname is not _KEEP: + result.linkname = linkname + if uid is not _KEEP: + result.uid = uid + if gid is not _KEEP: + result.gid = gid + if uname is not _KEEP: + result.uname = uname + if gname is not _KEEP: + result.gname = gname + return result + def get_info(self): """Return the TarInfo's attributes as a dictionary. """ + if self.mode is None: + mode = None + else: + mode = self.mode & 0o7777 info = { "name": self.name, - "mode": self.mode & 0o7777, + "mode": mode, "uid": self.uid, "gid": self.gid, "size": self.size, @@ -820,6 +974,9 @@ """Return a tar header as a string of 512 byte blocks. """ info = self.get_info() + for name, value in info.items(): + if value is None: + raise ValueError("%s may not be None" % name) if format == USTAR_FORMAT: return self.create_ustar_header(info, encoding, errors) @@ -950,6 +1107,12 @@ devmajor = stn("", 8, encoding, errors) devminor = stn("", 8, encoding, errors) + # None values in metadata should cause ValueError. + # itn()/stn() do this for all fields except type. + filetype = info.get("type", REGTYPE) + if filetype is None: + raise ValueError("TarInfo.type must not be None") + parts = [ stn(info.get("name", ""), 100, encoding, errors), itn(info.get("mode", 0) & 0o7777, 8, format), @@ -958,7 +1121,7 @@ itn(info.get("size", 0), 12, format), itn(info.get("mtime", 0), 12, format), b" ", # checksum field - info.get("type", REGTYPE), + filetype, stn(info.get("linkname", ""), 100, encoding, errors), info.get("magic", POSIX_MAGIC), stn(info.get("uname", ""), 32, encoding, errors), @@ -1468,6 +1631,8 @@ fileobject = ExFileObject # The file-object for extractfile(). + extraction_filter = None # The default filter for extraction. + def __init__(self, name=None, mode="r", fileobj=None, format=None, tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, errors="surrogateescape", pax_headers=None, debug=None, @@ -1940,7 +2105,10 @@ members = self for tarinfo in members: if verbose: - _safe_print(stat.filemode(tarinfo.mode)) + if tarinfo.mode is None: + _safe_print("??????????") + else: + _safe_print(stat.filemode(tarinfo.mode)) _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, tarinfo.gname or tarinfo.gid)) if tarinfo.ischr() or tarinfo.isblk(): @@ -1948,8 +2116,11 @@ ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor))) else: _safe_print("%10d" % tarinfo.size) - _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6]) + if tarinfo.mtime is None: + _safe_print("????-??-?? ??:??:??") + else: + _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6]) _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else "")) @@ -2036,32 +2207,58 @@ self.members.append(tarinfo) - def extractall(self, path=".", members=None, *, numeric_owner=False): + def _get_filter_function(self, filter): + if filter is None: + filter = self.extraction_filter + if filter is None: + return fully_trusted_filter + if isinstance(filter, str): + raise TypeError( + 'String names are not supported for ' + + 'TarFile.extraction_filter. Use a function such as ' + + 'tarfile.data_filter directly.') + return filter + if callable(filter): + return filter + try: + return _NAMED_FILTERS[filter] + except KeyError: + raise ValueError(f"filter {filter!r} not found") from None + + def extractall(self, path=".", members=None, *, numeric_owner=False, + filter=None): """Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the list returned by getmembers(). If `numeric_owner` is True, only the numbers for user/group names are used and not the names. + + The `filter` function will be called on each member just + before extraction. + It can return a changed TarInfo or None to skip the member. + String names of common filters are accepted. """ directories = [] + filter_function = self._get_filter_function(filter) if members is None: members = self - for tarinfo in members: + for member in members: + tarinfo = self._get_extract_tarinfo(member, filter_function, path) + if tarinfo is None: + continue if tarinfo.isdir(): - # Extract directories with a safe mode. + # For directories, delay setting attributes until later, + # since permissions can interfere with extraction and + # extracting contents can reset mtime. directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 0o700 - # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir(), - numeric_owner=numeric_owner) + self._extract_one(tarinfo, path, set_attrs=not tarinfo.isdir(), + numeric_owner=numeric_owner) # Reverse sort directories. - directories.sort(key=lambda a: a.name) - directories.reverse() + directories.sort(key=lambda a: a.name, reverse=True) # Set correct owner, mtime and filemode on directories. for tarinfo in directories: @@ -2071,12 +2268,10 @@ self.utime(tarinfo, dirpath) self.chmod(tarinfo, dirpath) except ExtractError as e: - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) + self._handle_nonfatal_error(e) - def extract(self, member, path="", set_attrs=True, *, numeric_owner=False): + def extract(self, member, path="", set_attrs=True, *, numeric_owner=False, + filter=None): """Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. `member' may be a filename or a TarInfo object. You can @@ -2084,35 +2279,70 @@ mtime, mode) are set unless `set_attrs' is False. If `numeric_owner` is True, only the numbers for user/group names are used and not the names. + + The `filter` function will be called before extraction. + It can return a changed TarInfo or None to skip the member. + String names of common filters are accepted. """ - self._check("r") + filter_function = self._get_filter_function(filter) + tarinfo = self._get_extract_tarinfo(member, filter_function, path) + if tarinfo is not None: + self._extract_one(tarinfo, path, set_attrs, numeric_owner) + def _get_extract_tarinfo(self, member, filter_function, path): + """Get filtered TarInfo (or None) from member, which might be a str""" if isinstance(member, str): tarinfo = self.getmember(member) else: tarinfo = member + unfiltered = tarinfo + try: + tarinfo = filter_function(tarinfo, path) + except (OSError, FilterError) as e: + self._handle_fatal_error(e) + except ExtractError as e: + self._handle_nonfatal_error(e) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % unfiltered.name) + return None # Prepare the link target for makelink(). if tarinfo.islnk(): + tarinfo = copy.copy(tarinfo) tarinfo._link_target = os.path.join(path, tarinfo.linkname) + return tarinfo + + def _extract_one(self, tarinfo, path, set_attrs, numeric_owner): + """Extract from filtered tarinfo to disk""" + self._check("r") try: self._extract_member(tarinfo, os.path.join(path, tarinfo.name), set_attrs=set_attrs, numeric_owner=numeric_owner) except OSError as e: - if self.errorlevel > 0: - raise - else: - if e.filename is None: - self._dbg(1, "tarfile: %s" % e.strerror) - else: - self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + self._handle_fatal_error(e) except ExtractError as e: - if self.errorlevel > 1: - raise + self._handle_nonfatal_error(e) + + def _handle_nonfatal_error(self, e): + """Handle non-fatal error (ExtractError) according to errorlevel""" + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def _handle_fatal_error(self, e): + """Handle "fatal" error according to self.errorlevel""" + if self.errorlevel > 0: + raise + elif isinstance(e, OSError): + if e.filename is None: + self._dbg(1, "tarfile: %s" % e.strerror) else: - self._dbg(1, "tarfile: %s" % e) + self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + else: + self._dbg(1, "tarfile: %s %s" % (type(e).__name__, e)) def extractfile(self, member): """Extract a member from the archive as a file object. `member' may be @@ -2199,9 +2429,13 @@ """Make a directory called targetpath. """ try: - # Use a safe mode for the directory, the real mode is set - # later in _extract_member(). - os.mkdir(targetpath, 0o700) + if tarinfo.mode is None: + # Use the system's default mode + os.mkdir(targetpath) + else: + # Use a safe mode for the directory, the real mode is set + # later in _extract_member(). + os.mkdir(targetpath, 0o700) except FileExistsError: pass @@ -2244,6 +2478,9 @@ raise ExtractError("special devices not supported by system") mode = tarinfo.mode + if mode is None: + # Use mknod's default + mode = 0o600 if tarinfo.isblk(): mode |= stat.S_IFBLK else: @@ -2265,7 +2502,6 @@ os.unlink(targetpath) os.symlink(tarinfo.linkname, targetpath) else: - # See extract(). if os.path.exists(tarinfo._link_target): os.link(tarinfo._link_target, targetpath) else: @@ -2290,15 +2526,19 @@ u = tarinfo.uid if not numeric_owner: try: - if grp: + if grp and tarinfo.gname: g = grp.getgrnam(tarinfo.gname)[2] except KeyError: pass try: - if pwd: + if pwd and tarinfo.uname: u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: pass + if g is None: + g = -1 + if u is None: + u = -1 try: if tarinfo.issym() and hasattr(os, "lchown"): os.lchown(targetpath, u, g) @@ -2310,6 +2550,8 @@ def chmod(self, tarinfo, targetpath): """Set file permissions of targetpath according to tarinfo. """ + if tarinfo.mode is None: + return try: os.chmod(targetpath, tarinfo.mode) except OSError as e: @@ -2318,10 +2560,13 @@ def utime(self, tarinfo, targetpath): """Set modification time of targetpath according to tarinfo. """ + mtime = tarinfo.mtime + if mtime is None: + return if not hasattr(os, 'utime'): return try: - os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) + os.utime(targetpath, (mtime, mtime)) except OSError as e: raise ExtractError("could not change modification time") from e @@ -2397,13 +2642,26 @@ members = self.getmembers() # Limit the member search list up to tarinfo. + skipping = False if tarinfo is not None: - members = members[:members.index(tarinfo)] + try: + index = members.index(tarinfo) + except ValueError: + # The given starting point might be a (modified) copy. + # We'll later skip members until we find an equivalent. + skipping = True + else: + # Happy fast path + members = members[:index] if normalize: name = os.path.normpath(name) for member in reversed(members): + if skipping: + if tarinfo.offset == member.offset: + skipping = False + continue if normalize: member_name = os.path.normpath(member.name) else: @@ -2412,6 +2670,10 @@ if name == member_name: return member + if skipping: + # Starting point was not found + raise ValueError(tarinfo) + def _load(self): """Read through the entire archive file and look for readable members. @@ -2504,6 +2766,7 @@ #-------------------- # exported functions #-------------------- + def is_tarfile(name): """Return True if name points to a tar archive that we are able to handle, else return False. @@ -2530,6 +2793,10 @@ parser = argparse.ArgumentParser(description=description) parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Verbose output') + parser.add_argument('--filter', metavar='', + choices=_NAMED_FILTERS, + help='Filter for extraction') + group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-l', '--list', metavar='', help='Show listing of a tarfile') @@ -2541,8 +2808,12 @@ help='Create tarfile from sources') group.add_argument('-t', '--test', metavar='', help='Test if a tarfile is valid') + args = parser.parse_args() + if args.filter and args.extract is None: + parser.exit(1, '--filter is only valid for extraction\n') + if args.test is not None: src = args.test if is_tarfile(src): @@ -2573,7 +2844,7 @@ if is_tarfile(src): with TarFile.open(src, 'r:*') as tf: - tf.extractall(path=curdir) + tf.extractall(path=curdir, filter=args.filter) if args.verbose: if curdir == '.': msg = '{!r} file is extracted.'.format(src) diff -Nru python3.10-3.10.7/Lib/test/audit-tests.py python3.10-3.10.12/Lib/test/audit-tests.py --- python3.10-3.10.7/Lib/test/audit-tests.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/audit-tests.py 2023-06-06 22:30:33.000000000 +0000 @@ -408,6 +408,38 @@ raise RuntimeError("Expected sqlite3.load_extension to fail") +def test_syslog(): + import syslog + + def hook(event, args): + if event.startswith("syslog."): + print(event, *args) + + sys.addaudithook(hook) + syslog.openlog('python') + syslog.syslog('test') + syslog.setlogmask(syslog.LOG_DEBUG) + syslog.closelog() + # implicit open + syslog.syslog('test2') + # open with default ident + syslog.openlog(logoption=syslog.LOG_NDELAY, facility=syslog.LOG_LOCAL0) + sys.argv = None + syslog.openlog() + syslog.closelog() + + +def test_not_in_gc(): + import gc + + hook = lambda *a: None + sys.addaudithook(hook) + + for o in gc.get_objects(): + if isinstance(o, list): + assert hook not in o + + if __name__ == "__main__": from test.support import suppress_msvcrt_asserts diff -Nru python3.10-3.10.7/Lib/test/clinic.test python3.10-3.10.12/Lib/test/clinic.test --- python3.10-3.10.7/Lib/test/clinic.test 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/clinic.test 2023-06-06 22:30:33.000000000 +0000 @@ -1740,29 +1740,18 @@ goto exit; } return_value = test_str_converter_encoding_impl(module, a, b, c, d, d_length, e, e_length); + /* Post parse cleanup for a */ + PyMem_FREE(a); + /* Post parse cleanup for b */ + PyMem_FREE(b); + /* Post parse cleanup for c */ + PyMem_FREE(c); + /* Post parse cleanup for d */ + PyMem_FREE(d); + /* Post parse cleanup for e */ + PyMem_FREE(e); exit: - /* Cleanup for a */ - if (a) { - PyMem_FREE(a); - } - /* Cleanup for b */ - if (b) { - PyMem_FREE(b); - } - /* Cleanup for c */ - if (c) { - PyMem_FREE(c); - } - /* Cleanup for d */ - if (d) { - PyMem_FREE(d); - } - /* Cleanup for e */ - if (e) { - PyMem_FREE(e); - } - return return_value; } @@ -1770,7 +1759,7 @@ test_str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, char *d, Py_ssize_clean_t d_length, char *e, Py_ssize_clean_t e_length) -/*[clinic end generated code: output=f579dd9e795a364e input=eb4c38e1f898f402]*/ +/*[clinic end generated code: output=2d7e8b6203db31aa input=eb4c38e1f898f402]*/ /*[clinic input] @@ -1805,12 +1794,12 @@ test_Py_UNICODE_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const Py_UNICODE *a; - const Py_UNICODE *b; - const Py_UNICODE *c; - const Py_UNICODE *d; + const Py_UNICODE *a = NULL; + const Py_UNICODE *b = NULL; + const Py_UNICODE *c = NULL; + const Py_UNICODE *d = NULL; Py_ssize_clean_t d_length; - const Py_UNICODE *e; + const Py_UNICODE *e = NULL; Py_ssize_clean_t e_length; if (!_PyArg_ParseStack(args, nargs, "O&O&O&u#Z#:test_Py_UNICODE_converter", @@ -1843,7 +1832,7 @@ Py_ssize_clean_t d_length, const Py_UNICODE *e, Py_ssize_clean_t e_length) -/*[clinic end generated code: output=ef45e982fedf0b3d input=064a3b68ad7f04b0]*/ +/*[clinic end generated code: output=e45007c49e77ad4a input=064a3b68ad7f04b0]*/ /*[clinic input] diff -Nru python3.10-3.10.7/Lib/test/inspect_fodder2.py python3.10-3.10.12/Lib/test/inspect_fodder2.py --- python3.10-3.10.7/Lib/test/inspect_fodder2.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/inspect_fodder2.py 2023-06-06 22:30:33.000000000 +0000 @@ -259,3 +259,17 @@ #line 259 def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5): pass + +# line 263 +def deco_factory(**kwargs): + def deco(f): + @wraps(f) + def wrapper(*a, **kwd): + kwd.update(kwargs) + return f(*a, **kwd) + return wrapper + return deco + +@deco_factory(foo=(1 + 2), bar=lambda: 1) +def complex_decorated(foo=0, bar=lambda: 0): + return foo + bar() diff -Nru python3.10-3.10.7/Lib/test/pickletester.py python3.10-3.10.12/Lib/test/pickletester.py --- python3.10-3.10.7/Lib/test/pickletester.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/pickletester.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,3 +1,4 @@ +import builtins import collections import copyreg import dbm @@ -11,6 +12,7 @@ import struct import sys import threading +import types import unittest import weakref from textwrap import dedent @@ -1979,6 +1981,33 @@ u = self.loads(s) self.assertIs(type(singleton), u) + def test_builtin_types(self): + for t in builtins.__dict__.values(): + if isinstance(t, type) and not issubclass(t, BaseException): + for proto in protocols: + s = self.dumps(t, proto) + self.assertIs(self.loads(s), t) + + def test_builtin_exceptions(self): + for t in builtins.__dict__.values(): + if isinstance(t, type) and issubclass(t, BaseException): + for proto in protocols: + s = self.dumps(t, proto) + u = self.loads(s) + if proto <= 2 and issubclass(t, OSError) and t is not BlockingIOError: + self.assertIs(u, OSError) + elif proto <= 2 and issubclass(t, ImportError): + self.assertIs(u, ImportError) + else: + self.assertIs(u, t) + + def test_builtin_functions(self): + for t in builtins.__dict__.values(): + if isinstance(t, types.BuiltinFunctionType): + for proto in protocols: + s = self.dumps(t, proto) + self.assertIs(self.loads(s), t) + # Tests for protocol 2 def test_proto(self): @@ -2773,6 +2802,15 @@ unpickled = self.loads(self.dumps(method, proto)) self.assertEqual(method(obj), unpickled(obj)) + descriptors = ( + PyMethodsTest.__dict__['cheese'], # static method descriptor + PyMethodsTest.__dict__['wine'], # class method descriptor + ) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + for descr in descriptors: + with self.subTest(proto=proto, descr=descr): + self.assertRaises(TypeError, self.dumps, descr, proto) + def test_c_methods(self): global Subclass class Subclass(tuple): @@ -2808,6 +2846,15 @@ unpickled = self.loads(self.dumps(method, proto)) self.assertEqual(method(*args), unpickled(*args)) + descriptors = ( + bytearray.__dict__['maketrans'], # built-in static method descriptor + dict.__dict__['fromkeys'], # built-in class method descriptor + ) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + for descr in descriptors: + with self.subTest(proto=proto, descr=descr): + self.assertRaises(TypeError, self.dumps, descr, proto) + def test_compat_pickle(self): tests = [ (range(1, 7), '__builtin__', 'xrange'), diff -Nru python3.10-3.10.7/Lib/test/support/__init__.py python3.10-3.10.12/Lib/test/support/__init__.py --- python3.10-3.10.7/Lib/test/support/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/support/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -1986,7 +1986,7 @@ Raise an AssertionError if the process exit code is not equal to exitcode. - If the process runs longer than timeout seconds (SHORT_TIMEOUT by default), + If the process runs longer than timeout seconds (LONG_TIMEOUT by default), kill the process (if signal.SIGKILL is available) and raise an AssertionError. The timeout feature is not available on Windows. """ @@ -1994,7 +1994,7 @@ import signal if timeout is None: - timeout = SHORT_TIMEOUT + timeout = LONG_TIMEOUT t0 = time.monotonic() sleep = 0.001 max_sleep = 0.1 @@ -2005,7 +2005,7 @@ # process is still running dt = time.monotonic() - t0 - if dt > SHORT_TIMEOUT: + if dt > timeout: try: os.kill(pid, signal.SIGKILL) os.waitpid(pid, 0) diff -Nru python3.10-3.10.7/Lib/test/support/socket_helper.py python3.10-3.10.12/Lib/test/support/socket_helper.py --- python3.10-3.10.7/Lib/test/support/socket_helper.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/support/socket_helper.py 2023-06-06 22:30:33.000000000 +0000 @@ -58,7 +58,7 @@ http://bugs.python.org/issue2550 for more info. The following site also has a very thorough description about the implications of both REUSEADDR and EXCLUSIVEADDRUSE on Windows: - http://msdn2.microsoft.com/en-us/library/ms740621(VS.85).aspx) + https://learn.microsoft.com/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse XXX: although this approach is a vast improvement on previous attempts to elicit unused ports, it rests heavily on the assumption that the ephemeral diff -Nru python3.10-3.10.7/Lib/test/support/warnings_helper.py python3.10-3.10.12/Lib/test/support/warnings_helper.py --- python3.10-3.10.7/Lib/test/support/warnings_helper.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/support/warnings_helper.py 2023-06-06 22:30:33.000000000 +0000 @@ -36,7 +36,7 @@ def ignore_warnings(*, category): - """Decorator to suppress deprecation warnings. + """Decorator to suppress warnings. Use of context managers to hide warnings make diffs more noisy and tools like 'git blame' less useful. diff -Nru python3.10-3.10.7/Lib/test/test_argparse.py python3.10-3.10.12/Lib/test/test_argparse.py --- python3.10-3.10.7/Lib/test/test_argparse.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_argparse.py 2023-06-06 22:30:33.000000000 +0000 @@ -295,7 +295,7 @@ Sig('-z'), ] failures = ['a', '--foo', '-xa', '-x --foo', '-x -z', '-z -x', - '-yx', '-yz a', '-yyyx', '-yyyza', '-xyza'] + '-yx', '-yz a', '-yyyx', '-yyyza', '-xyza', '-x='] successes = [ ('', NS(x=False, yyy=None, z=None)), ('-x', NS(x=True, yyy=None, z=None)), @@ -3728,6 +3728,28 @@ ''' version = '' + +class TestHelpUsageWithParentheses(HelpTestCase): + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('positional', metavar='(example) positional'), + Sig('-p', '--optional', metavar='{1 (option A), 2 (option B)}'), + ] + + usage = '''\ + usage: PROG [-h] [-p {1 (option A), 2 (option B)}] (example) positional + ''' + help = usage + '''\ + + positional arguments: + (example) positional + + options: + -h, --help show this help message and exit + -p {1 (option A), 2 (option B)}, --optional {1 (option A), 2 (option B)} + ''' + version = '' + class TestHelpOnlyUserGroups(HelpTestCase): """Test basic usage messages""" diff -Nru python3.10-3.10.7/Lib/test/test_ast.py python3.10-3.10.12/Lib/test/test_ast.py --- python3.10-3.10.7/Lib/test/test_ast.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_ast.py 2023-06-06 22:30:33.000000000 +0000 @@ -355,6 +355,24 @@ self.assertEqual(alias.col_offset, 16) self.assertEqual(alias.end_col_offset, 17) + im = ast.parse("from bar import y as z").body[0] + alias = im.names[0] + self.assertEqual(alias.name, "y") + self.assertEqual(alias.asname, "z") + self.assertEqual(alias.lineno, 1) + self.assertEqual(alias.end_lineno, 1) + self.assertEqual(alias.col_offset, 16) + self.assertEqual(alias.end_col_offset, 22) + + im = ast.parse("import bar as foo").body[0] + alias = im.names[0] + self.assertEqual(alias.name, "bar") + self.assertEqual(alias.asname, "foo") + self.assertEqual(alias.lineno, 1) + self.assertEqual(alias.end_lineno, 1) + self.assertEqual(alias.col_offset, 7) + self.assertEqual(alias.end_col_offset, 17) + def test_base_classes(self): self.assertTrue(issubclass(ast.For, ast.stmt)) self.assertTrue(issubclass(ast.Name, ast.expr)) @@ -914,6 +932,18 @@ self.assertEqual(ast.increment_lineno(src).lineno, 2) self.assertIsNone(ast.increment_lineno(src).end_lineno) + def test_increment_lineno_on_module(self): + src = ast.parse(dedent("""\ + a = 1 + b = 2 # type: ignore + c = 3 + d = 4 # type: ignore@tag + """), type_comments=True) + ast.increment_lineno(src, n=5) + self.assertEqual(src.type_ignores[0].lineno, 7) + self.assertEqual(src.type_ignores[1].lineno, 9) + self.assertEqual(src.type_ignores[1].tag, '@tag') + def test_iter_fields(self): node = ast.parse('foo()', mode='eval') d = dict(ast.iter_fields(node.body)) diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_base_events.py python3.10-3.10.12/Lib/test/test_asyncio/test_base_events.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_base_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_base_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -752,7 +752,7 @@ def test_env_var_debug(self): code = '\n'.join(( 'import asyncio', - 'loop = asyncio.get_event_loop()', + 'loop = asyncio.new_event_loop()', 'print(loop.get_debug())')) # Test with -E to not fail if the unit test was run with diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_events.py python3.10-3.10.12/Lib/test/test_asyncio/test_events.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -670,6 +670,47 @@ self.assertEqual(port, expected) tr.close() + def test_create_connection_local_addr_skip_different_family(self): + # See https://github.com/python/cpython/issues/86508 + port1 = socket_helper.find_unused_port() + port2 = socket_helper.find_unused_port() + getaddrinfo_orig = self.loop.getaddrinfo + + async def getaddrinfo(host, port, *args, **kwargs): + if port == port2: + return [(socket.AF_INET6, socket.SOCK_STREAM, 0, '', ('::1', 0, 0, 0)), + (socket.AF_INET, socket.SOCK_STREAM, 0, '', ('127.0.0.1', 0))] + return await getaddrinfo_orig(host, port, *args, **kwargs) + + self.loop.getaddrinfo = getaddrinfo + + f = self.loop.create_connection( + lambda: MyProto(loop=self.loop), + 'localhost', port1, local_addr=('localhost', port2)) + + with self.assertRaises(OSError): + self.loop.run_until_complete(f) + + def test_create_connection_local_addr_nomatch_family(self): + # See https://github.com/python/cpython/issues/86508 + port1 = socket_helper.find_unused_port() + port2 = socket_helper.find_unused_port() + getaddrinfo_orig = self.loop.getaddrinfo + + async def getaddrinfo(host, port, *args, **kwargs): + if port == port2: + return [(socket.AF_INET6, socket.SOCK_STREAM, 0, '', ('::1', 0, 0, 0))] + return await getaddrinfo_orig(host, port, *args, **kwargs) + + self.loop.getaddrinfo = getaddrinfo + + f = self.loop.create_connection( + lambda: MyProto(loop=self.loop), + 'localhost', port1, local_addr=('localhost', port2)) + + with self.assertRaises(OSError): + self.loop.run_until_complete(f) + def test_create_connection_local_addr_in_use(self): with test_utils.run_test_server() as httpd: f = self.loop.create_connection( @@ -2561,7 +2602,6 @@ def test_get_event_loop(self): policy = asyncio.DefaultEventLoopPolicy() self.assertIsNone(policy._local._loop) - loop = policy.get_event_loop() self.assertIsInstance(loop, asyncio.AbstractEventLoop) @@ -2577,6 +2617,7 @@ wraps=policy.set_event_loop) as m_set_event_loop: loop = policy.get_event_loop() + self.addCleanup(loop.close) # policy._local._loop must be set through .set_event_loop() # (the unix DefaultEventLoopPolicy needs this call to attach @@ -2610,7 +2651,8 @@ def test_set_event_loop(self): policy = asyncio.DefaultEventLoopPolicy() - old_loop = policy.get_event_loop() + old_loop = policy.new_event_loop() + policy.set_event_loop(old_loop) self.assertRaises(AssertionError, policy.set_event_loop, object()) @@ -2723,15 +2765,11 @@ asyncio.set_event_loop_policy(Policy()) loop = asyncio.new_event_loop() - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaises(TestError): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaises(TestError): + asyncio.get_event_loop() with self.assertRaisesRegex(RuntimeError, 'no running'): asyncio.get_running_loop() @@ -2745,16 +2783,11 @@ loop.run_until_complete(func()) asyncio.set_event_loop(loop) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) - + with self.assertRaises(TestError): + asyncio.get_event_loop() asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(TestError): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaises(TestError): + asyncio.get_event_loop() finally: asyncio.set_event_loop_policy(old_policy) @@ -2773,15 +2806,11 @@ loop = asyncio.new_event_loop() self.addCleanup(loop.close) - with self.assertWarns(DeprecationWarning) as cm: - loop2 = asyncio.get_event_loop() + loop2 = asyncio.get_event_loop() self.addCleanup(loop2.close) - self.assertEqual(cm.warnings[0].filename, __file__) asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'no current'): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current'): + asyncio.get_event_loop() with self.assertRaisesRegex(RuntimeError, 'no running'): asyncio.get_running_loop() @@ -2795,15 +2824,11 @@ loop.run_until_complete(func()) asyncio.set_event_loop(loop) - with self.assertWarns(DeprecationWarning) as cm: - self.assertIs(asyncio.get_event_loop(), loop) - self.assertEqual(cm.warnings[0].filename, __file__) + self.assertIs(asyncio.get_event_loop(), loop) asyncio.set_event_loop(None) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'no current'): - asyncio.get_event_loop() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current'): + asyncio.get_event_loop() finally: asyncio.set_event_loop_policy(old_policy) diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_futures.py python3.10-3.10.12/Lib/test/test_asyncio/test_futures.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_futures.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_futures.py 2023-06-06 22:30:33.000000000 +0000 @@ -145,10 +145,8 @@ self.assertTrue(f.cancelled()) def test_constructor_without_loop(self): - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - self._new_future() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + self._new_future() def test_constructor_use_running_loop(self): async def test(): @@ -158,12 +156,10 @@ self.assertIs(f.get_loop(), self.loop) def test_constructor_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10, undeprecated in 3.11.1 asyncio.set_event_loop(self.loop) self.addCleanup(asyncio.set_event_loop, None) - with self.assertWarns(DeprecationWarning) as cm: - f = self._new_future() - self.assertEqual(cm.warnings[0].filename, __file__) + f = self._new_future() self.assertIs(f._loop, self.loop) self.assertIs(f.get_loop(), self.loop) @@ -499,10 +495,8 @@ return (arg, threading.get_ident()) ex = concurrent.futures.ThreadPoolExecutor(1) f1 = ex.submit(run, 'oi') - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(RuntimeError): - asyncio.wrap_future(f1) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.wrap_future(f1) ex.shutdown(wait=True) def test_wrap_future_use_running_loop(self): @@ -517,16 +511,14 @@ ex.shutdown(wait=True) def test_wrap_future_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10, undeprecated in 3.11.1 asyncio.set_event_loop(self.loop) self.addCleanup(asyncio.set_event_loop, None) def run(arg): return (arg, threading.get_ident()) ex = concurrent.futures.ThreadPoolExecutor(1) f1 = ex.submit(run, 'oi') - with self.assertWarns(DeprecationWarning) as cm: - f2 = asyncio.wrap_future(f1) - self.assertEqual(cm.warnings[0].filename, __file__) + f2 = asyncio.wrap_future(f1) self.assertIs(self.loop, f2._loop) ex.shutdown(wait=True) @@ -827,6 +819,21 @@ fut.remove_done_callback(evil()) + def test_remove_done_callbacks_list_clear(self): + # see https://github.com/python/cpython/issues/97592 for details + + fut = self._new_future() + fut.add_done_callback(str) + + for _ in range(63): + fut.add_done_callback(id) + + class evil: + def __eq__(self, other): + fut.remove_done_callback(other) + + fut.remove_done_callback(evil()) + def test_schedule_callbacks_list_mutation_1(self): # see http://bugs.python.org/issue28963 for details diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_locks.py python3.10-3.10.12/Lib/test/test_asyncio/test_locks.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_locks.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_locks.py 2023-06-06 22:30:33.000000000 +0000 @@ -5,6 +5,7 @@ import re import asyncio +import collections STR_RGX_REPR = ( r'^<(?P.*?) object at (?P
.*?)' @@ -782,6 +783,9 @@ self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) + if sem._waiters is None: + sem._waiters = collections.deque() + sem._waiters.append(mock.Mock()) self.assertTrue('waiters:1' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) @@ -853,7 +857,7 @@ sem.release() sem.release() - self.assertEqual(2, sem._value) + self.assertEqual(0, sem._value) await asyncio.sleep(0) self.assertEqual(0, sem._value) @@ -898,6 +902,7 @@ sem.release() await asyncio.sleep(0) + await asyncio.sleep(0) num_done = sum(t.done() for t in [t3, t4]) self.assertEqual(num_done, 1) self.assertTrue(t3.done()) @@ -917,9 +922,32 @@ t1.cancel() sem.release() await asyncio.sleep(0) + await asyncio.sleep(0) self.assertTrue(sem.locked()) self.assertTrue(t2.done()) + async def test_acquire_no_hang(self): + + sem = asyncio.Semaphore(1) + + async def c1(): + async with sem: + await asyncio.sleep(0) + t2.cancel() + + async def c2(): + async with sem: + self.assertFalse(True) + + t1 = asyncio.create_task(c1()) + t2 = asyncio.create_task(c2()) + + r1, r2 = await asyncio.gather(t1, t2, return_exceptions=True) + self.assertTrue(r1 is None) + self.assertTrue(isinstance(r2, asyncio.CancelledError)) + + await asyncio.wait_for(sem.acquire(), timeout=1.0) + def test_release_not_acquired(self): sem = asyncio.BoundedSemaphore() @@ -959,6 +987,77 @@ result ) + async def test_acquire_fifo_order_2(self): + sem = asyncio.Semaphore(1) + result = [] + + async def c1(result): + await sem.acquire() + result.append(1) + return True + + async def c2(result): + await sem.acquire() + result.append(2) + sem.release() + await sem.acquire() + result.append(4) + return True + + async def c3(result): + await sem.acquire() + result.append(3) + return True + + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) + + await asyncio.sleep(0) + + sem.release() + sem.release() + + tasks = [t1, t2, t3] + await asyncio.gather(*tasks) + self.assertEqual([1, 2, 3, 4], result) + + async def test_acquire_fifo_order_3(self): + sem = asyncio.Semaphore(0) + result = [] + + async def c1(result): + await sem.acquire() + result.append(1) + return True + + async def c2(result): + await sem.acquire() + result.append(2) + return True + + async def c3(result): + await sem.acquire() + result.append(3) + return True + + t1 = asyncio.create_task(c1(result)) + t2 = asyncio.create_task(c2(result)) + t3 = asyncio.create_task(c3(result)) + + await asyncio.sleep(0) + + t1.cancel() + + await asyncio.sleep(0) + + sem.release() + sem.release() + + tasks = [t1, t2, t3] + await asyncio.gather(*tasks, return_exceptions=True) + self.assertEqual([2, 3], result) + if __name__ == '__main__': unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_proactor_events.py python3.10-3.10.12/Lib/test/test_asyncio/test_proactor_events.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_proactor_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_proactor_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -289,7 +289,33 @@ tr._closing = True tr._force_close(None) test_utils.run_briefly(self.loop) + # See https://github.com/python/cpython/issues/89237 + # `protocol.connection_lost` should be called even if + # the transport was closed forcefully otherwise + # the resources held by protocol will never be freed + # and waiters will never be notified leading to hang. + self.assertTrue(self.protocol.connection_lost.called) + + def test_force_close_protocol_connection_lost_once(self): + tr = self.socket_transport() + self.assertFalse(self.protocol.connection_lost.called) + tr._closing = True + # Calling _force_close twice should not call + # protocol.connection_lost twice + tr._force_close(None) + tr._force_close(None) + test_utils.run_briefly(self.loop) + self.assertEqual(1, self.protocol.connection_lost.call_count) + + def test_close_protocol_connection_lost_once(self): + tr = self.socket_transport() self.assertFalse(self.protocol.connection_lost.called) + # Calling close twice should not call + # protocol.connection_lost twice + tr.close() + tr.close() + test_utils.run_briefly(self.loop) + self.assertEqual(1, self.protocol.connection_lost.call_count) def test_fatal_error_2(self): tr = self.socket_transport() diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_sendfile.py python3.10-3.10.12/Lib/test/test_asyncio/test_sendfile.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_sendfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_sendfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,6 +1,7 @@ """Tests for sendfile functionality.""" import asyncio +import errno import os import socket import sys @@ -484,8 +485,17 @@ srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) with self.assertRaises(ConnectionError): - self.run_loop( - self.loop.sendfile(cli_proto.transport, self.file)) + try: + self.run_loop( + self.loop.sendfile(cli_proto.transport, self.file)) + except OSError as e: + # macOS may raise OSError of EPROTOTYPE when writing to a + # socket that is in the process of closing down. + if e.errno == errno.EPROTOTYPE and sys.platform == "darwin": + raise ConnectionError + else: + raise + self.run_loop(srv_proto.done) self.assertTrue(1024 <= srv_proto.nbytes < len(self.DATA), diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_streams.py python3.10-3.10.12/Lib/test/test_asyncio/test_streams.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_streams.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_streams.py 2023-06-06 22:30:33.000000000 +0000 @@ -747,10 +747,8 @@ self.assertEqual(data, b'data') def test_streamreader_constructor_without_loop(self): - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - asyncio.StreamReader() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.StreamReader() def test_streamreader_constructor_use_running_loop(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor @@ -764,21 +762,17 @@ def test_streamreader_constructor_use_global_loop(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor # retrieves the current loop if the loop parameter is not set - # Deprecated in 3.10 + # Deprecated in 3.10, undeprecated in 3.11.1 self.addCleanup(asyncio.set_event_loop, None) asyncio.set_event_loop(self.loop) - with self.assertWarns(DeprecationWarning) as cm: - reader = asyncio.StreamReader() - self.assertEqual(cm.warnings[0].filename, __file__) + reader = asyncio.StreamReader() self.assertIs(reader._loop, self.loop) def test_streamreaderprotocol_constructor_without_loop(self): reader = mock.Mock() - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - asyncio.StreamReaderProtocol(reader) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.StreamReaderProtocol(reader) def test_streamreaderprotocol_constructor_use_running_loop(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor @@ -792,15 +786,32 @@ def test_streamreaderprotocol_constructor_use_global_loop(self): # asyncio issue #184: Ensure that StreamReaderProtocol constructor # retrieves the current loop if the loop parameter is not set - # Deprecated in 3.10 + # Deprecated in 3.10, undeprecated in 3.11.1 self.addCleanup(asyncio.set_event_loop, None) asyncio.set_event_loop(self.loop) reader = mock.Mock() - with self.assertWarns(DeprecationWarning) as cm: - protocol = asyncio.StreamReaderProtocol(reader) - self.assertEqual(cm.warnings[0].filename, __file__) + protocol = asyncio.StreamReaderProtocol(reader) self.assertIs(protocol._loop, self.loop) + def test_multiple_drain(self): + # See https://github.com/python/cpython/issues/74116 + drained = 0 + + async def drainer(stream): + nonlocal drained + await stream._drain_helper() + drained += 1 + + async def main(): + loop = asyncio.get_running_loop() + stream = asyncio.streams.FlowControlMixin(loop) + stream.pause_writing() + loop.call_later(0.1, stream.resume_writing) + await asyncio.gather(*[drainer(stream) for _ in range(10)]) + self.assertEqual(drained, 10) + + self.loop.run_until_complete(main()) + def test_drain_raises(self): # See http://bugs.python.org/issue25441 diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_subprocess.py python3.10-3.10.12/Lib/test/test_asyncio/test_subprocess.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_subprocess.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_subprocess.py 2023-06-06 22:30:33.000000000 +0000 @@ -401,6 +401,26 @@ self.assertEqual(output, None) self.assertEqual(exitcode, 0) + @unittest.skipIf(sys.platform != 'linux', "Don't have /dev/stdin") + def test_devstdin_input(self): + + async def devstdin_input(message): + code = 'file = open("/dev/stdin"); data = file.read(); print(len(data))' + proc = await asyncio.create_subprocess_exec( + sys.executable, '-c', code, + stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + close_fds=False, + ) + stdout, stderr = await proc.communicate(message) + exitcode = await proc.wait() + return (stdout, exitcode) + + output, exitcode = self.loop.run_until_complete(devstdin_input(b'abc')) + self.assertEqual(output.rstrip(), b'3') + self.assertEqual(exitcode, 0) + def test_cancel_process_wait(self): # Issue #23140: cancel Process.wait() diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_tasks.py python3.10-3.10.12/Lib/test/test_asyncio/test_tasks.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_tasks.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_tasks.py 2023-06-06 22:30:33.000000000 +0000 @@ -210,10 +210,8 @@ a = notmuch() self.addCleanup(a.close) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - asyncio.ensure_future(a) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.ensure_future(a) async def test(): return asyncio.ensure_future(notmuch()) @@ -223,12 +221,10 @@ self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 asyncio.set_event_loop(self.loop) self.addCleanup(asyncio.set_event_loop, None) - with self.assertWarns(DeprecationWarning) as cm: - t = asyncio.ensure_future(notmuch()) - self.assertEqual(cm.warnings[0].filename, __file__) + t = asyncio.ensure_future(notmuch()) self.assertIs(t._loop, self.loop) self.loop.run_until_complete(t) self.assertTrue(t.done()) @@ -247,10 +243,8 @@ a = notmuch() self.addCleanup(a.close) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - asyncio.ensure_future(a) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): + asyncio.ensure_future(a) async def test(): return asyncio.ensure_future(notmuch()) @@ -260,12 +254,10 @@ self.assertTrue(t.done()) self.assertEqual(t.result(), 'ok') - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 asyncio.set_event_loop(self.loop) self.addCleanup(asyncio.set_event_loop, None) - with self.assertWarns(DeprecationWarning) as cm: - t = asyncio.ensure_future(notmuch()) - self.assertEqual(cm.warnings[0].filename, __file__) + t = asyncio.ensure_future(notmuch()) self.assertIs(t._loop, self.loop) self.loop.run_until_complete(t) self.assertTrue(t.done()) @@ -1488,10 +1480,8 @@ self.addCleanup(a.close) futs = asyncio.as_completed([a]) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - list(futs) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + list(futs) def test_as_completed_coroutine_use_running_loop(self): loop = self.new_test_loop() @@ -1507,17 +1497,14 @@ loop.run_until_complete(test()) def test_as_completed_coroutine_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 async def coro(): return 42 loop = self.new_test_loop() asyncio.set_event_loop(loop) self.addCleanup(asyncio.set_event_loop, None) - futs = asyncio.as_completed([coro()]) - with self.assertWarns(DeprecationWarning) as cm: - futs = list(futs) - self.assertEqual(cm.warnings[0].filename, __file__) + futs = list(asyncio.as_completed([coro()])) self.assertEqual(len(futs), 1) self.assertEqual(loop.run_until_complete(futs[0]), 42) @@ -1987,10 +1974,8 @@ inner = coro() self.addCleanup(inner.close) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaisesRegex(RuntimeError, 'There is no current event loop'): - asyncio.shield(inner) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.shield(inner) def test_shield_coroutine_use_running_loop(self): async def coro(): @@ -2004,15 +1989,13 @@ self.assertEqual(res, 42) def test_shield_coroutine_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 async def coro(): return 42 asyncio.set_event_loop(self.loop) self.addCleanup(asyncio.set_event_loop, None) - with self.assertWarns(DeprecationWarning) as cm: - outer = asyncio.shield(coro()) - self.assertEqual(cm.warnings[0].filename, __file__) + outer = asyncio.shield(coro()) self.assertEqual(outer._loop, self.loop) res = self.loop.run_until_complete(outer) self.assertEqual(res, 42) @@ -2950,7 +2933,7 @@ self.assertIsNone(asyncio.current_task(loop=self.loop)) def test_current_task_no_running_loop_implicit(self): - with self.assertRaises(RuntimeError): + with self.assertRaisesRegex(RuntimeError, 'no running event loop'): asyncio.current_task() def test_current_task_with_implicit_loop(self): @@ -3114,10 +3097,8 @@ return asyncio.gather(*args, **kwargs) def test_constructor_empty_sequence_without_loop(self): - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(RuntimeError): - asyncio.gather() - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.gather() def test_constructor_empty_sequence_use_running_loop(self): async def gather(): @@ -3130,12 +3111,10 @@ self.assertEqual(fut.result(), []) def test_constructor_empty_sequence_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 asyncio.set_event_loop(self.one_loop) self.addCleanup(asyncio.set_event_loop, None) - with self.assertWarns(DeprecationWarning) as cm: - fut = asyncio.gather() - self.assertEqual(cm.warnings[0].filename, __file__) + fut = asyncio.gather() self.assertIsInstance(fut, asyncio.Future) self.assertIs(fut._loop, self.one_loop) self._run_loop(self.one_loop) @@ -3223,10 +3202,8 @@ self.addCleanup(gen1.close) gen2 = coro() self.addCleanup(gen2.close) - with self.assertWarns(DeprecationWarning) as cm: - with self.assertRaises(RuntimeError): - asyncio.gather(gen1, gen2) - self.assertEqual(cm.warnings[0].filename, __file__) + with self.assertRaisesRegex(RuntimeError, 'no current event loop'): + asyncio.gather(gen1, gen2) def test_constructor_use_running_loop(self): async def coro(): @@ -3240,16 +3217,14 @@ self.one_loop.run_until_complete(fut) def test_constructor_use_global_loop(self): - # Deprecated in 3.10 + # Deprecated in 3.10.0, undeprecated in 3.10.9 async def coro(): return 'abc' asyncio.set_event_loop(self.other_loop) self.addCleanup(asyncio.set_event_loop, None) gen1 = coro() gen2 = coro() - with self.assertWarns(DeprecationWarning) as cm: - fut = asyncio.gather(gen1, gen2) - self.assertEqual(cm.warnings[0].filename, __file__) + fut = asyncio.gather(gen1, gen2) self.assertIs(fut._loop, self.other_loop) self.other_loop.run_until_complete(fut) diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_unix_events.py python3.10-3.10.12/Lib/test/test_asyncio/test_unix_events.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_unix_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_unix_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -1740,7 +1740,8 @@ def test_child_watcher_replace_mainloop_existing(self): policy = self.create_policy() - loop = policy.get_event_loop() + loop = policy.new_event_loop() + policy.set_event_loop(loop) # Explicitly setup SafeChildWatcher, # default ThreadedChildWatcher has no _loop property diff -Nru python3.10-3.10.7/Lib/test/test_asyncio/test_windows_events.py python3.10-3.10.12/Lib/test/test_asyncio/test_windows_events.py --- python3.10-3.10.7/Lib/test/test_asyncio/test_windows_events.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_asyncio/test_windows_events.py 2023-06-06 22:30:33.000000000 +0000 @@ -239,6 +239,57 @@ self.close_loop(self.loop) self.assertFalse(self.loop.call_exception_handler.called) + def test_address_argument_type_error(self): + # Regression test for https://github.com/python/cpython/issues/98793 + proactor = self.loop._proactor + sock = socket.socket(type=socket.SOCK_DGRAM) + bad_address = None + with self.assertRaises(TypeError): + proactor.connect(sock, bad_address) + with self.assertRaises(TypeError): + proactor.sendto(sock, b'abc', addr=bad_address) + sock.close() + + def test_client_pipe_stat(self): + res = self.loop.run_until_complete(self._test_client_pipe_stat()) + self.assertEqual(res, 'done') + + async def _test_client_pipe_stat(self): + # Regression test for https://github.com/python/cpython/issues/100573 + ADDRESS = r'\\.\pipe\test_client_pipe_stat-%s' % os.getpid() + + async def probe(): + # See https://github.com/python/cpython/pull/100959#discussion_r1068533658 + h = _overlapped.ConnectPipe(ADDRESS) + try: + _winapi.CloseHandle(_overlapped.ConnectPipe(ADDRESS)) + except OSError as e: + if e.winerror != _overlapped.ERROR_PIPE_BUSY: + raise + finally: + _winapi.CloseHandle(h) + + with self.assertRaises(FileNotFoundError): + await probe() + + [server] = await self.loop.start_serving_pipe(asyncio.Protocol, ADDRESS) + self.assertIsInstance(server, windows_events.PipeServer) + + errors = [] + self.loop.set_exception_handler(lambda _, data: errors.append(data)) + + for i in range(5): + await self.loop.create_task(probe()) + + self.assertEqual(len(errors), 0, errors) + + server.close() + + with self.assertRaises(FileNotFoundError): + await probe() + + return "done" + class WinPolicyTests(test_utils.TestCase): diff -Nru python3.10-3.10.7/Lib/test/test_audit.py python3.10-3.10.12/Lib/test/test_audit.py --- python3.10-3.10.7/Lib/test/test_audit.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_audit.py 2023-06-06 22:30:33.000000000 +0000 @@ -16,6 +16,8 @@ class AuditTest(unittest.TestCase): + maxDiff = None + def do_test(self, *args): with subprocess.Popen( [sys.executable, "-X utf8", AUDIT_TESTS_PY, *args], @@ -170,5 +172,34 @@ self.assertEqual(actual, expected) + def test_syslog(self): + syslog = import_helper.import_module("syslog") + + returncode, events, stderr = self.run_python("test_syslog") + if returncode: + self.fail(stderr) + + if support.verbose: + print('Events:', *events, sep='\n ') + + self.assertSequenceEqual( + events, + [('syslog.openlog', ' ', f'python 0 {syslog.LOG_USER}'), + ('syslog.syslog', ' ', f'{syslog.LOG_INFO} test'), + ('syslog.setlogmask', ' ', f'{syslog.LOG_DEBUG}'), + ('syslog.closelog', '', ''), + ('syslog.syslog', ' ', f'{syslog.LOG_INFO} test2'), + ('syslog.openlog', ' ', f'audit-tests.py 0 {syslog.LOG_USER}'), + ('syslog.openlog', ' ', f'audit-tests.py {syslog.LOG_NDELAY} {syslog.LOG_LOCAL0}'), + ('syslog.openlog', ' ', f'None 0 {syslog.LOG_USER}'), + ('syslog.closelog', '', '')] + ) + + def test_not_in_gc(self): + returncode, _, stderr = self.run_python("test_not_in_gc") + if returncode: + self.fail(stderr) + + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_baseexception.py python3.10-3.10.12/Lib/test/test_baseexception.py --- python3.10-3.10.7/Lib/test/test_baseexception.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_baseexception.py 2023-06-06 22:30:33.000000000 +0000 @@ -114,6 +114,31 @@ [repr(exc), exc.__class__.__name__ + '()']) self.interface_test_driver(results) + def test_setstate_refcount_no_crash(self): + # gh-97591: Acquire strong reference before calling tp_hash slot + # in PyObject_SetAttr. + import gc + d = {} + class HashThisKeyWillClearTheDict(str): + def __hash__(self) -> int: + d.clear() + return super().__hash__() + class Value(str): + pass + exc = Exception() + + d[HashThisKeyWillClearTheDict()] = Value() # refcount of Value() is 1 now + + # Exception.__setstate__ should aquire a strong reference of key and + # value in the dict. Otherwise, Value()'s refcount would go below + # zero in the tp_hash call in PyObject_SetAttr(), and it would cause + # crash in GC. + exc.__setstate__(d) # __hash__() is called again here, clearing the dict. + + # This GC would crash if the refcount of Value() goes below zero. + gc.collect() + + class UsageTests(unittest.TestCase): """Test usage of exceptions""" diff -Nru python3.10-3.10.7/Lib/test/test_bdb.py python3.10-3.10.12/Lib/test/test_bdb.py --- python3.10-3.10.7/Lib/test/test_bdb.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_bdb.py 2023-06-06 22:30:33.000000000 +0000 @@ -1203,5 +1203,11 @@ tracer.runcall(tfunc_import) +class TestRegressions(unittest.TestCase): + def test_format_stack_entry_no_lineno(self): + # See gh-101517 + Bdb().format_stack_entry((sys._getframe(), None)) + + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_bool.py python3.10-3.10.12/Lib/test/test_bool.py --- python3.10-3.10.7/Lib/test/test_bool.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_bool.py 2023-06-06 22:30:33.000000000 +0000 @@ -40,6 +40,12 @@ self.assertEqual(float(True), 1.0) self.assertIsNot(float(True), True) + def test_complex(self): + self.assertEqual(complex(False), 0j) + self.assertEqual(complex(False), False) + self.assertEqual(complex(True), 1+0j) + self.assertEqual(complex(True), True) + def test_math(self): self.assertEqual(+False, 0) self.assertIsNot(+False, False) diff -Nru python3.10-3.10.7/Lib/test/test_builtin.py python3.10-3.10.12/Lib/test/test_builtin.py --- python3.10-3.10.7/Lib/test/test_builtin.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_builtin.py 2023-06-06 22:30:33.000000000 +0000 @@ -159,7 +159,7 @@ __import__('string') __import__(name='sys') __import__(name='time', level=0) - self.assertRaises(ImportError, __import__, 'spamspam') + self.assertRaises(ModuleNotFoundError, __import__, 'spamspam') self.assertRaises(TypeError, __import__, 1, 2, 3, 4) self.assertRaises(ValueError, __import__, '') self.assertRaises(TypeError, __import__, 'sys', name='sys') @@ -799,6 +799,16 @@ f2 = filter(filter_char, "abcdeabcde") self.check_iter_pickle(f1, list(f2), proto) + def test_filter_dealloc(self): + # Tests recursive deallocation of nested filter objects using the + # thrashcan mechanism. See gh-102356 for more details. + max_iters = 1000000 + i = filter(bool, range(max_iters)) + for _ in range(max_iters): + i = filter(bool, i) + del i + gc.collect() + def test_getattr(self): self.assertTrue(getattr(sys, 'stdout') is sys.stdout) self.assertRaises(TypeError, getattr, sys, 1) @@ -2248,7 +2258,7 @@ self.assertEqual(A.__module__, __name__) with self.assertRaises(ValueError): type('A\x00B', (), {}) - with self.assertRaises(ValueError): + with self.assertRaises(UnicodeEncodeError): type('A\udcdcB', (), {}) with self.assertRaises(TypeError): type(b'A', (), {}) @@ -2265,7 +2275,7 @@ with self.assertRaises(ValueError): A.__name__ = 'A\x00B' self.assertEqual(A.__name__, 'C') - with self.assertRaises(ValueError): + with self.assertRaises(UnicodeEncodeError): A.__name__ = 'A\udcdcB' self.assertEqual(A.__name__, 'C') with self.assertRaises(TypeError): diff -Nru python3.10-3.10.7/Lib/test/test_calendar.py python3.10-3.10.12/Lib/test/test_calendar.py --- python3.10-3.10.7/Lib/test/test_calendar.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_calendar.py 2023-06-06 22:30:33.000000000 +0000 @@ -568,11 +568,15 @@ try: # formatweekday uses different day names based on the available width. cal = calendar.LocaleTextCalendar(locale='en_US') + # For really short widths, the abbreviated name is truncated. + self.assertEqual(cal.formatweekday(0, 1), "M") + self.assertEqual(cal.formatweekday(0, 2), "Mo") # For short widths, a centered, abbreviated name is used. + self.assertEqual(cal.formatweekday(0, 3), "Mon") self.assertEqual(cal.formatweekday(0, 5), " Mon ") - # For really short widths, even the abbreviated name is truncated. - self.assertEqual(cal.formatweekday(0, 2), "Mo") + self.assertEqual(cal.formatweekday(0, 8), " Mon ") # For long widths, the full day name is used. + self.assertEqual(cal.formatweekday(0, 9), " Monday ") self.assertEqual(cal.formatweekday(0, 10), " Monday ") except locale.Error: raise unittest.SkipTest('cannot set the en_US locale') diff -Nru python3.10-3.10.7/Lib/test/test_call.py python3.10-3.10.12/Lib/test/test_call.py --- python3.10-3.10.7/Lib/test/test_call.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_call.py 2023-06-06 22:30:33.000000000 +0000 @@ -546,7 +546,7 @@ self.kwargs.clear() gc.collect() return 0 - x = IntWithDict(dont_inherit=IntWithDict()) + x = IntWithDict(optimize=IntWithDict()) # We test the argument handling of "compile" here, the compilation # itself is not relevant. When we pass flags=x below, x.__index__() is # called, which changes the keywords dict. diff -Nru python3.10-3.10.7/Lib/test/test_capi/__init__.py python3.10-3.10.12/Lib/test/test_capi/__init__.py --- python3.10-3.10.7/Lib/test/test_capi/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,5 @@ +import os +from test.support import load_package_tests + +def load_tests(*args): + return load_package_tests(os.path.dirname(__file__), *args) diff -Nru python3.10-3.10.7/Lib/test/test_capi/__main__.py python3.10-3.10.12/Lib/test/test_capi/__main__.py --- python3.10-3.10.7/Lib/test/test_capi/__main__.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/__main__.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,3 @@ +import unittest + +unittest.main('test.test_capi') diff -Nru python3.10-3.10.7/Lib/test/test_capi/test_getargs.py python3.10-3.10.12/Lib/test/test_capi/test_getargs.py --- python3.10-3.10.7/Lib/test/test_capi/test_getargs.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/test_getargs.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,1322 @@ +import unittest +import math +import string +import sys +import warnings +from test import support +from test.support import import_helper +from test.support import warnings_helper +# Skip this test if the _testcapi module isn't available. +_testcapi = import_helper.import_module('_testcapi') +from _testcapi import getargs_keywords, getargs_keyword_only + +# > How about the following counterproposal. This also changes some of +# > the other format codes to be a little more regular. +# > +# > Code C type Range check +# > +# > b unsigned char 0..UCHAR_MAX +# > h signed short SHRT_MIN..SHRT_MAX +# > B unsigned char none ** +# > H unsigned short none ** +# > k * unsigned long none +# > I * unsigned int 0..UINT_MAX +# +# +# > i int INT_MIN..INT_MAX +# > l long LONG_MIN..LONG_MAX +# +# > K * unsigned long long none +# > L long long LLONG_MIN..LLONG_MAX +# +# > Notes: +# > +# > * New format codes. +# > +# > ** Changed from previous "range-and-a-half" to "none"; the +# > range-and-a-half checking wasn't particularly useful. +# +# Plus a C API or two, e.g. PyLong_AsUnsignedLongMask() -> +# unsigned long and PyLong_AsUnsignedLongLongMask() -> unsigned +# long long (if that exists). + +LARGE = 0x7FFFFFFF +VERY_LARGE = 0xFF0000121212121212121242 + +from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \ + INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \ + SHRT_MIN, SHRT_MAX, FLT_MIN, FLT_MAX, DBL_MIN, DBL_MAX + +DBL_MAX_EXP = sys.float_info.max_exp +INF = float('inf') +NAN = float('nan') + +# fake, they are not defined in Python's header files +LLONG_MAX = 2**63-1 +LLONG_MIN = -2**63 +ULLONG_MAX = 2**64-1 + +class Index: + def __index__(self): + return 99 + +class IndexIntSubclass(int): + def __index__(self): + return 99 + +class BadIndex: + def __index__(self): + return 1.0 + +class BadIndex2: + def __index__(self): + return True + +class BadIndex3(int): + def __index__(self): + return True + + +class Int: + def __int__(self): + return 99 + +class IntSubclass(int): + def __int__(self): + return 99 + +class BadInt: + def __int__(self): + return 1.0 + +class BadInt2: + def __int__(self): + return True + +class BadInt3(int): + def __int__(self): + return True + + +class Float: + def __float__(self): + return 4.25 + +class FloatSubclass(float): + pass + +class FloatSubclass2(float): + def __float__(self): + return 4.25 + +class BadFloat: + def __float__(self): + return 687 + +class BadFloat2: + def __float__(self): + return FloatSubclass(4.25) + +class BadFloat3(float): + def __float__(self): + return FloatSubclass(4.25) + + +class Complex: + def __complex__(self): + return 4.25+0.5j + +class ComplexSubclass(complex): + pass + +class ComplexSubclass2(complex): + def __complex__(self): + return 4.25+0.5j + +class BadComplex: + def __complex__(self): + return 1.25 + +class BadComplex2: + def __complex__(self): + return ComplexSubclass(4.25+0.5j) + +class BadComplex3(complex): + def __complex__(self): + return ComplexSubclass(4.25+0.5j) + + +class TupleSubclass(tuple): + pass + +class DictSubclass(dict): + pass + + +class Unsigned_TestCase(unittest.TestCase): + def test_b(self): + from _testcapi import getargs_b + # b returns 'unsigned char', and does range checking (0 ... UCHAR_MAX) + self.assertRaises(TypeError, getargs_b, 3.14) + self.assertEqual(99, getargs_b(Index())) + self.assertEqual(0, getargs_b(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_b, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_b(BadIndex2())) + self.assertEqual(0, getargs_b(BadIndex3())) + self.assertRaises(TypeError, getargs_b, Int()) + self.assertEqual(0, getargs_b(IntSubclass())) + self.assertRaises(TypeError, getargs_b, BadInt()) + self.assertRaises(TypeError, getargs_b, BadInt2()) + self.assertEqual(0, getargs_b(BadInt3())) + + self.assertRaises(OverflowError, getargs_b, -1) + self.assertEqual(0, getargs_b(0)) + self.assertEqual(UCHAR_MAX, getargs_b(UCHAR_MAX)) + self.assertRaises(OverflowError, getargs_b, UCHAR_MAX + 1) + + self.assertEqual(42, getargs_b(42)) + self.assertRaises(OverflowError, getargs_b, VERY_LARGE) + + def test_B(self): + from _testcapi import getargs_B + # B returns 'unsigned char', no range checking + self.assertRaises(TypeError, getargs_B, 3.14) + self.assertEqual(99, getargs_B(Index())) + self.assertEqual(0, getargs_B(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_B, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_B(BadIndex2())) + self.assertEqual(0, getargs_B(BadIndex3())) + self.assertRaises(TypeError, getargs_B, Int()) + self.assertEqual(0, getargs_B(IntSubclass())) + self.assertRaises(TypeError, getargs_B, BadInt()) + self.assertRaises(TypeError, getargs_B, BadInt2()) + self.assertEqual(0, getargs_B(BadInt3())) + + self.assertEqual(UCHAR_MAX, getargs_B(-1)) + self.assertEqual(0, getargs_B(0)) + self.assertEqual(UCHAR_MAX, getargs_B(UCHAR_MAX)) + self.assertEqual(0, getargs_B(UCHAR_MAX+1)) + + self.assertEqual(42, getargs_B(42)) + self.assertEqual(UCHAR_MAX & VERY_LARGE, getargs_B(VERY_LARGE)) + + def test_H(self): + from _testcapi import getargs_H + # H returns 'unsigned short', no range checking + self.assertRaises(TypeError, getargs_H, 3.14) + self.assertEqual(99, getargs_H(Index())) + self.assertEqual(0, getargs_H(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_H, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_H(BadIndex2())) + self.assertEqual(0, getargs_H(BadIndex3())) + self.assertRaises(TypeError, getargs_H, Int()) + self.assertEqual(0, getargs_H(IntSubclass())) + self.assertRaises(TypeError, getargs_H, BadInt()) + self.assertRaises(TypeError, getargs_H, BadInt2()) + self.assertEqual(0, getargs_H(BadInt3())) + + self.assertEqual(USHRT_MAX, getargs_H(-1)) + self.assertEqual(0, getargs_H(0)) + self.assertEqual(USHRT_MAX, getargs_H(USHRT_MAX)) + self.assertEqual(0, getargs_H(USHRT_MAX+1)) + + self.assertEqual(42, getargs_H(42)) + + self.assertEqual(VERY_LARGE & USHRT_MAX, getargs_H(VERY_LARGE)) + + def test_I(self): + from _testcapi import getargs_I + # I returns 'unsigned int', no range checking + self.assertRaises(TypeError, getargs_I, 3.14) + self.assertEqual(99, getargs_I(Index())) + self.assertEqual(0, getargs_I(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_I, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_I(BadIndex2())) + self.assertEqual(0, getargs_I(BadIndex3())) + self.assertRaises(TypeError, getargs_I, Int()) + self.assertEqual(0, getargs_I(IntSubclass())) + self.assertRaises(TypeError, getargs_I, BadInt()) + self.assertRaises(TypeError, getargs_I, BadInt2()) + self.assertEqual(0, getargs_I(BadInt3())) + + self.assertEqual(UINT_MAX, getargs_I(-1)) + self.assertEqual(0, getargs_I(0)) + self.assertEqual(UINT_MAX, getargs_I(UINT_MAX)) + self.assertEqual(0, getargs_I(UINT_MAX+1)) + + self.assertEqual(42, getargs_I(42)) + + self.assertEqual(VERY_LARGE & UINT_MAX, getargs_I(VERY_LARGE)) + + def test_k(self): + from _testcapi import getargs_k + # k returns 'unsigned long', no range checking + # it does not accept float, or instances with __int__ + self.assertRaises(TypeError, getargs_k, 3.14) + self.assertRaises(TypeError, getargs_k, Index()) + self.assertEqual(0, getargs_k(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_k, BadIndex()) + self.assertRaises(TypeError, getargs_k, BadIndex2()) + self.assertEqual(0, getargs_k(BadIndex3())) + self.assertRaises(TypeError, getargs_k, Int()) + self.assertEqual(0, getargs_k(IntSubclass())) + self.assertRaises(TypeError, getargs_k, BadInt()) + self.assertRaises(TypeError, getargs_k, BadInt2()) + self.assertEqual(0, getargs_k(BadInt3())) + + self.assertEqual(ULONG_MAX, getargs_k(-1)) + self.assertEqual(0, getargs_k(0)) + self.assertEqual(ULONG_MAX, getargs_k(ULONG_MAX)) + self.assertEqual(0, getargs_k(ULONG_MAX+1)) + + self.assertEqual(42, getargs_k(42)) + + self.assertEqual(VERY_LARGE & ULONG_MAX, getargs_k(VERY_LARGE)) + +class Signed_TestCase(unittest.TestCase): + def test_h(self): + from _testcapi import getargs_h + # h returns 'short', and does range checking (SHRT_MIN ... SHRT_MAX) + self.assertRaises(TypeError, getargs_h, 3.14) + self.assertEqual(99, getargs_h(Index())) + self.assertEqual(0, getargs_h(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_h, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_h(BadIndex2())) + self.assertEqual(0, getargs_h(BadIndex3())) + self.assertRaises(TypeError, getargs_h, Int()) + self.assertEqual(0, getargs_h(IntSubclass())) + self.assertRaises(TypeError, getargs_h, BadInt()) + self.assertRaises(TypeError, getargs_h, BadInt2()) + self.assertEqual(0, getargs_h(BadInt3())) + + self.assertRaises(OverflowError, getargs_h, SHRT_MIN-1) + self.assertEqual(SHRT_MIN, getargs_h(SHRT_MIN)) + self.assertEqual(SHRT_MAX, getargs_h(SHRT_MAX)) + self.assertRaises(OverflowError, getargs_h, SHRT_MAX+1) + + self.assertEqual(42, getargs_h(42)) + self.assertRaises(OverflowError, getargs_h, VERY_LARGE) + + def test_i(self): + from _testcapi import getargs_i + # i returns 'int', and does range checking (INT_MIN ... INT_MAX) + self.assertRaises(TypeError, getargs_i, 3.14) + self.assertEqual(99, getargs_i(Index())) + self.assertEqual(0, getargs_i(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_i, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_i(BadIndex2())) + self.assertEqual(0, getargs_i(BadIndex3())) + self.assertRaises(TypeError, getargs_i, Int()) + self.assertEqual(0, getargs_i(IntSubclass())) + self.assertRaises(TypeError, getargs_i, BadInt()) + self.assertRaises(TypeError, getargs_i, BadInt2()) + self.assertEqual(0, getargs_i(BadInt3())) + + self.assertRaises(OverflowError, getargs_i, INT_MIN-1) + self.assertEqual(INT_MIN, getargs_i(INT_MIN)) + self.assertEqual(INT_MAX, getargs_i(INT_MAX)) + self.assertRaises(OverflowError, getargs_i, INT_MAX+1) + + self.assertEqual(42, getargs_i(42)) + self.assertRaises(OverflowError, getargs_i, VERY_LARGE) + + def test_l(self): + from _testcapi import getargs_l + # l returns 'long', and does range checking (LONG_MIN ... LONG_MAX) + self.assertRaises(TypeError, getargs_l, 3.14) + self.assertEqual(99, getargs_l(Index())) + self.assertEqual(0, getargs_l(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_l, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_l(BadIndex2())) + self.assertEqual(0, getargs_l(BadIndex3())) + self.assertRaises(TypeError, getargs_l, Int()) + self.assertEqual(0, getargs_l(IntSubclass())) + self.assertRaises(TypeError, getargs_l, BadInt()) + self.assertRaises(TypeError, getargs_l, BadInt2()) + self.assertEqual(0, getargs_l(BadInt3())) + + self.assertRaises(OverflowError, getargs_l, LONG_MIN-1) + self.assertEqual(LONG_MIN, getargs_l(LONG_MIN)) + self.assertEqual(LONG_MAX, getargs_l(LONG_MAX)) + self.assertRaises(OverflowError, getargs_l, LONG_MAX+1) + + self.assertEqual(42, getargs_l(42)) + self.assertRaises(OverflowError, getargs_l, VERY_LARGE) + + def test_n(self): + from _testcapi import getargs_n + # n returns 'Py_ssize_t', and does range checking + # (PY_SSIZE_T_MIN ... PY_SSIZE_T_MAX) + self.assertRaises(TypeError, getargs_n, 3.14) + self.assertEqual(99, getargs_n(Index())) + self.assertEqual(0, getargs_n(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_n, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_n(BadIndex2())) + self.assertEqual(0, getargs_n(BadIndex3())) + self.assertRaises(TypeError, getargs_n, Int()) + self.assertEqual(0, getargs_n(IntSubclass())) + self.assertRaises(TypeError, getargs_n, BadInt()) + self.assertRaises(TypeError, getargs_n, BadInt2()) + self.assertEqual(0, getargs_n(BadInt3())) + + self.assertRaises(OverflowError, getargs_n, PY_SSIZE_T_MIN-1) + self.assertEqual(PY_SSIZE_T_MIN, getargs_n(PY_SSIZE_T_MIN)) + self.assertEqual(PY_SSIZE_T_MAX, getargs_n(PY_SSIZE_T_MAX)) + self.assertRaises(OverflowError, getargs_n, PY_SSIZE_T_MAX+1) + + self.assertEqual(42, getargs_n(42)) + self.assertRaises(OverflowError, getargs_n, VERY_LARGE) + + +class LongLong_TestCase(unittest.TestCase): + def test_L(self): + from _testcapi import getargs_L + # L returns 'long long', and does range checking (LLONG_MIN + # ... LLONG_MAX) + self.assertRaises(TypeError, getargs_L, 3.14) + self.assertRaises(TypeError, getargs_L, "Hello") + self.assertEqual(99, getargs_L(Index())) + self.assertEqual(0, getargs_L(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_L, BadIndex()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(1, getargs_L(BadIndex2())) + self.assertEqual(0, getargs_L(BadIndex3())) + self.assertRaises(TypeError, getargs_L, Int()) + self.assertEqual(0, getargs_L(IntSubclass())) + self.assertRaises(TypeError, getargs_L, BadInt()) + self.assertRaises(TypeError, getargs_L, BadInt2()) + self.assertEqual(0, getargs_L(BadInt3())) + + self.assertRaises(OverflowError, getargs_L, LLONG_MIN-1) + self.assertEqual(LLONG_MIN, getargs_L(LLONG_MIN)) + self.assertEqual(LLONG_MAX, getargs_L(LLONG_MAX)) + self.assertRaises(OverflowError, getargs_L, LLONG_MAX+1) + + self.assertEqual(42, getargs_L(42)) + self.assertRaises(OverflowError, getargs_L, VERY_LARGE) + + def test_K(self): + from _testcapi import getargs_K + # K return 'unsigned long long', no range checking + self.assertRaises(TypeError, getargs_K, 3.14) + self.assertRaises(TypeError, getargs_K, Index()) + self.assertEqual(0, getargs_K(IndexIntSubclass())) + self.assertRaises(TypeError, getargs_K, BadIndex()) + self.assertRaises(TypeError, getargs_K, BadIndex2()) + self.assertEqual(0, getargs_K(BadIndex3())) + self.assertRaises(TypeError, getargs_K, Int()) + self.assertEqual(0, getargs_K(IntSubclass())) + self.assertRaises(TypeError, getargs_K, BadInt()) + self.assertRaises(TypeError, getargs_K, BadInt2()) + self.assertEqual(0, getargs_K(BadInt3())) + + self.assertEqual(ULLONG_MAX, getargs_K(ULLONG_MAX)) + self.assertEqual(0, getargs_K(0)) + self.assertEqual(0, getargs_K(ULLONG_MAX+1)) + + self.assertEqual(42, getargs_K(42)) + + self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE)) + + +class Float_TestCase(unittest.TestCase): + def assertEqualWithSign(self, actual, expected): + self.assertEqual(actual, expected) + self.assertEqual(math.copysign(1, actual), math.copysign(1, expected)) + + def test_f(self): + from _testcapi import getargs_f + self.assertEqual(getargs_f(4.25), 4.25) + self.assertEqual(getargs_f(4), 4.0) + self.assertRaises(TypeError, getargs_f, 4.25+0j) + self.assertEqual(getargs_f(Float()), 4.25) + self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5) + self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5) + self.assertRaises(TypeError, getargs_f, BadFloat()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_f(BadFloat2()), 4.25) + self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5) + self.assertEqual(getargs_f(Index()), 99.0) + self.assertRaises(TypeError, getargs_f, Int()) + + for x in (FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX, INF, -INF): + self.assertEqual(getargs_f(x), x) + if FLT_MAX < DBL_MAX: + self.assertEqual(getargs_f(DBL_MAX), INF) + self.assertEqual(getargs_f(-DBL_MAX), -INF) + if FLT_MIN > DBL_MIN: + self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0) + self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0) + self.assertEqualWithSign(getargs_f(0.0), 0.0) + self.assertEqualWithSign(getargs_f(-0.0), -0.0) + r = getargs_f(NAN) + self.assertNotEqual(r, r) + + @support.requires_IEEE_754 + def test_f_rounding(self): + from _testcapi import getargs_f + self.assertEqual(getargs_f(3.40282356e38), FLT_MAX) + self.assertEqual(getargs_f(-3.40282356e38), -FLT_MAX) + + def test_d(self): + from _testcapi import getargs_d + self.assertEqual(getargs_d(4.25), 4.25) + self.assertEqual(getargs_d(4), 4.0) + self.assertRaises(TypeError, getargs_d, 4.25+0j) + self.assertEqual(getargs_d(Float()), 4.25) + self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5) + self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5) + self.assertRaises(TypeError, getargs_d, BadFloat()) + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_d(BadFloat2()), 4.25) + self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5) + self.assertEqual(getargs_d(Index()), 99.0) + self.assertRaises(TypeError, getargs_d, Int()) + + for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF): + self.assertEqual(getargs_d(x), x) + self.assertRaises(OverflowError, getargs_d, 1< 1 + self.assertEqual(getargs_c(b'a'), 97) + self.assertEqual(getargs_c(bytearray(b'a')), 97) + self.assertRaises(TypeError, getargs_c, memoryview(b'a')) + self.assertRaises(TypeError, getargs_c, 's') + self.assertRaises(TypeError, getargs_c, 97) + self.assertRaises(TypeError, getargs_c, None) + + def test_y(self): + from _testcapi import getargs_y + self.assertRaises(TypeError, getargs_y, 'abc\xe9') + self.assertEqual(getargs_y(b'bytes'), b'bytes') + self.assertRaises(ValueError, getargs_y, b'nul:\0') + self.assertRaises(TypeError, getargs_y, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_y, memoryview(b'memoryview')) + self.assertRaises(TypeError, getargs_y, None) + + def test_y_star(self): + from _testcapi import getargs_y_star + self.assertRaises(TypeError, getargs_y_star, 'abc\xe9') + self.assertEqual(getargs_y_star(b'bytes'), b'bytes') + self.assertEqual(getargs_y_star(b'nul:\0'), b'nul:\0') + self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray') + self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview') + self.assertRaises(TypeError, getargs_y_star, None) + + def test_y_hash(self): + from _testcapi import getargs_y_hash + self.assertRaises(TypeError, getargs_y_hash, 'abc\xe9') + self.assertEqual(getargs_y_hash(b'bytes'), b'bytes') + self.assertEqual(getargs_y_hash(b'nul:\0'), b'nul:\0') + self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview')) + self.assertRaises(TypeError, getargs_y_hash, None) + + def test_w_star(self): + # getargs_w_star() modifies first and last byte + from _testcapi import getargs_w_star + self.assertRaises(TypeError, getargs_w_star, 'abc\xe9') + self.assertRaises(TypeError, getargs_w_star, b'bytes') + self.assertRaises(TypeError, getargs_w_star, b'nul:\0') + self.assertRaises(TypeError, getargs_w_star, memoryview(b'bytes')) + buf = bytearray(b'bytearray') + self.assertEqual(getargs_w_star(buf), b'[ytearra]') + self.assertEqual(buf, bytearray(b'[ytearra]')) + buf = bytearray(b'memoryview') + self.assertEqual(getargs_w_star(memoryview(buf)), b'[emoryvie]') + self.assertEqual(buf, bytearray(b'[emoryvie]')) + self.assertRaises(TypeError, getargs_w_star, None) + + +class String_TestCase(unittest.TestCase): + def test_C(self): + from _testcapi import getargs_C + self.assertRaises(TypeError, getargs_C, 'abc') # len > 1 + self.assertEqual(getargs_C('a'), 97) + self.assertEqual(getargs_C('\u20ac'), 0x20ac) + self.assertEqual(getargs_C('\U0001f40d'), 0x1f40d) + self.assertRaises(TypeError, getargs_C, b'a') + self.assertRaises(TypeError, getargs_C, bytearray(b'a')) + self.assertRaises(TypeError, getargs_C, memoryview(b'a')) + self.assertRaises(TypeError, getargs_C, 97) + self.assertRaises(TypeError, getargs_C, None) + + def test_s(self): + from _testcapi import getargs_s + self.assertEqual(getargs_s('abc\xe9'), b'abc\xc3\xa9') + self.assertRaises(ValueError, getargs_s, 'nul:\0') + self.assertRaises(TypeError, getargs_s, b'bytes') + self.assertRaises(TypeError, getargs_s, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_s, memoryview(b'memoryview')) + self.assertRaises(TypeError, getargs_s, None) + + def test_s_star(self): + from _testcapi import getargs_s_star + self.assertEqual(getargs_s_star('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_s_star('nul:\0'), b'nul:\0') + self.assertEqual(getargs_s_star(b'bytes'), b'bytes') + self.assertEqual(getargs_s_star(bytearray(b'bytearray')), b'bytearray') + self.assertEqual(getargs_s_star(memoryview(b'memoryview')), b'memoryview') + self.assertRaises(TypeError, getargs_s_star, None) + + def test_s_hash(self): + from _testcapi import getargs_s_hash + self.assertEqual(getargs_s_hash('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_s_hash('nul:\0'), b'nul:\0') + self.assertEqual(getargs_s_hash(b'bytes'), b'bytes') + self.assertRaises(TypeError, getargs_s_hash, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_s_hash, memoryview(b'memoryview')) + self.assertRaises(TypeError, getargs_s_hash, None) + + def test_s_hash_int(self): + # "s#" without PY_SSIZE_T_CLEAN defined. + from _testcapi import getargs_s_hash_int + from _testcapi import getargs_s_hash_int2 + buf = bytearray([1, 2]) + self.assertRaises(SystemError, getargs_s_hash_int, buf, "abc") + self.assertRaises(SystemError, getargs_s_hash_int, buf, x=42) + self.assertRaises(SystemError, getargs_s_hash_int, buf, x="abc") + self.assertRaises(SystemError, getargs_s_hash_int2, buf, ("abc",)) + self.assertRaises(SystemError, getargs_s_hash_int2, buf, x=42) + self.assertRaises(SystemError, getargs_s_hash_int2, buf, x="abc") + buf.append(3) # still mutable -- not locked by a buffer export + # getargs_s_hash_int(buf) may not raise SystemError because skipitem() + # is not called. But it is an implementation detail. + # getargs_s_hash_int(buf) + # getargs_s_hash_int2(buf) + + def test_z(self): + from _testcapi import getargs_z + self.assertEqual(getargs_z('abc\xe9'), b'abc\xc3\xa9') + self.assertRaises(ValueError, getargs_z, 'nul:\0') + self.assertRaises(TypeError, getargs_z, b'bytes') + self.assertRaises(TypeError, getargs_z, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_z, memoryview(b'memoryview')) + self.assertIsNone(getargs_z(None)) + + def test_z_star(self): + from _testcapi import getargs_z_star + self.assertEqual(getargs_z_star('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_z_star('nul:\0'), b'nul:\0') + self.assertEqual(getargs_z_star(b'bytes'), b'bytes') + self.assertEqual(getargs_z_star(bytearray(b'bytearray')), b'bytearray') + self.assertEqual(getargs_z_star(memoryview(b'memoryview')), b'memoryview') + self.assertIsNone(getargs_z_star(None)) + + def test_z_hash(self): + from _testcapi import getargs_z_hash + self.assertEqual(getargs_z_hash('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_z_hash('nul:\0'), b'nul:\0') + self.assertEqual(getargs_z_hash(b'bytes'), b'bytes') + self.assertRaises(TypeError, getargs_z_hash, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_z_hash, memoryview(b'memoryview')) + self.assertIsNone(getargs_z_hash(None)) + + def test_es(self): + from _testcapi import getargs_es + self.assertEqual(getargs_es('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_es('abc\xe9', 'latin1'), b'abc\xe9') + self.assertRaises(UnicodeEncodeError, getargs_es, 'abc\xe9', 'ascii') + self.assertRaises(LookupError, getargs_es, 'abc\xe9', 'spam') + self.assertRaises(TypeError, getargs_es, b'bytes', 'latin1') + self.assertRaises(TypeError, getargs_es, bytearray(b'bytearray'), 'latin1') + self.assertRaises(TypeError, getargs_es, memoryview(b'memoryview'), 'latin1') + self.assertRaises(TypeError, getargs_es, None, 'latin1') + self.assertRaises(TypeError, getargs_es, 'nul:\0', 'latin1') + + def test_et(self): + from _testcapi import getargs_et + self.assertEqual(getargs_et('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_et('abc\xe9', 'latin1'), b'abc\xe9') + self.assertRaises(UnicodeEncodeError, getargs_et, 'abc\xe9', 'ascii') + self.assertRaises(LookupError, getargs_et, 'abc\xe9', 'spam') + self.assertEqual(getargs_et(b'bytes', 'latin1'), b'bytes') + self.assertEqual(getargs_et(bytearray(b'bytearray'), 'latin1'), b'bytearray') + self.assertRaises(TypeError, getargs_et, memoryview(b'memoryview'), 'latin1') + self.assertRaises(TypeError, getargs_et, None, 'latin1') + self.assertRaises(TypeError, getargs_et, 'nul:\0', 'latin1') + self.assertRaises(TypeError, getargs_et, b'nul:\0', 'latin1') + self.assertRaises(TypeError, getargs_et, bytearray(b'nul:\0'), 'latin1') + + def test_es_hash(self): + from _testcapi import getargs_es_hash + self.assertEqual(getargs_es_hash('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_es_hash('abc\xe9', 'latin1'), b'abc\xe9') + self.assertRaises(UnicodeEncodeError, getargs_es_hash, 'abc\xe9', 'ascii') + self.assertRaises(LookupError, getargs_es_hash, 'abc\xe9', 'spam') + self.assertRaises(TypeError, getargs_es_hash, b'bytes', 'latin1') + self.assertRaises(TypeError, getargs_es_hash, bytearray(b'bytearray'), 'latin1') + self.assertRaises(TypeError, getargs_es_hash, memoryview(b'memoryview'), 'latin1') + self.assertRaises(TypeError, getargs_es_hash, None, 'latin1') + self.assertEqual(getargs_es_hash('nul:\0', 'latin1'), b'nul:\0') + + buf = bytearray(b'x'*8) + self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9') + self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx')) + buf = bytearray(b'x'*5) + self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9') + self.assertEqual(buf, bytearray(b'abc\xe9\x00')) + buf = bytearray(b'x'*4) + self.assertRaises(ValueError, getargs_es_hash, 'abc\xe9', 'latin1', buf) + self.assertEqual(buf, bytearray(b'x'*4)) + buf = bytearray() + self.assertRaises(ValueError, getargs_es_hash, 'abc\xe9', 'latin1', buf) + + def test_et_hash(self): + from _testcapi import getargs_et_hash + self.assertEqual(getargs_et_hash('abc\xe9'), b'abc\xc3\xa9') + self.assertEqual(getargs_et_hash('abc\xe9', 'latin1'), b'abc\xe9') + self.assertRaises(UnicodeEncodeError, getargs_et_hash, 'abc\xe9', 'ascii') + self.assertRaises(LookupError, getargs_et_hash, 'abc\xe9', 'spam') + self.assertEqual(getargs_et_hash(b'bytes', 'latin1'), b'bytes') + self.assertEqual(getargs_et_hash(bytearray(b'bytearray'), 'latin1'), b'bytearray') + self.assertRaises(TypeError, getargs_et_hash, memoryview(b'memoryview'), 'latin1') + self.assertRaises(TypeError, getargs_et_hash, None, 'latin1') + self.assertEqual(getargs_et_hash('nul:\0', 'latin1'), b'nul:\0') + self.assertEqual(getargs_et_hash(b'nul:\0', 'latin1'), b'nul:\0') + self.assertEqual(getargs_et_hash(bytearray(b'nul:\0'), 'latin1'), b'nul:\0') + + buf = bytearray(b'x'*8) + self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9') + self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx')) + buf = bytearray(b'x'*5) + self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9') + self.assertEqual(buf, bytearray(b'abc\xe9\x00')) + buf = bytearray(b'x'*4) + self.assertRaises(ValueError, getargs_et_hash, 'abc\xe9', 'latin1', buf) + self.assertEqual(buf, bytearray(b'x'*4)) + buf = bytearray() + self.assertRaises(ValueError, getargs_et_hash, 'abc\xe9', 'latin1', buf) + + @support.requires_legacy_unicode_capi + def test_u(self): + from _testcapi import getargs_u + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9') + with self.assertWarns(DeprecationWarning): + self.assertRaises(ValueError, getargs_u, 'nul:\0') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u, b'bytes') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u, None) + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + self.assertRaises(DeprecationWarning, getargs_u, 'abc\xe9') + + @support.requires_legacy_unicode_capi + def test_u_hash(self): + from _testcapi import getargs_u_hash + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_u_hash('abc\xe9'), 'abc\xe9') + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_u_hash('nul:\0'), 'nul:\0') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u_hash, b'bytes') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u_hash, bytearray(b'bytearray')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u_hash, memoryview(b'memoryview')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_u_hash, None) + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + self.assertRaises(DeprecationWarning, getargs_u_hash, 'abc\xe9') + + @support.requires_legacy_unicode_capi + def test_Z(self): + from _testcapi import getargs_Z + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9') + with self.assertWarns(DeprecationWarning): + self.assertRaises(ValueError, getargs_Z, 'nul:\0') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z, b'bytes') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview')) + with self.assertWarns(DeprecationWarning): + self.assertIsNone(getargs_Z(None)) + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + self.assertRaises(DeprecationWarning, getargs_Z, 'abc\xe9') + + @support.requires_legacy_unicode_capi + def test_Z_hash(self): + from _testcapi import getargs_Z_hash + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_Z_hash('abc\xe9'), 'abc\xe9') + with self.assertWarns(DeprecationWarning): + self.assertEqual(getargs_Z_hash('nul:\0'), 'nul:\0') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z_hash, b'bytes') + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z_hash, bytearray(b'bytearray')) + with self.assertWarns(DeprecationWarning): + self.assertRaises(TypeError, getargs_Z_hash, memoryview(b'memoryview')) + with self.assertWarns(DeprecationWarning): + self.assertIsNone(getargs_Z_hash(None)) + with warnings.catch_warnings(): + warnings.simplefilter('error', DeprecationWarning) + self.assertRaises(DeprecationWarning, getargs_Z_hash, 'abc\xe9') + + def test_gh_99240_clear_args(self): + from _testcapi import gh_99240_clear_args + self.assertRaises(TypeError, gh_99240_clear_args, 'a', '\0b') + + +class Object_TestCase(unittest.TestCase): + def test_S(self): + from _testcapi import getargs_S + obj = b'bytes' + self.assertIs(getargs_S(obj), obj) + self.assertRaises(TypeError, getargs_S, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_S, 'str') + self.assertRaises(TypeError, getargs_S, None) + self.assertRaises(TypeError, getargs_S, memoryview(obj)) + + def test_Y(self): + from _testcapi import getargs_Y + obj = bytearray(b'bytearray') + self.assertIs(getargs_Y(obj), obj) + self.assertRaises(TypeError, getargs_Y, b'bytes') + self.assertRaises(TypeError, getargs_Y, 'str') + self.assertRaises(TypeError, getargs_Y, None) + self.assertRaises(TypeError, getargs_Y, memoryview(obj)) + + def test_U(self): + from _testcapi import getargs_U + obj = 'str' + self.assertIs(getargs_U(obj), obj) + self.assertRaises(TypeError, getargs_U, b'bytes') + self.assertRaises(TypeError, getargs_U, bytearray(b'bytearray')) + self.assertRaises(TypeError, getargs_U, None) + + +# Bug #6012 +class Test6012(unittest.TestCase): + def test(self): + self.assertEqual(_testcapi.argparsing("Hello", "World"), 1) + + +class SkipitemTest(unittest.TestCase): + + # u, and Z raises DeprecationWarning + @warnings_helper.ignore_warnings(category=DeprecationWarning) + def test_skipitem(self): + """ + If this test failed, you probably added a new "format unit" + in Python/getargs.c, but neglected to update our poor friend + skipitem() in the same file. (If so, shame on you!) + + With a few exceptions**, this function brute-force tests all + printable ASCII*** characters (32 to 126 inclusive) as format units, + checking to see that PyArg_ParseTupleAndKeywords() return consistent + errors both when the unit is attempted to be used and when it is + skipped. If the format unit doesn't exist, we'll get one of two + specific error messages (one for used, one for skipped); if it does + exist we *won't* get that error--we'll get either no error or some + other error. If we get the specific "does not exist" error for one + test and not for the other, there's a mismatch, and the test fails. + + ** Some format units have special funny semantics and it would + be difficult to accommodate them here. Since these are all + well-established and properly skipped in skipitem() we can + get away with not testing them--this test is really intended + to catch *new* format units. + + *** Python C source files must be ASCII. Therefore it's impossible + to have non-ASCII format units. + + """ + empty_tuple = () + tuple_1 = (0,) + dict_b = {'b':1} + keywords = ["a", "b"] + + for i in range(32, 127): + c = chr(i) + + # skip parentheses, the error reporting is inconsistent about them + # skip 'e', it's always a two-character code + # skip '|' and '$', they don't represent arguments anyway + if c in '()e|$': + continue + + # test the format unit when not skipped + format = c + "i" + try: + _testcapi.parse_tuple_and_keywords(tuple_1, dict_b, + format, keywords) + when_not_skipped = False + except SystemError as e: + s = "argument 1 (impossible)" + when_not_skipped = (str(e) == s) + except TypeError: + when_not_skipped = False + + # test the format unit when skipped + optional_format = "|" + format + try: + _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b, + optional_format, keywords) + when_skipped = False + except SystemError as e: + s = "impossible: '{}'".format(format) + when_skipped = (str(e) == s) + + message = ("test_skipitem_parity: " + "detected mismatch between convertsimple and skipitem " + "for format unit '{}' ({}), not skipped {}, skipped {}".format( + c, i, when_skipped, when_not_skipped)) + self.assertIs(when_skipped, when_not_skipped, message) + + def test_skipitem_with_suffix(self): + parse = _testcapi.parse_tuple_and_keywords + empty_tuple = () + tuple_1 = (0,) + dict_b = {'b':1} + keywords = ["a", "b"] + + supported = ('s#', 's*', 'z#', 'z*', 'u#', 'Z#', 'y#', 'y*', 'w#', 'w*') + for c in string.ascii_letters: + for c2 in '#*': + f = c + c2 + with self.subTest(format=f): + optional_format = "|" + f + "i" + if f in supported: + parse(empty_tuple, dict_b, optional_format, keywords) + else: + with self.assertRaisesRegex(SystemError, + 'impossible'): + parse(empty_tuple, dict_b, optional_format, keywords) + + for c in map(chr, range(32, 128)): + f = 'e' + c + optional_format = "|" + f + "i" + with self.subTest(format=f): + if c in 'st': + parse(empty_tuple, dict_b, optional_format, keywords) + else: + with self.assertRaisesRegex(SystemError, + 'impossible'): + parse(empty_tuple, dict_b, optional_format, keywords) + + +class ParseTupleAndKeywords_Test(unittest.TestCase): + + def test_parse_tuple_and_keywords(self): + # Test handling errors in the parse_tuple_and_keywords helper itself + self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords, + (), {}, 42, []) + self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, + (), {}, '', 42) + self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, + (), {}, '', [''] * 42) + self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, + (), {}, '', [42]) + + def test_bad_use(self): + # Test handling invalid format and keywords in + # PyArg_ParseTupleAndKeywords() + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '||O', ['a']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (1, 2), {}, '|O|O', ['a', 'b']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {'a': 1}, '$$O', ['a']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {'a': 1}, '$|O', ['a']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '|O', ['a', 'b']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (1,), {}, '|OO', ['a']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {}, '|$O', ['']) + self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, + (), {}, '|OO', ['a', '']) + + def test_positional_only(self): + parse = _testcapi.parse_tuple_and_keywords + + parse((1, 2, 3), {}, 'OOO', ['', '', 'a']) + parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a']) + with self.assertRaisesRegex(TypeError, + r'function takes at least 2 positional arguments \(1 given\)'): + parse((1,), {'a': 3}, 'OOO', ['', '', 'a']) + parse((1,), {}, 'O|OO', ['', '', 'a']) + with self.assertRaisesRegex(TypeError, + r'function takes at least 1 positional argument \(0 given\)'): + parse((), {}, 'O|OO', ['', '', 'a']) + parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a']) + with self.assertRaisesRegex(TypeError, + r'function takes exactly 2 positional arguments \(1 given\)'): + parse((1,), {'a': 3}, 'OO$O', ['', '', 'a']) + parse((1,), {}, 'O|O$O', ['', '', 'a']) + with self.assertRaisesRegex(TypeError, + r'function takes at least 1 positional argument \(0 given\)'): + parse((), {}, 'O|O$O', ['', '', 'a']) + with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'): + parse((1,), {}, 'O|$OO', ['', '', 'a']) + with self.assertRaisesRegex(SystemError, 'Empty keyword'): + parse((1,), {}, 'O|OO', ['', 'a', '']) + + +class Test_testcapi(unittest.TestCase): + locals().update((name, getattr(_testcapi, name)) + for name in dir(_testcapi) + if name.startswith('test_') and name.endswith('_code')) + + @warnings_helper.ignore_warnings(category=DeprecationWarning) + def test_u_code(self): + _testcapi.test_u_code() + + @warnings_helper.ignore_warnings(category=DeprecationWarning) + def test_Z_code(self): + _testcapi.test_Z_code() + + +if __name__ == "__main__": + unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_capi/test_misc.py python3.10-3.10.12/Lib/test/test_capi/test_misc.py --- python3.10-3.10.7/Lib/test/test_capi/test_misc.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/test_misc.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,1077 @@ +# Run the _testcapi module tests (tests for the Python/C API): by defn, +# these are all functions _testcapi exports whose name begins with 'test_'. + +from collections import OrderedDict +import importlib.machinery +import importlib.util +import os +import pickle +import random +import re +import subprocess +import sys +import textwrap +import threading +import time +import unittest +import weakref +from test import support +from test.support import MISSING_C_DOCSTRINGS +from test.support import import_helper +from test.support import threading_helper +from test.support import warnings_helper +from test.support.script_helper import assert_python_failure, assert_python_ok +try: + import _posixsubprocess +except ImportError: + _posixsubprocess = None + +# Skip this test if the _testcapi module isn't available. +_testcapi = import_helper.import_module('_testcapi') + +import _testinternalcapi + +# Were we compiled --with-pydebug or with #define Py_DEBUG? +Py_DEBUG = hasattr(sys, 'gettotalrefcount') + + +def decode_stderr(err): + return err.decode('utf-8', 'replace').replace('\r', '') + + +def testfunction(self): + """some doc""" + return self + + +class InstanceMethod: + id = _testcapi.instancemethod(id) + testfunction = _testcapi.instancemethod(testfunction) + +class CAPITest(unittest.TestCase): + + def test_instancemethod(self): + inst = InstanceMethod() + self.assertEqual(id(inst), inst.id()) + self.assertTrue(inst.testfunction() is inst) + self.assertEqual(inst.testfunction.__doc__, testfunction.__doc__) + self.assertEqual(InstanceMethod.testfunction.__doc__, testfunction.__doc__) + + InstanceMethod.testfunction.attribute = "test" + self.assertEqual(testfunction.attribute, "test") + self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test") + + def test_no_FatalError_infinite_loop(self): + with support.SuppressCrashReport(): + p = subprocess.Popen([sys.executable, "-c", + 'import _testcapi;' + '_testcapi.crash_no_current_thread()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + self.assertEqual(out, b'') + # This used to cause an infinite loop. + self.assertTrue(err.rstrip().startswith( + b'Fatal Python error: ' + b'PyThreadState_Get: ' + b'the function must be called with the GIL held, ' + b'but the GIL is released ' + b'(the current Python thread state is NULL)'), + err) + + def test_memoryview_from_NULL_pointer(self): + self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) + + def test_exc_info(self): + raised_exception = ValueError("5") + new_exc = TypeError("TEST") + try: + raise raised_exception + except ValueError as e: + tb = e.__traceback__ + orig_sys_exc_info = sys.exc_info() + orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None) + new_sys_exc_info = sys.exc_info() + new_exc_info = _testcapi.set_exc_info(*orig_exc_info) + reset_sys_exc_info = sys.exc_info() + + self.assertEqual(orig_exc_info[1], e) + + self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb)) + self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info) + self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info) + self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None)) + self.assertSequenceEqual(new_sys_exc_info, new_exc_info) + else: + self.assertTrue(False) + + @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') + def test_seq_bytes_to_charp_array(self): + # Issue #15732: crash in _PySequence_BytesToCharpArray() + class Z(object): + def __len__(self): + return 1 + self.assertRaises(TypeError, _posixsubprocess.fork_exec, + 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + # Issue #15736: overflow in _PySequence_BytesToCharpArray() + class Z(object): + def __len__(self): + return sys.maxsize + def __getitem__(self, i): + return b'x' + self.assertRaises(MemoryError, _posixsubprocess.fork_exec, + 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + + @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') + def test_subprocess_fork_exec(self): + class Z(object): + def __len__(self): + return 1 + + # Issue #15738: crash in subprocess_fork_exec() + self.assertRaises(TypeError, _posixsubprocess.fork_exec, + Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") + def test_docstring_signature_parsing(self): + + self.assertEqual(_testcapi.no_docstring.__doc__, None) + self.assertEqual(_testcapi.no_docstring.__text_signature__, None) + + self.assertEqual(_testcapi.docstring_empty.__doc__, None) + self.assertEqual(_testcapi.docstring_empty.__text_signature__, None) + + self.assertEqual(_testcapi.docstring_no_signature.__doc__, + "This docstring has no signature.") + self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None) + + self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__, + "docstring_with_invalid_signature($module, /, boo)\n" + "\n" + "This docstring has an invalid signature." + ) + self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None) + + self.assertEqual(_testcapi.docstring_with_invalid_signature2.__doc__, + "docstring_with_invalid_signature2($module, /, boo)\n" + "\n" + "--\n" + "\n" + "This docstring also has an invalid signature." + ) + self.assertEqual(_testcapi.docstring_with_invalid_signature2.__text_signature__, None) + + self.assertEqual(_testcapi.docstring_with_signature.__doc__, + "This docstring has a valid signature.") + self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)") + + self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__doc__, None) + self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__text_signature__, + "($module, /, sig)") + + self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__, + "\nThis docstring has a valid signature and some extra newlines.") + self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__, + "($module, /, parameter)") + + def test_c_type_with_matrix_multiplication(self): + M = _testcapi.matmulType + m1 = M() + m2 = M() + self.assertEqual(m1 @ m2, ("matmul", m1, m2)) + self.assertEqual(m1 @ 42, ("matmul", m1, 42)) + self.assertEqual(42 @ m1, ("matmul", 42, m1)) + o = m1 + o @= m2 + self.assertEqual(o, ("imatmul", m1, m2)) + o = m1 + o @= 42 + self.assertEqual(o, ("imatmul", m1, 42)) + o = 42 + o @= m1 + self.assertEqual(o, ("matmul", 42, m1)) + + def test_c_type_with_ipow(self): + # When the __ipow__ method of a type was implemented in C, using the + # modulo param would cause segfaults. + o = _testcapi.ipowType() + self.assertEqual(o.__ipow__(1), (1, None)) + self.assertEqual(o.__ipow__(2, 2), (2, 2)) + + def test_return_null_without_error(self): + # Issue #23571: A function must not return NULL without setting an + # error + if Py_DEBUG: + code = textwrap.dedent(""" + import _testcapi + from test import support + + with support.SuppressCrashReport(): + _testcapi.return_null_without_error() + """) + rc, out, err = assert_python_failure('-c', code) + err = decode_stderr(err) + self.assertRegex(err, + r'Fatal Python error: _Py_CheckFunctionResult: ' + r'a function returned NULL without setting an exception\n' + r'Python runtime state: initialized\n' + r'SystemError: ' + r'returned NULL without setting an exception\n' + r'\n' + r'Current thread.*:\n' + r' File .*", line 6 in \n') + else: + with self.assertRaises(SystemError) as cm: + _testcapi.return_null_without_error() + self.assertRegex(str(cm.exception), + 'return_null_without_error.* ' + 'returned NULL without setting an exception') + + def test_return_result_with_error(self): + # Issue #23571: A function must not return a result with an error set + if Py_DEBUG: + code = textwrap.dedent(""" + import _testcapi + from test import support + + with support.SuppressCrashReport(): + _testcapi.return_result_with_error() + """) + rc, out, err = assert_python_failure('-c', code) + err = decode_stderr(err) + self.assertRegex(err, + r'Fatal Python error: _Py_CheckFunctionResult: ' + r'a function returned a result with an exception set\n' + r'Python runtime state: initialized\n' + r'ValueError\n' + r'\n' + r'The above exception was the direct cause ' + r'of the following exception:\n' + r'\n' + r'SystemError: ' + r'returned a result with an exception set\n' + r'\n' + r'Current thread.*:\n' + r' File .*, line 6 in \n') + else: + with self.assertRaises(SystemError) as cm: + _testcapi.return_result_with_error() + self.assertRegex(str(cm.exception), + 'return_result_with_error.* ' + 'returned a result with an exception set') + + def test_getitem_with_error(self): + # Test _Py_CheckSlotResult(). Raise an exception and then calls + # PyObject_GetItem(): check that the assertion catches the bug. + # PyObject_GetItem() must not be called with an exception set. + code = textwrap.dedent(""" + import _testcapi + from test import support + + with support.SuppressCrashReport(): + _testcapi.getitem_with_error({1: 2}, 1) + """) + rc, out, err = assert_python_failure('-c', code) + err = decode_stderr(err) + if 'SystemError: ' not in err: + self.assertRegex(err, + r'Fatal Python error: _Py_CheckSlotResult: ' + r'Slot __getitem__ of type dict succeeded ' + r'with an exception set\n' + r'Python runtime state: initialized\n' + r'ValueError: bug\n' + r'\n' + r'Current thread .* \(most recent call first\):\n' + r' File .*, line 6 in \n' + r'\n' + r'Extension modules: _testcapi \(total: 1\)\n') + else: + # Python built with NDEBUG macro defined: + # test _Py_CheckFunctionResult() instead. + self.assertIn('returned a result with an exception set', err) + + def test_buildvalue_N(self): + _testcapi.test_buildvalue_N() + + def test_set_nomemory(self): + code = """if 1: + import _testcapi + + class C(): pass + + # The first loop tests both functions and that remove_mem_hooks() + # can be called twice in a row. The second loop checks a call to + # set_nomemory() after a call to remove_mem_hooks(). The third + # loop checks the start and stop arguments of set_nomemory(). + for outer_cnt in range(1, 4): + start = 10 * outer_cnt + for j in range(100): + if j == 0: + if outer_cnt != 3: + _testcapi.set_nomemory(start) + else: + _testcapi.set_nomemory(start, start + 1) + try: + C() + except MemoryError as e: + if outer_cnt != 3: + _testcapi.remove_mem_hooks() + print('MemoryError', outer_cnt, j) + _testcapi.remove_mem_hooks() + break + """ + rc, out, err = assert_python_ok('-c', code) + self.assertIn(b'MemoryError 1 10', out) + self.assertIn(b'MemoryError 2 20', out) + self.assertIn(b'MemoryError 3 30', out) + + def test_mapping_keys_values_items(self): + class Mapping1(dict): + def keys(self): + return list(super().keys()) + def values(self): + return list(super().values()) + def items(self): + return list(super().items()) + class Mapping2(dict): + def keys(self): + return tuple(super().keys()) + def values(self): + return tuple(super().values()) + def items(self): + return tuple(super().items()) + dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} + + for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(), + dict_obj, OrderedDict(dict_obj), + Mapping1(dict_obj), Mapping2(dict_obj)]: + self.assertListEqual(_testcapi.get_mapping_keys(mapping), + list(mapping.keys())) + self.assertListEqual(_testcapi.get_mapping_values(mapping), + list(mapping.values())) + self.assertListEqual(_testcapi.get_mapping_items(mapping), + list(mapping.items())) + + def test_mapping_keys_values_items_bad_arg(self): + self.assertRaises(AttributeError, _testcapi.get_mapping_keys, None) + self.assertRaises(AttributeError, _testcapi.get_mapping_values, None) + self.assertRaises(AttributeError, _testcapi.get_mapping_items, None) + + class BadMapping: + def keys(self): + return None + def values(self): + return None + def items(self): + return None + bad_mapping = BadMapping() + self.assertRaises(TypeError, _testcapi.get_mapping_keys, bad_mapping) + self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping) + self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping) + + def test_mapping_has_key(self): + dct = {'a': 1} + self.assertTrue(_testcapi.mapping_has_key(dct, 'a')) + self.assertFalse(_testcapi.mapping_has_key(dct, 'b')) + + class SubDict(dict): + pass + + dct2 = SubDict({'a': 1}) + self.assertTrue(_testcapi.mapping_has_key(dct2, 'a')) + self.assertFalse(_testcapi.mapping_has_key(dct2, 'b')) + + @unittest.skipUnless(hasattr(_testcapi, 'negative_refcount'), + 'need _testcapi.negative_refcount') + def test_negative_refcount(self): + # bpo-35059: Check that Py_DECREF() reports the correct filename + # when calling _Py_NegativeRefcount() to abort Python. + code = textwrap.dedent(""" + import _testcapi + from test import support + + with support.SuppressCrashReport(): + _testcapi.negative_refcount() + """) + rc, out, err = assert_python_failure('-c', code) + self.assertRegex(err, + br'_testcapimodule\.c:[0-9]+: ' + br'_Py_NegativeRefcount: Assertion failed: ' + br'object has negative ref count') + + def test_trashcan_subclass(self): + # bpo-35983: Check that the trashcan mechanism for "list" is NOT + # activated when its tp_dealloc is being called by a subclass + from _testcapi import MyList + L = None + for i in range(1000): + L = MyList((L,)) + + @support.requires_resource('cpu') + def test_trashcan_python_class1(self): + self.do_test_trashcan_python_class(list) + + @support.requires_resource('cpu') + def test_trashcan_python_class2(self): + from _testcapi import MyList + self.do_test_trashcan_python_class(MyList) + + def do_test_trashcan_python_class(self, base): + # Check that the trashcan mechanism works properly for a Python + # subclass of a class using the trashcan (this specific test assumes + # that the base class "base" behaves like list) + class PyList(base): + # Count the number of PyList instances to verify that there is + # no memory leak + num = 0 + def __init__(self, *args): + __class__.num += 1 + super().__init__(*args) + def __del__(self): + __class__.num -= 1 + + for parity in (0, 1): + L = None + # We need in the order of 2**20 iterations here such that a + # typical 8MB stack would overflow without the trashcan. + for i in range(2**20): + L = PyList((L,)) + L.attr = i + if parity: + # Add one additional nesting layer + L = (L,) + self.assertGreater(PyList.num, 0) + del L + self.assertEqual(PyList.num, 0) + + def test_heap_ctype_doc_and_text_signature(self): + self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc") + self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)") + + def test_null_type_doc(self): + self.assertEqual(_testcapi.NullTpDocType.__doc__, None) + + def test_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self): + class HeapGcCTypeSubclass(_testcapi.HeapGcCType): + def __init__(self): + self.value2 = 20 + super().__init__() + + subclass_instance = HeapGcCTypeSubclass() + type_refcnt = sys.getrefcount(HeapGcCTypeSubclass) + + # Test that subclass instance was fully created + self.assertEqual(subclass_instance.value, 10) + self.assertEqual(subclass_instance.value2, 20) + + # Test that the type reference count is only decremented once + del subclass_instance + self.assertEqual(type_refcnt - 1, sys.getrefcount(HeapGcCTypeSubclass)) + + def test_subclass_of_heap_gc_ctype_with_del_modifying_dunder_class_only_decrefs_once(self): + class A(_testcapi.HeapGcCType): + def __init__(self): + self.value2 = 20 + super().__init__() + + class B(A): + def __init__(self): + super().__init__() + + def __del__(self): + self.__class__ = A + A.refcnt_in_del = sys.getrefcount(A) + B.refcnt_in_del = sys.getrefcount(B) + + subclass_instance = B() + type_refcnt = sys.getrefcount(B) + new_type_refcnt = sys.getrefcount(A) + + # Test that subclass instance was fully created + self.assertEqual(subclass_instance.value, 10) + self.assertEqual(subclass_instance.value2, 20) + + del subclass_instance + + # Test that setting __class__ modified the reference counts of the types + self.assertEqual(type_refcnt - 1, B.refcnt_in_del) + self.assertEqual(new_type_refcnt + 1, A.refcnt_in_del) + + # Test that the original type already has decreased its refcnt + self.assertEqual(type_refcnt - 1, sys.getrefcount(B)) + + # Test that subtype_dealloc decref the newly assigned __class__ only once + self.assertEqual(new_type_refcnt, sys.getrefcount(A)) + + def test_heaptype_with_dict(self): + inst = _testcapi.HeapCTypeWithDict() + inst.foo = 42 + self.assertEqual(inst.foo, 42) + self.assertEqual(inst.dictobj, inst.__dict__) + self.assertEqual(inst.dictobj, {"foo": 42}) + + inst = _testcapi.HeapCTypeWithDict() + self.assertEqual({}, inst.__dict__) + + def test_heaptype_with_negative_dict(self): + inst = _testcapi.HeapCTypeWithNegativeDict() + inst.foo = 42 + self.assertEqual(inst.foo, 42) + self.assertEqual(inst.dictobj, inst.__dict__) + self.assertEqual(inst.dictobj, {"foo": 42}) + + inst = _testcapi.HeapCTypeWithNegativeDict() + self.assertEqual({}, inst.__dict__) + + def test_heaptype_with_weakref(self): + inst = _testcapi.HeapCTypeWithWeakref() + ref = weakref.ref(inst) + self.assertEqual(ref(), inst) + self.assertEqual(inst.weakreflist, ref) + + def test_heaptype_with_buffer(self): + inst = _testcapi.HeapCTypeWithBuffer() + b = bytes(inst) + self.assertEqual(b, b"1234") + + def test_c_subclass_of_heap_ctype_with_tpdealloc_decrefs_once(self): + subclass_instance = _testcapi.HeapCTypeSubclass() + type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass) + + # Test that subclass instance was fully created + self.assertEqual(subclass_instance.value, 10) + self.assertEqual(subclass_instance.value2, 20) + + # Test that the type reference count is only decremented once + del subclass_instance + self.assertEqual(type_refcnt - 1, sys.getrefcount(_testcapi.HeapCTypeSubclass)) + + def test_c_subclass_of_heap_ctype_with_del_modifying_dunder_class_only_decrefs_once(self): + subclass_instance = _testcapi.HeapCTypeSubclassWithFinalizer() + type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclassWithFinalizer) + new_type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass) + + # Test that subclass instance was fully created + self.assertEqual(subclass_instance.value, 10) + self.assertEqual(subclass_instance.value2, 20) + + # The tp_finalize slot will set __class__ to HeapCTypeSubclass + del subclass_instance + + # Test that setting __class__ modified the reference counts of the types + self.assertEqual(type_refcnt - 1, _testcapi.HeapCTypeSubclassWithFinalizer.refcnt_in_del) + self.assertEqual(new_type_refcnt + 1, _testcapi.HeapCTypeSubclass.refcnt_in_del) + + # Test that the original type already has decreased its refcnt + self.assertEqual(type_refcnt - 1, sys.getrefcount(_testcapi.HeapCTypeSubclassWithFinalizer)) + + # Test that subtype_dealloc decref the newly assigned __class__ only once + self.assertEqual(new_type_refcnt, sys.getrefcount(_testcapi.HeapCTypeSubclass)) + + def test_heaptype_with_setattro(self): + obj = _testcapi.HeapCTypeSetattr() + self.assertEqual(obj.pvalue, 10) + obj.value = 12 + self.assertEqual(obj.pvalue, 12) + del obj.value + self.assertEqual(obj.pvalue, 0) + + def test_pynumber_tobase(self): + from _testcapi import pynumber_tobase + self.assertEqual(pynumber_tobase(123, 2), '0b1111011') + self.assertEqual(pynumber_tobase(123, 8), '0o173') + self.assertEqual(pynumber_tobase(123, 10), '123') + self.assertEqual(pynumber_tobase(123, 16), '0x7b') + self.assertEqual(pynumber_tobase(-123, 2), '-0b1111011') + self.assertEqual(pynumber_tobase(-123, 8), '-0o173') + self.assertEqual(pynumber_tobase(-123, 10), '-123') + self.assertEqual(pynumber_tobase(-123, 16), '-0x7b') + self.assertRaises(TypeError, pynumber_tobase, 123.0, 10) + self.assertRaises(TypeError, pynumber_tobase, '123', 10) + self.assertRaises(SystemError, pynumber_tobase, 123, 0) + + def check_fatal_error(self, code, expected, not_expected=()): + with support.SuppressCrashReport(): + rc, out, err = assert_python_failure('-sSI', '-c', code) + + err = decode_stderr(err) + self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n', + err) + + match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$', + err, re.MULTILINE) + if not match: + self.fail(f"Cannot find 'Extension modules:' in {err!r}") + modules = set(match.group(1).strip().split(', ')) + total = int(match.group(2)) + + for name in expected: + self.assertIn(name, modules) + for name in not_expected: + self.assertNotIn(name, modules) + self.assertEqual(len(modules), total) + + def test_fatal_error(self): + # By default, stdlib extension modules are ignored, + # but not test modules. + expected = ('_testcapi',) + not_expected = ('sys',) + code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")' + self.check_fatal_error(code, expected, not_expected) + + # Mark _testcapi as stdlib module, but not sys + expected = ('sys',) + not_expected = ('_testcapi',) + code = textwrap.dedent(''' + import _testcapi, sys + sys.stdlib_module_names = frozenset({"_testcapi"}) + _testcapi.fatal_error(b"MESSAGE") + ''') + self.check_fatal_error(code, expected) + + def test_pyobject_repr_from_null(self): + s = _testcapi.pyobject_repr_from_null() + self.assertEqual(s, '') + + def test_pyobject_str_from_null(self): + s = _testcapi.pyobject_str_from_null() + self.assertEqual(s, '') + + def test_pyobject_bytes_from_null(self): + s = _testcapi.pyobject_bytes_from_null() + self.assertEqual(s, b'') + + def test_Py_CompileString(self): + # Check that Py_CompileString respects the coding cookie + _compile = _testcapi.Py_CompileString + code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" + result = _compile(code) + expected = compile(code, "", "exec") + self.assertEqual(result.co_consts, expected.co_consts) + + +class TestPendingCalls(unittest.TestCase): + + def pendingcalls_submit(self, l, n): + def callback(): + #this function can be interrupted by thread switching so let's + #use an atomic operation + l.append(None) + + for i in range(n): + time.sleep(random.random()*0.02) #0.01 secs on average + #try submitting callback until successful. + #rely on regular interrupt to flush queue if we are + #unsuccessful. + while True: + if _testcapi._pending_threadfunc(callback): + break + + def pendingcalls_wait(self, l, n, context = None): + #now, stick around until l[0] has grown to 10 + count = 0 + while len(l) != n: + #this busy loop is where we expect to be interrupted to + #run our callbacks. Note that callbacks are only run on the + #main thread + if False and support.verbose: + print("(%i)"%(len(l),),) + for i in range(1000): + a = i*i + if context and not context.event.is_set(): + continue + count += 1 + self.assertTrue(count < 10000, + "timeout waiting for %i callbacks, got %i"%(n, len(l))) + if False and support.verbose: + print("(%i)"%(len(l),)) + + def test_pendingcalls_threaded(self): + + #do every callback on a separate thread + n = 32 #total callbacks + threads = [] + class foo(object):pass + context = foo() + context.l = [] + context.n = 2 #submits per thread + context.nThreads = n // context.n + context.nFinished = 0 + context.lock = threading.Lock() + context.event = threading.Event() + + threads = [threading.Thread(target=self.pendingcalls_thread, + args=(context,)) + for i in range(context.nThreads)] + with threading_helper.start_threads(threads): + self.pendingcalls_wait(context.l, n, context) + + def pendingcalls_thread(self, context): + try: + self.pendingcalls_submit(context.l, context.n) + finally: + with context.lock: + context.nFinished += 1 + nFinished = context.nFinished + if False and support.verbose: + print("finished threads: ", nFinished) + if nFinished == context.nThreads: + context.event.set() + + def test_pendingcalls_non_threaded(self): + #again, just using the main thread, likely they will all be dispatched at + #once. It is ok to ask for too many, because we loop until we find a slot. + #the loop can be interrupted to dispatch. + #there are only 32 dispatch slots, so we go for twice that! + l = [] + n = 64 + self.pendingcalls_submit(l, n) + self.pendingcalls_wait(l, n) + + +class SubinterpreterTest(unittest.TestCase): + + def test_subinterps(self): + import builtins + r, w = os.pipe() + code = """if 1: + import sys, builtins, pickle + with open({:d}, "wb") as f: + pickle.dump(id(sys.modules), f) + pickle.dump(id(builtins), f) + """.format(w) + with open(r, "rb") as f: + ret = support.run_in_subinterp(code) + self.assertEqual(ret, 0) + self.assertNotEqual(pickle.load(f), id(sys.modules)) + self.assertNotEqual(pickle.load(f), id(builtins)) + + def test_subinterps_recent_language_features(self): + r, w = os.pipe() + code = """if 1: + import pickle + with open({:d}, "wb") as f: + + @(lambda x:x) # Py 3.9 + def noop(x): return x + + a = (b := f'1{{2}}3') + noop('x') # Py 3.8 (:=) / 3.6 (f'') + + async def foo(arg): return await arg # Py 3.5 + + pickle.dump(dict(a=a, b=b), f) + """.format(w) + + with open(r, "rb") as f: + ret = support.run_in_subinterp(code) + self.assertEqual(ret, 0) + self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'}) + + def test_mutate_exception(self): + """ + Exceptions saved in global module state get shared between + individual module instances. This test checks whether or not + a change in one interpreter's module gets reflected into the + other ones. + """ + import binascii + + support.run_in_subinterp("import binascii; binascii.Error.foobar = 'foobar'") + + self.assertFalse(hasattr(binascii.Error, "foobar")) + + def test_module_state_shared_in_global(self): + """ + bpo-44050: Extension module state should be shared between interpreters + when it doesn't support sub-interpreters. + """ + r, w = os.pipe() + self.addCleanup(os.close, r) + self.addCleanup(os.close, w) + + script = textwrap.dedent(f""" + import importlib.machinery + import importlib.util + import os + + fullname = '_test_module_state_shared' + origin = importlib.util.find_spec('_testmultiphase').origin + loader = importlib.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + attr_id = str(id(module.Error)).encode() + + os.write({w}, attr_id) + """) + exec(script) + main_attr_id = os.read(r, 100) + + ret = support.run_in_subinterp(script) + self.assertEqual(ret, 0) + subinterp_attr_id = os.read(r, 100) + self.assertEqual(main_attr_id, subinterp_attr_id) + + +class TestThreadState(unittest.TestCase): + + @threading_helper.reap_threads + def test_thread_state(self): + # some extra thread-state tests driven via _testcapi + def target(): + idents = [] + + def callback(): + idents.append(threading.get_ident()) + + _testcapi._test_thread_state(callback) + a = b = callback + time.sleep(1) + # Check our main thread is in the list exactly 3 times. + self.assertEqual(idents.count(threading.get_ident()), 3, + "Couldn't find main thread correctly in the list") + + target() + t = threading.Thread(target=target) + t.start() + t.join() + + @threading_helper.reap_threads + def test_gilstate_ensure_no_deadlock(self): + # See https://github.com/python/cpython/issues/96071 + code = textwrap.dedent(f""" + import _testcapi + + def callback(): + print('callback called') + + _testcapi._test_thread_state(callback) + """) + ret = assert_python_ok('-X', 'tracemalloc', '-c', code) + self.assertIn(b'callback called', ret.out) + + +class Test_testcapi(unittest.TestCase): + locals().update((name, getattr(_testcapi, name)) + for name in dir(_testcapi) + if name.startswith('test_') and not name.endswith('_code')) + + # Suppress warning from PyUnicode_FromUnicode(). + @warnings_helper.ignore_warnings(category=DeprecationWarning) + def test_widechar(self): + _testcapi.test_widechar() + + +class Test_testinternalcapi(unittest.TestCase): + locals().update((name, getattr(_testinternalcapi, name)) + for name in dir(_testinternalcapi) + if name.startswith('test_')) + + +class PyMemDebugTests(unittest.TestCase): + PYTHONMALLOC = 'debug' + # '0x04c06e0' or '04C06E0' + PTR_REGEX = r'(?:0x)?[0-9a-fA-F]+' + + def check(self, code): + with support.SuppressCrashReport(): + out = assert_python_failure( + '-c', code, + PYTHONMALLOC=self.PYTHONMALLOC, + # FreeBSD: instruct jemalloc to not fill freed() memory + # with junk byte 0x5a, see JEMALLOC(3) + MALLOC_CONF="junk:false", + ) + stderr = out.err + return stderr.decode('ascii', 'replace') + + def test_buffer_overflow(self): + out = self.check('import _testcapi; _testcapi.pymem_buffer_overflow()') + regex = (r"Debug memory block at address p={ptr}: API 'm'\n" + r" 16 bytes originally requested\n" + r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n" + r" The [0-9] pad bytes at tail={ptr} are not all FORBIDDENBYTE \(0x[0-9a-f]{{2}}\):\n" + r" at tail\+0: 0x78 \*\*\* OUCH\n" + r" at tail\+1: 0xfd\n" + r" at tail\+2: 0xfd\n" + r" .*\n" + r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?" + r" Data at p: cd cd cd .*\n" + r"\n" + r"Enable tracemalloc to get the memory block allocation traceback\n" + r"\n" + r"Fatal Python error: _PyMem_DebugRawFree: bad trailing pad byte") + regex = regex.format(ptr=self.PTR_REGEX) + regex = re.compile(regex, flags=re.DOTALL) + self.assertRegex(out, regex) + + def test_api_misuse(self): + out = self.check('import _testcapi; _testcapi.pymem_api_misuse()') + regex = (r"Debug memory block at address p={ptr}: API 'm'\n" + r" 16 bytes originally requested\n" + r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n" + r" The [0-9] pad bytes at tail={ptr} are FORBIDDENBYTE, as expected.\n" + r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?" + r" Data at p: cd cd cd .*\n" + r"\n" + r"Enable tracemalloc to get the memory block allocation traceback\n" + r"\n" + r"Fatal Python error: _PyMem_DebugRawFree: bad ID: Allocated using API 'm', verified using API 'r'\n") + regex = regex.format(ptr=self.PTR_REGEX) + self.assertRegex(out, regex) + + def check_malloc_without_gil(self, code): + out = self.check(code) + expected = ('Fatal Python error: _PyMem_DebugMalloc: ' + 'Python memory allocator called without holding the GIL') + self.assertIn(expected, out) + + def test_pymem_malloc_without_gil(self): + # Debug hooks must raise an error if PyMem_Malloc() is called + # without holding the GIL + code = 'import _testcapi; _testcapi.pymem_malloc_without_gil()' + self.check_malloc_without_gil(code) + + def test_pyobject_malloc_without_gil(self): + # Debug hooks must raise an error if PyObject_Malloc() is called + # without holding the GIL + code = 'import _testcapi; _testcapi.pyobject_malloc_without_gil()' + self.check_malloc_without_gil(code) + + def check_pyobject_is_freed(self, func_name): + code = textwrap.dedent(f''' + import gc, os, sys, _testcapi + # Disable the GC to avoid crash on GC collection + gc.disable() + try: + _testcapi.{func_name}() + # Exit immediately to avoid a crash while deallocating + # the invalid object + os._exit(0) + except _testcapi.error: + os._exit(1) + ''') + assert_python_ok( + '-c', code, + PYTHONMALLOC=self.PYTHONMALLOC, + MALLOC_CONF="junk:false", + ) + + def test_pyobject_null_is_freed(self): + self.check_pyobject_is_freed('check_pyobject_null_is_freed') + + def test_pyobject_uninitialized_is_freed(self): + self.check_pyobject_is_freed('check_pyobject_uninitialized_is_freed') + + def test_pyobject_forbidden_bytes_is_freed(self): + self.check_pyobject_is_freed('check_pyobject_forbidden_bytes_is_freed') + + def test_pyobject_freed_is_freed(self): + self.check_pyobject_is_freed('check_pyobject_freed_is_freed') + + +class PyMemMallocDebugTests(PyMemDebugTests): + PYTHONMALLOC = 'malloc_debug' + + +@unittest.skipUnless(support.with_pymalloc(), 'need pymalloc') +class PyMemPymallocDebugTests(PyMemDebugTests): + PYTHONMALLOC = 'pymalloc_debug' + + +@unittest.skipUnless(Py_DEBUG, 'need Py_DEBUG') +class PyMemDefaultTests(PyMemDebugTests): + # test default allocator of Python compiled in debug mode + PYTHONMALLOC = '' + + +class Test_ModuleStateAccess(unittest.TestCase): + """Test access to module start (PEP 573)""" + + # The C part of the tests lives in _testmultiphase, in a module called + # _testmultiphase_meth_state_access. + # This module has multi-phase initialization, unlike _testcapi. + + def setUp(self): + fullname = '_testmultiphase_meth_state_access' # XXX + origin = importlib.util.find_spec('_testmultiphase').origin + loader = importlib.machinery.ExtensionFileLoader(fullname, origin) + spec = importlib.util.spec_from_loader(fullname, loader) + module = importlib.util.module_from_spec(spec) + loader.exec_module(module) + self.module = module + + def test_subclass_get_module(self): + """PyType_GetModule for defining_class""" + class StateAccessType_Subclass(self.module.StateAccessType): + pass + + instance = StateAccessType_Subclass() + self.assertIs(instance.get_defining_module(), self.module) + + def test_subclass_get_module_with_super(self): + class StateAccessType_Subclass(self.module.StateAccessType): + def get_defining_module(self): + return super().get_defining_module() + + instance = StateAccessType_Subclass() + self.assertIs(instance.get_defining_module(), self.module) + + def test_state_access(self): + """Checks methods defined with and without argument clinic + + This tests a no-arg method (get_count) and a method with + both a positional and keyword argument. + """ + + a = self.module.StateAccessType() + b = self.module.StateAccessType() + + methods = { + 'clinic': a.increment_count_clinic, + 'noclinic': a.increment_count_noclinic, + } + + for name, increment_count in methods.items(): + with self.subTest(name): + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 0) + + increment_count() + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 1) + + increment_count(3) + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 4) + + increment_count(-2, twice=True) + self.assertEqual(a.get_count(), b.get_count()) + self.assertEqual(a.get_count(), 0) + + with self.assertRaises(TypeError): + increment_count(thrice=3) + + with self.assertRaises(TypeError): + increment_count(1, 2, 3) + + def test_get_module_bad_def(self): + # _PyType_GetModuleByDef fails gracefully if it doesn't + # find what it's looking for. + # see bpo-46433 + instance = self.module.StateAccessType() + with self.assertRaises(TypeError): + instance.getmodulebydef_bad_def() + + def test_get_module_static_in_mro(self): + # Here, the class _PyType_GetModuleByDef is looking for + # appears in the MRO after a static type (Exception). + # see bpo-46433 + class Subclass(BaseException, self.module.StateAccessType): + pass + self.assertIs(Subclass().get_defining_module(), self.module) + + +if __name__ == "__main__": + unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_capi/test_structmembers.py python3.10-3.10.12/Lib/test/test_capi/test_structmembers.py --- python3.10-3.10.7/Lib/test/test_capi/test_structmembers.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/test_structmembers.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,145 @@ +import unittest +from test.support import import_helper +from test.support import warnings_helper + +# Skip this test if the _testcapi module isn't available. +import_helper.import_module('_testcapi') +from _testcapi import _test_structmembersType, \ + CHAR_MAX, CHAR_MIN, UCHAR_MAX, \ + SHRT_MAX, SHRT_MIN, USHRT_MAX, \ + INT_MAX, INT_MIN, UINT_MAX, \ + LONG_MAX, LONG_MIN, ULONG_MAX, \ + LLONG_MAX, LLONG_MIN, ULLONG_MAX, \ + PY_SSIZE_T_MAX, PY_SSIZE_T_MIN + +ts=_test_structmembersType(False, # T_BOOL + 1, # T_BYTE + 2, # T_UBYTE + 3, # T_SHORT + 4, # T_USHORT + 5, # T_INT + 6, # T_UINT + 7, # T_LONG + 8, # T_ULONG + 23, # T_PYSSIZET + 9.99999,# T_FLOAT + 10.1010101010, # T_DOUBLE + "hi" # T_STRING_INPLACE + ) + +class ReadWriteTests(unittest.TestCase): + + def test_bool(self): + ts.T_BOOL = True + self.assertEqual(ts.T_BOOL, True) + ts.T_BOOL = False + self.assertEqual(ts.T_BOOL, False) + self.assertRaises(TypeError, setattr, ts, 'T_BOOL', 1) + + def test_byte(self): + ts.T_BYTE = CHAR_MAX + self.assertEqual(ts.T_BYTE, CHAR_MAX) + ts.T_BYTE = CHAR_MIN + self.assertEqual(ts.T_BYTE, CHAR_MIN) + ts.T_UBYTE = UCHAR_MAX + self.assertEqual(ts.T_UBYTE, UCHAR_MAX) + + def test_short(self): + ts.T_SHORT = SHRT_MAX + self.assertEqual(ts.T_SHORT, SHRT_MAX) + ts.T_SHORT = SHRT_MIN + self.assertEqual(ts.T_SHORT, SHRT_MIN) + ts.T_USHORT = USHRT_MAX + self.assertEqual(ts.T_USHORT, USHRT_MAX) + + def test_int(self): + ts.T_INT = INT_MAX + self.assertEqual(ts.T_INT, INT_MAX) + ts.T_INT = INT_MIN + self.assertEqual(ts.T_INT, INT_MIN) + ts.T_UINT = UINT_MAX + self.assertEqual(ts.T_UINT, UINT_MAX) + + def test_long(self): + ts.T_LONG = LONG_MAX + self.assertEqual(ts.T_LONG, LONG_MAX) + ts.T_LONG = LONG_MIN + self.assertEqual(ts.T_LONG, LONG_MIN) + ts.T_ULONG = ULONG_MAX + self.assertEqual(ts.T_ULONG, ULONG_MAX) + + def test_py_ssize_t(self): + ts.T_PYSSIZET = PY_SSIZE_T_MAX + self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MAX) + ts.T_PYSSIZET = PY_SSIZE_T_MIN + self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MIN) + + @unittest.skipUnless(hasattr(ts, "T_LONGLONG"), "long long not present") + def test_longlong(self): + ts.T_LONGLONG = LLONG_MAX + self.assertEqual(ts.T_LONGLONG, LLONG_MAX) + ts.T_LONGLONG = LLONG_MIN + self.assertEqual(ts.T_LONGLONG, LLONG_MIN) + + ts.T_ULONGLONG = ULLONG_MAX + self.assertEqual(ts.T_ULONGLONG, ULLONG_MAX) + + ## make sure these will accept a plain int as well as a long + ts.T_LONGLONG = 3 + self.assertEqual(ts.T_LONGLONG, 3) + ts.T_ULONGLONG = 4 + self.assertEqual(ts.T_ULONGLONG, 4) + + def test_bad_assignments(self): + integer_attributes = [ + 'T_BOOL', + 'T_BYTE', 'T_UBYTE', + 'T_SHORT', 'T_USHORT', + 'T_INT', 'T_UINT', + 'T_LONG', 'T_ULONG', + 'T_PYSSIZET' + ] + if hasattr(ts, 'T_LONGLONG'): + integer_attributes.extend(['T_LONGLONG', 'T_ULONGLONG']) + + # issue8014: this produced 'bad argument to internal function' + # internal error + for nonint in None, 3.2j, "full of eels", {}, []: + for attr in integer_attributes: + self.assertRaises(TypeError, setattr, ts, attr, nonint) + + def test_inplace_string(self): + self.assertEqual(ts.T_STRING_INPLACE, "hi") + self.assertRaises(TypeError, setattr, ts, "T_STRING_INPLACE", "s") + self.assertRaises(TypeError, delattr, ts, "T_STRING_INPLACE") + + +class TestWarnings(unittest.TestCase): + + def test_byte_max(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_BYTE = CHAR_MAX+1 + + def test_byte_min(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_BYTE = CHAR_MIN-1 + + def test_ubyte_max(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_UBYTE = UCHAR_MAX+1 + + def test_short_max(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_SHORT = SHRT_MAX+1 + + def test_short_min(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_SHORT = SHRT_MIN-1 + + def test_ushort_max(self): + with warnings_helper.check_warnings(('', RuntimeWarning)): + ts.T_USHORT = USHRT_MAX+1 + + +if __name__ == "__main__": + unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_capi/test_unicode.py python3.10-3.10.12/Lib/test/test_capi/test_unicode.py --- python3.10-3.10.7/Lib/test/test_capi/test_unicode.py 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi/test_unicode.py 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,502 @@ +import unittest +import sys +import warnings +from test import support +from test.support import import_helper +from test.support import warnings_helper + +try: + import _testcapi +except ImportError: + _testcapi = None + + +class CAPITest(unittest.TestCase): + + # Test PyUnicode_FromFormat() + def test_from_format(self): + import_helper.import_module('ctypes') + from ctypes import ( + c_char_p, + pythonapi, py_object, sizeof, + c_int, c_long, c_longlong, c_ssize_t, + c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) + name = "PyUnicode_FromFormat" + _PyUnicode_FromFormat = getattr(pythonapi, name) + _PyUnicode_FromFormat.argtypes = (c_char_p,) + _PyUnicode_FromFormat.restype = py_object + + def PyUnicode_FromFormat(format, *args): + cargs = tuple( + py_object(arg) if isinstance(arg, str) else arg + for arg in args) + return _PyUnicode_FromFormat(format, *cargs) + + def check_format(expected, format, *args): + text = PyUnicode_FromFormat(format, *args) + self.assertEqual(expected, text) + + # ascii format, non-ascii argument + check_format('ascii\x7f=unicode\xe9', + b'ascii\x7f=%U', 'unicode\xe9') + + # non-ascii format, ascii argument: ensure that PyUnicode_FromFormatV() + # raises an error + self.assertRaisesRegex(ValueError, + r'^PyUnicode_FromFormatV\(\) expects an ASCII-encoded format ' + 'string, got a non-ASCII byte: 0xe9$', + PyUnicode_FromFormat, b'unicode\xe9=%s', 'ascii') + + # test "%c" + check_format('\uabcd', + b'%c', c_int(0xabcd)) + check_format('\U0010ffff', + b'%c', c_int(0x10ffff)) + with self.assertRaises(OverflowError): + PyUnicode_FromFormat(b'%c', c_int(0x110000)) + # Issue #18183 + check_format('\U00010000\U00100000', + b'%c%c', c_int(0x10000), c_int(0x100000)) + + # test "%" + check_format('%', + b'%') + check_format('%', + b'%%') + check_format('%s', + b'%%s') + check_format('[%]', + b'[%%]') + check_format('%abc', + b'%%%s', b'abc') + + # truncated string + check_format('abc', + b'%.3s', b'abcdef') + check_format('abc[\ufffd', + b'%.5s', 'abc[\u20ac]'.encode('utf8')) + check_format("'\\u20acABC'", + b'%A', '\u20acABC') + check_format("'\\u20", + b'%.5A', '\u20acABCDEF') + check_format("'\u20acABC'", + b'%R', '\u20acABC') + check_format("'\u20acA", + b'%.3R', '\u20acABCDEF') + check_format('\u20acAB', + b'%.3S', '\u20acABCDEF') + check_format('\u20acAB', + b'%.3U', '\u20acABCDEF') + check_format('\u20acAB', + b'%.3V', '\u20acABCDEF', None) + check_format('abc[\ufffd', + b'%.5V', None, 'abc[\u20ac]'.encode('utf8')) + + # following tests comes from #7330 + # test width modifier and precision modifier with %S + check_format("repr= abc", + b'repr=%5S', 'abc') + check_format("repr=ab", + b'repr=%.2S', 'abc') + check_format("repr= ab", + b'repr=%5.2S', 'abc') + + # test width modifier and precision modifier with %R + check_format("repr= 'abc'", + b'repr=%8R', 'abc') + check_format("repr='ab", + b'repr=%.3R', 'abc') + check_format("repr= 'ab", + b'repr=%5.3R', 'abc') + + # test width modifier and precision modifier with %A + check_format("repr= 'abc'", + b'repr=%8A', 'abc') + check_format("repr='ab", + b'repr=%.3A', 'abc') + check_format("repr= 'ab", + b'repr=%5.3A', 'abc') + + # test width modifier and precision modifier with %s + check_format("repr= abc", + b'repr=%5s', b'abc') + check_format("repr=ab", + b'repr=%.2s', b'abc') + check_format("repr= ab", + b'repr=%5.2s', b'abc') + + # test width modifier and precision modifier with %U + check_format("repr= abc", + b'repr=%5U', 'abc') + check_format("repr=ab", + b'repr=%.2U', 'abc') + check_format("repr= ab", + b'repr=%5.2U', 'abc') + + # test width modifier and precision modifier with %V + check_format("repr= abc", + b'repr=%5V', 'abc', b'123') + check_format("repr=ab", + b'repr=%.2V', 'abc', b'123') + check_format("repr= ab", + b'repr=%5.2V', 'abc', b'123') + check_format("repr= 123", + b'repr=%5V', None, b'123') + check_format("repr=12", + b'repr=%.2V', None, b'123') + check_format("repr= 12", + b'repr=%5.2V', None, b'123') + + # test integer formats (%i, %d, %u) + check_format('010', + b'%03i', c_int(10)) + check_format('0010', + b'%0.4i', c_int(10)) + check_format('-123', + b'%i', c_int(-123)) + check_format('-123', + b'%li', c_long(-123)) + check_format('-123', + b'%lli', c_longlong(-123)) + check_format('-123', + b'%zi', c_ssize_t(-123)) + + check_format('-123', + b'%d', c_int(-123)) + check_format('-123', + b'%ld', c_long(-123)) + check_format('-123', + b'%lld', c_longlong(-123)) + check_format('-123', + b'%zd', c_ssize_t(-123)) + + check_format('123', + b'%u', c_uint(123)) + check_format('123', + b'%lu', c_ulong(123)) + check_format('123', + b'%llu', c_ulonglong(123)) + check_format('123', + b'%zu', c_size_t(123)) + + # test long output + min_longlong = -(2 ** (8 * sizeof(c_longlong) - 1)) + max_longlong = -min_longlong - 1 + check_format(str(min_longlong), + b'%lld', c_longlong(min_longlong)) + check_format(str(max_longlong), + b'%lld', c_longlong(max_longlong)) + max_ulonglong = 2 ** (8 * sizeof(c_ulonglong)) - 1 + check_format(str(max_ulonglong), + b'%llu', c_ulonglong(max_ulonglong)) + PyUnicode_FromFormat(b'%p', c_void_p(-1)) + + # test padding (width and/or precision) + check_format('123'.rjust(10, '0'), + b'%010i', c_int(123)) + check_format('123'.rjust(100), + b'%100i', c_int(123)) + check_format('123'.rjust(100, '0'), + b'%.100i', c_int(123)) + check_format('123'.rjust(80, '0').rjust(100), + b'%100.80i', c_int(123)) + + check_format('123'.rjust(10, '0'), + b'%010u', c_uint(123)) + check_format('123'.rjust(100), + b'%100u', c_uint(123)) + check_format('123'.rjust(100, '0'), + b'%.100u', c_uint(123)) + check_format('123'.rjust(80, '0').rjust(100), + b'%100.80u', c_uint(123)) + + check_format('123'.rjust(10, '0'), + b'%010x', c_int(0x123)) + check_format('123'.rjust(100), + b'%100x', c_int(0x123)) + check_format('123'.rjust(100, '0'), + b'%.100x', c_int(0x123)) + check_format('123'.rjust(80, '0').rjust(100), + b'%100.80x', c_int(0x123)) + + # test %A + check_format(r"%A:'abc\xe9\uabcd\U0010ffff'", + b'%%A:%A', 'abc\xe9\uabcd\U0010ffff') + + # test %V + check_format('repr=abc', + b'repr=%V', 'abc', b'xyz') + + # test %p + # We cannot test the exact result, + # because it returns a hex representation of a C pointer, + # which is going to be different each time. But, we can test the format. + p_format_regex = r'^0x[a-zA-Z0-9]{3,}$' + p_format1 = PyUnicode_FromFormat(b'%p', 'abc') + self.assertIsInstance(p_format1, str) + self.assertRegex(p_format1, p_format_regex) + + p_format2 = PyUnicode_FromFormat(b'%p %p', '123456', b'xyz') + self.assertIsInstance(p_format2, str) + self.assertRegex(p_format2, + r'0x[a-zA-Z0-9]{3,} 0x[a-zA-Z0-9]{3,}') + + # Extra args are ignored: + p_format3 = PyUnicode_FromFormat(b'%p', '123456', None, b'xyz') + self.assertIsInstance(p_format3, str) + self.assertRegex(p_format3, p_format_regex) + + # Test string decode from parameter of %s using utf-8. + # b'\xe4\xba\xba\xe6\xb0\x91' is utf-8 encoded byte sequence of + # '\u4eba\u6c11' + check_format('repr=\u4eba\u6c11', + b'repr=%V', None, b'\xe4\xba\xba\xe6\xb0\x91') + + #Test replace error handler. + check_format('repr=abc\ufffd', + b'repr=%V', None, b'abc\xff') + + # not supported: copy the raw format string. these tests are just here + # to check for crashes and should not be considered as specifications + check_format('%s', + b'%1%s', b'abc') + check_format('%1abc', + b'%1abc') + check_format('%+i', + b'%+i', c_int(10)) + check_format('%.%s', + b'%.%s', b'abc') + + # Issue #33817: empty strings + check_format('', + b'') + check_format('', + b'%s', b'') + + # Test PyUnicode_AsWideChar() + @support.cpython_only + def test_aswidechar(self): + from _testcapi import unicode_aswidechar + import_helper.import_module('ctypes') + from ctypes import c_wchar, sizeof + + wchar, size = unicode_aswidechar('abcdef', 2) + self.assertEqual(size, 2) + self.assertEqual(wchar, 'ab') + + wchar, size = unicode_aswidechar('abc', 3) + self.assertEqual(size, 3) + self.assertEqual(wchar, 'abc') + + wchar, size = unicode_aswidechar('abc', 4) + self.assertEqual(size, 3) + self.assertEqual(wchar, 'abc\0') + + wchar, size = unicode_aswidechar('abc', 10) + self.assertEqual(size, 3) + self.assertEqual(wchar, 'abc\0') + + wchar, size = unicode_aswidechar('abc\0def', 20) + self.assertEqual(size, 7) + self.assertEqual(wchar, 'abc\0def\0') + + nonbmp = chr(0x10ffff) + if sizeof(c_wchar) == 2: + buflen = 3 + nchar = 2 + else: # sizeof(c_wchar) == 4 + buflen = 2 + nchar = 1 + wchar, size = unicode_aswidechar(nonbmp, buflen) + self.assertEqual(size, nchar) + self.assertEqual(wchar, nonbmp + '\0') + + # Test PyUnicode_AsWideCharString() + @support.cpython_only + def test_aswidecharstring(self): + from _testcapi import unicode_aswidecharstring + import_helper.import_module('ctypes') + from ctypes import c_wchar, sizeof + + wchar, size = unicode_aswidecharstring('abc') + self.assertEqual(size, 3) + self.assertEqual(wchar, 'abc\0') + + wchar, size = unicode_aswidecharstring('abc\0def') + self.assertEqual(size, 7) + self.assertEqual(wchar, 'abc\0def\0') + + nonbmp = chr(0x10ffff) + if sizeof(c_wchar) == 2: + nchar = 2 + else: # sizeof(c_wchar) == 4 + nchar = 1 + wchar, size = unicode_aswidecharstring(nonbmp) + self.assertEqual(size, nchar) + self.assertEqual(wchar, nonbmp + '\0') + + # Test PyUnicode_AsUCS4() + @support.cpython_only + def test_asucs4(self): + from _testcapi import unicode_asucs4 + for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600', + 'a\ud800b\udfffc', '\ud834\udd1e']: + l = len(s) + self.assertEqual(unicode_asucs4(s, l, True), s+'\0') + self.assertEqual(unicode_asucs4(s, l, False), s+'\uffff') + self.assertEqual(unicode_asucs4(s, l+1, True), s+'\0\uffff') + self.assertEqual(unicode_asucs4(s, l+1, False), s+'\0\uffff') + self.assertRaises(SystemError, unicode_asucs4, s, l-1, True) + self.assertRaises(SystemError, unicode_asucs4, s, l-2, False) + s = '\0'.join([s, s]) + self.assertEqual(unicode_asucs4(s, len(s), True), s+'\0') + self.assertEqual(unicode_asucs4(s, len(s), False), s+'\uffff') + + # Test PyUnicode_AsUTF8() + @support.cpython_only + def test_asutf8(self): + from _testcapi import unicode_asutf8 + + bmp = '\u0100' + bmp2 = '\uffff' + nonbmp = chr(0x10ffff) + + self.assertEqual(unicode_asutf8(bmp), b'\xc4\x80') + self.assertEqual(unicode_asutf8(bmp2), b'\xef\xbf\xbf') + self.assertEqual(unicode_asutf8(nonbmp), b'\xf4\x8f\xbf\xbf') + self.assertRaises(UnicodeEncodeError, unicode_asutf8, 'a\ud800b\udfffc') + + # Test PyUnicode_AsUTF8AndSize() + @support.cpython_only + def test_asutf8andsize(self): + from _testcapi import unicode_asutf8andsize + + bmp = '\u0100' + bmp2 = '\uffff' + nonbmp = chr(0x10ffff) + + self.assertEqual(unicode_asutf8andsize(bmp), (b'\xc4\x80', 2)) + self.assertEqual(unicode_asutf8andsize(bmp2), (b'\xef\xbf\xbf', 3)) + self.assertEqual(unicode_asutf8andsize(nonbmp), (b'\xf4\x8f\xbf\xbf', 4)) + self.assertRaises(UnicodeEncodeError, unicode_asutf8andsize, 'a\ud800b\udfffc') + + # Test PyUnicode_FindChar() + @support.cpython_only + def test_findchar(self): + from _testcapi import unicode_findchar + + for str in "\xa1", "\u8000\u8080", "\ud800\udc02", "\U0001f100\U0001f1f1": + for i, ch in enumerate(str): + self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), 1), i) + self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), -1), i) + + str = "!>_= end + self.assertEqual(unicode_findchar(str, ord('!'), 0, 0, 1), -1) + self.assertEqual(unicode_findchar(str, ord('!'), len(str), 0, 1), -1) + # negative + self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, 1), 0) + self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, -1), 0) + + # Test PyUnicode_CopyCharacters() + @support.cpython_only + def test_copycharacters(self): + from _testcapi import unicode_copycharacters + + strings = [ + 'abcde', '\xa1\xa2\xa3\xa4\xa5', + '\u4f60\u597d\u4e16\u754c\uff01', + '\U0001f600\U0001f601\U0001f602\U0001f603\U0001f604' + ] + + for idx, from_ in enumerate(strings): + # wide -> narrow: exceed maxchar limitation + for to in strings[:idx]: + self.assertRaises( + SystemError, + unicode_copycharacters, to, 0, from_, 0, 5 + ) + # same kind + for from_start in range(5): + self.assertEqual( + unicode_copycharacters(from_, 0, from_, from_start, 5), + (from_[from_start:from_start+5].ljust(5, '\0'), + 5-from_start) + ) + for to_start in range(5): + self.assertEqual( + unicode_copycharacters(from_, to_start, from_, to_start, 5), + (from_[to_start:to_start+5].rjust(5, '\0'), + 5-to_start) + ) + # narrow -> wide + # Tests omitted since this creates invalid strings. + + s = strings[0] + self.assertRaises(IndexError, unicode_copycharacters, s, 6, s, 0, 5) + self.assertRaises(IndexError, unicode_copycharacters, s, -1, s, 0, 5) + self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, 6, 5) + self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, -1, 5) + self.assertRaises(SystemError, unicode_copycharacters, s, 1, s, 0, 5) + self.assertRaises(SystemError, unicode_copycharacters, s, 0, s, 0, -1) + self.assertRaises(SystemError, unicode_copycharacters, s, 0, b'', 0, 0) + + @support.cpython_only + @support.requires_legacy_unicode_capi + def test_encode_decimal(self): + from _testcapi import unicode_encodedecimal + with warnings_helper.check_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + self.assertEqual(unicode_encodedecimal('123'), + b'123') + self.assertEqual(unicode_encodedecimal('\u0663.\u0661\u0664'), + b'3.14') + self.assertEqual(unicode_encodedecimal( + "\N{EM SPACE}3.14\N{EN SPACE}"), b' 3.14 ') + self.assertRaises(UnicodeEncodeError, + unicode_encodedecimal, "123\u20ac", "strict") + self.assertRaisesRegex( + ValueError, + "^'decimal' codec can't encode character", + unicode_encodedecimal, "123\u20ac", "replace") + + @support.cpython_only + @support.requires_legacy_unicode_capi + def test_transform_decimal(self): + from _testcapi import unicode_transformdecimaltoascii as transform_decimal + with warnings_helper.check_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + self.assertEqual(transform_decimal('123'), + '123') + self.assertEqual(transform_decimal('\u0663.\u0661\u0664'), + '3.14') + self.assertEqual(transform_decimal("\N{EM SPACE}3.14\N{EN SPACE}"), + "\N{EM SPACE}3.14\N{EN SPACE}") + self.assertEqual(transform_decimal('123\u20ac'), + '123\u20ac') + + @support.cpython_only + def test_pep393_utf8_caching_bug(self): + # Issue #25709: Problem with string concatenation and utf-8 cache + from _testcapi import getargs_s_hash + for k in 0x24, 0xa4, 0x20ac, 0x1f40d: + s = '' + for i in range(5): + # Due to CPython specific optimization the 's' string can be + # resized in-place. + s += chr(k) + # Parsing with the "s#" format code calls indirectly + # PyUnicode_AsUTF8AndSize() which creates the UTF-8 + # encoded string cached in the Unicode object. + self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1)) + # Check that the second call returns the same result + self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1)) + + +if __name__ == "__main__": + unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_capi.py python3.10-3.10.12/Lib/test/test_capi.py --- python3.10-3.10.7/Lib/test/test_capi.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_capi.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,1065 +0,0 @@ -# Run the _testcapi module tests (tests for the Python/C API): by defn, -# these are all functions _testcapi exports whose name begins with 'test_'. - -from collections import OrderedDict -import importlib.machinery -import importlib.util -import os -import pickle -import random -import re -import subprocess -import sys -import textwrap -import threading -import time -import unittest -import weakref -from test import support -from test.support import MISSING_C_DOCSTRINGS -from test.support import import_helper -from test.support import threading_helper -from test.support import warnings_helper -from test.support.script_helper import assert_python_failure, assert_python_ok -try: - import _posixsubprocess -except ImportError: - _posixsubprocess = None - -# Skip this test if the _testcapi module isn't available. -_testcapi = import_helper.import_module('_testcapi') - -import _testinternalcapi - -# Were we compiled --with-pydebug or with #define Py_DEBUG? -Py_DEBUG = hasattr(sys, 'gettotalrefcount') - - -def decode_stderr(err): - return err.decode('utf-8', 'replace').replace('\r', '') - - -def testfunction(self): - """some doc""" - return self - - -class InstanceMethod: - id = _testcapi.instancemethod(id) - testfunction = _testcapi.instancemethod(testfunction) - -class CAPITest(unittest.TestCase): - - def test_instancemethod(self): - inst = InstanceMethod() - self.assertEqual(id(inst), inst.id()) - self.assertTrue(inst.testfunction() is inst) - self.assertEqual(inst.testfunction.__doc__, testfunction.__doc__) - self.assertEqual(InstanceMethod.testfunction.__doc__, testfunction.__doc__) - - InstanceMethod.testfunction.attribute = "test" - self.assertEqual(testfunction.attribute, "test") - self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test") - - def test_no_FatalError_infinite_loop(self): - with support.SuppressCrashReport(): - p = subprocess.Popen([sys.executable, "-c", - 'import _testcapi;' - '_testcapi.crash_no_current_thread()'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (out, err) = p.communicate() - self.assertEqual(out, b'') - # This used to cause an infinite loop. - self.assertTrue(err.rstrip().startswith( - b'Fatal Python error: ' - b'PyThreadState_Get: ' - b'the function must be called with the GIL held, ' - b'but the GIL is released ' - b'(the current Python thread state is NULL)'), - err) - - def test_memoryview_from_NULL_pointer(self): - self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) - - def test_exc_info(self): - raised_exception = ValueError("5") - new_exc = TypeError("TEST") - try: - raise raised_exception - except ValueError as e: - tb = e.__traceback__ - orig_sys_exc_info = sys.exc_info() - orig_exc_info = _testcapi.set_exc_info(new_exc.__class__, new_exc, None) - new_sys_exc_info = sys.exc_info() - new_exc_info = _testcapi.set_exc_info(*orig_exc_info) - reset_sys_exc_info = sys.exc_info() - - self.assertEqual(orig_exc_info[1], e) - - self.assertSequenceEqual(orig_exc_info, (raised_exception.__class__, raised_exception, tb)) - self.assertSequenceEqual(orig_sys_exc_info, orig_exc_info) - self.assertSequenceEqual(reset_sys_exc_info, orig_exc_info) - self.assertSequenceEqual(new_exc_info, (new_exc.__class__, new_exc, None)) - self.assertSequenceEqual(new_sys_exc_info, new_exc_info) - else: - self.assertTrue(False) - - @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') - def test_seq_bytes_to_charp_array(self): - # Issue #15732: crash in _PySequence_BytesToCharpArray() - class Z(object): - def __len__(self): - return 1 - self.assertRaises(TypeError, _posixsubprocess.fork_exec, - 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) - # Issue #15736: overflow in _PySequence_BytesToCharpArray() - class Z(object): - def __len__(self): - return sys.maxsize - def __getitem__(self, i): - return b'x' - self.assertRaises(MemoryError, _posixsubprocess.fork_exec, - 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) - - @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') - def test_subprocess_fork_exec(self): - class Z(object): - def __len__(self): - return 1 - - # Issue #15738: crash in subprocess_fork_exec() - self.assertRaises(TypeError, _posixsubprocess.fork_exec, - Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) - - @unittest.skipIf(MISSING_C_DOCSTRINGS, - "Signature information for builtins requires docstrings") - def test_docstring_signature_parsing(self): - - self.assertEqual(_testcapi.no_docstring.__doc__, None) - self.assertEqual(_testcapi.no_docstring.__text_signature__, None) - - self.assertEqual(_testcapi.docstring_empty.__doc__, None) - self.assertEqual(_testcapi.docstring_empty.__text_signature__, None) - - self.assertEqual(_testcapi.docstring_no_signature.__doc__, - "This docstring has no signature.") - self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None) - - self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__, - "docstring_with_invalid_signature($module, /, boo)\n" - "\n" - "This docstring has an invalid signature." - ) - self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None) - - self.assertEqual(_testcapi.docstring_with_invalid_signature2.__doc__, - "docstring_with_invalid_signature2($module, /, boo)\n" - "\n" - "--\n" - "\n" - "This docstring also has an invalid signature." - ) - self.assertEqual(_testcapi.docstring_with_invalid_signature2.__text_signature__, None) - - self.assertEqual(_testcapi.docstring_with_signature.__doc__, - "This docstring has a valid signature.") - self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)") - - self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__doc__, None) - self.assertEqual(_testcapi.docstring_with_signature_but_no_doc.__text_signature__, - "($module, /, sig)") - - self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__, - "\nThis docstring has a valid signature and some extra newlines.") - self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__, - "($module, /, parameter)") - - def test_c_type_with_matrix_multiplication(self): - M = _testcapi.matmulType - m1 = M() - m2 = M() - self.assertEqual(m1 @ m2, ("matmul", m1, m2)) - self.assertEqual(m1 @ 42, ("matmul", m1, 42)) - self.assertEqual(42 @ m1, ("matmul", 42, m1)) - o = m1 - o @= m2 - self.assertEqual(o, ("imatmul", m1, m2)) - o = m1 - o @= 42 - self.assertEqual(o, ("imatmul", m1, 42)) - o = 42 - o @= m1 - self.assertEqual(o, ("matmul", 42, m1)) - - def test_c_type_with_ipow(self): - # When the __ipow__ method of a type was implemented in C, using the - # modulo param would cause segfaults. - o = _testcapi.ipowType() - self.assertEqual(o.__ipow__(1), (1, None)) - self.assertEqual(o.__ipow__(2, 2), (2, 2)) - - def test_return_null_without_error(self): - # Issue #23571: A function must not return NULL without setting an - # error - if Py_DEBUG: - code = textwrap.dedent(""" - import _testcapi - from test import support - - with support.SuppressCrashReport(): - _testcapi.return_null_without_error() - """) - rc, out, err = assert_python_failure('-c', code) - err = decode_stderr(err) - self.assertRegex(err, - r'Fatal Python error: _Py_CheckFunctionResult: ' - r'a function returned NULL without setting an exception\n' - r'Python runtime state: initialized\n' - r'SystemError: ' - r'returned NULL without setting an exception\n' - r'\n' - r'Current thread.*:\n' - r' File .*", line 6 in \n') - else: - with self.assertRaises(SystemError) as cm: - _testcapi.return_null_without_error() - self.assertRegex(str(cm.exception), - 'return_null_without_error.* ' - 'returned NULL without setting an exception') - - def test_return_result_with_error(self): - # Issue #23571: A function must not return a result with an error set - if Py_DEBUG: - code = textwrap.dedent(""" - import _testcapi - from test import support - - with support.SuppressCrashReport(): - _testcapi.return_result_with_error() - """) - rc, out, err = assert_python_failure('-c', code) - err = decode_stderr(err) - self.assertRegex(err, - r'Fatal Python error: _Py_CheckFunctionResult: ' - r'a function returned a result with an exception set\n' - r'Python runtime state: initialized\n' - r'ValueError\n' - r'\n' - r'The above exception was the direct cause ' - r'of the following exception:\n' - r'\n' - r'SystemError: ' - r'returned a result with an exception set\n' - r'\n' - r'Current thread.*:\n' - r' File .*, line 6 in \n') - else: - with self.assertRaises(SystemError) as cm: - _testcapi.return_result_with_error() - self.assertRegex(str(cm.exception), - 'return_result_with_error.* ' - 'returned a result with an exception set') - - def test_getitem_with_error(self): - # Test _Py_CheckSlotResult(). Raise an exception and then calls - # PyObject_GetItem(): check that the assertion catches the bug. - # PyObject_GetItem() must not be called with an exception set. - code = textwrap.dedent(""" - import _testcapi - from test import support - - with support.SuppressCrashReport(): - _testcapi.getitem_with_error({1: 2}, 1) - """) - rc, out, err = assert_python_failure('-c', code) - err = decode_stderr(err) - if 'SystemError: ' not in err: - self.assertRegex(err, - r'Fatal Python error: _Py_CheckSlotResult: ' - r'Slot __getitem__ of type dict succeeded ' - r'with an exception set\n' - r'Python runtime state: initialized\n' - r'ValueError: bug\n' - r'\n' - r'Current thread .* \(most recent call first\):\n' - r' File .*, line 6 in \n' - r'\n' - r'Extension modules: _testcapi \(total: 1\)\n') - else: - # Python built with NDEBUG macro defined: - # test _Py_CheckFunctionResult() instead. - self.assertIn('returned a result with an exception set', err) - - def test_buildvalue_N(self): - _testcapi.test_buildvalue_N() - - def test_set_nomemory(self): - code = """if 1: - import _testcapi - - class C(): pass - - # The first loop tests both functions and that remove_mem_hooks() - # can be called twice in a row. The second loop checks a call to - # set_nomemory() after a call to remove_mem_hooks(). The third - # loop checks the start and stop arguments of set_nomemory(). - for outer_cnt in range(1, 4): - start = 10 * outer_cnt - for j in range(100): - if j == 0: - if outer_cnt != 3: - _testcapi.set_nomemory(start) - else: - _testcapi.set_nomemory(start, start + 1) - try: - C() - except MemoryError as e: - if outer_cnt != 3: - _testcapi.remove_mem_hooks() - print('MemoryError', outer_cnt, j) - _testcapi.remove_mem_hooks() - break - """ - rc, out, err = assert_python_ok('-c', code) - self.assertIn(b'MemoryError 1 10', out) - self.assertIn(b'MemoryError 2 20', out) - self.assertIn(b'MemoryError 3 30', out) - - def test_mapping_keys_values_items(self): - class Mapping1(dict): - def keys(self): - return list(super().keys()) - def values(self): - return list(super().values()) - def items(self): - return list(super().items()) - class Mapping2(dict): - def keys(self): - return tuple(super().keys()) - def values(self): - return tuple(super().values()) - def items(self): - return tuple(super().items()) - dict_obj = {'foo': 1, 'bar': 2, 'spam': 3} - - for mapping in [{}, OrderedDict(), Mapping1(), Mapping2(), - dict_obj, OrderedDict(dict_obj), - Mapping1(dict_obj), Mapping2(dict_obj)]: - self.assertListEqual(_testcapi.get_mapping_keys(mapping), - list(mapping.keys())) - self.assertListEqual(_testcapi.get_mapping_values(mapping), - list(mapping.values())) - self.assertListEqual(_testcapi.get_mapping_items(mapping), - list(mapping.items())) - - def test_mapping_keys_values_items_bad_arg(self): - self.assertRaises(AttributeError, _testcapi.get_mapping_keys, None) - self.assertRaises(AttributeError, _testcapi.get_mapping_values, None) - self.assertRaises(AttributeError, _testcapi.get_mapping_items, None) - - class BadMapping: - def keys(self): - return None - def values(self): - return None - def items(self): - return None - bad_mapping = BadMapping() - self.assertRaises(TypeError, _testcapi.get_mapping_keys, bad_mapping) - self.assertRaises(TypeError, _testcapi.get_mapping_values, bad_mapping) - self.assertRaises(TypeError, _testcapi.get_mapping_items, bad_mapping) - - @unittest.skipUnless(hasattr(_testcapi, 'negative_refcount'), - 'need _testcapi.negative_refcount') - def test_negative_refcount(self): - # bpo-35059: Check that Py_DECREF() reports the correct filename - # when calling _Py_NegativeRefcount() to abort Python. - code = textwrap.dedent(""" - import _testcapi - from test import support - - with support.SuppressCrashReport(): - _testcapi.negative_refcount() - """) - rc, out, err = assert_python_failure('-c', code) - self.assertRegex(err, - br'_testcapimodule\.c:[0-9]+: ' - br'_Py_NegativeRefcount: Assertion failed: ' - br'object has negative ref count') - - def test_trashcan_subclass(self): - # bpo-35983: Check that the trashcan mechanism for "list" is NOT - # activated when its tp_dealloc is being called by a subclass - from _testcapi import MyList - L = None - for i in range(1000): - L = MyList((L,)) - - @support.requires_resource('cpu') - def test_trashcan_python_class1(self): - self.do_test_trashcan_python_class(list) - - @support.requires_resource('cpu') - def test_trashcan_python_class2(self): - from _testcapi import MyList - self.do_test_trashcan_python_class(MyList) - - def do_test_trashcan_python_class(self, base): - # Check that the trashcan mechanism works properly for a Python - # subclass of a class using the trashcan (this specific test assumes - # that the base class "base" behaves like list) - class PyList(base): - # Count the number of PyList instances to verify that there is - # no memory leak - num = 0 - def __init__(self, *args): - __class__.num += 1 - super().__init__(*args) - def __del__(self): - __class__.num -= 1 - - for parity in (0, 1): - L = None - # We need in the order of 2**20 iterations here such that a - # typical 8MB stack would overflow without the trashcan. - for i in range(2**20): - L = PyList((L,)) - L.attr = i - if parity: - # Add one additional nesting layer - L = (L,) - self.assertGreater(PyList.num, 0) - del L - self.assertEqual(PyList.num, 0) - - def test_heap_ctype_doc_and_text_signature(self): - self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc") - self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)") - - def test_null_type_doc(self): - self.assertEqual(_testcapi.NullTpDocType.__doc__, None) - - def test_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self): - class HeapGcCTypeSubclass(_testcapi.HeapGcCType): - def __init__(self): - self.value2 = 20 - super().__init__() - - subclass_instance = HeapGcCTypeSubclass() - type_refcnt = sys.getrefcount(HeapGcCTypeSubclass) - - # Test that subclass instance was fully created - self.assertEqual(subclass_instance.value, 10) - self.assertEqual(subclass_instance.value2, 20) - - # Test that the type reference count is only decremented once - del subclass_instance - self.assertEqual(type_refcnt - 1, sys.getrefcount(HeapGcCTypeSubclass)) - - def test_subclass_of_heap_gc_ctype_with_del_modifying_dunder_class_only_decrefs_once(self): - class A(_testcapi.HeapGcCType): - def __init__(self): - self.value2 = 20 - super().__init__() - - class B(A): - def __init__(self): - super().__init__() - - def __del__(self): - self.__class__ = A - A.refcnt_in_del = sys.getrefcount(A) - B.refcnt_in_del = sys.getrefcount(B) - - subclass_instance = B() - type_refcnt = sys.getrefcount(B) - new_type_refcnt = sys.getrefcount(A) - - # Test that subclass instance was fully created - self.assertEqual(subclass_instance.value, 10) - self.assertEqual(subclass_instance.value2, 20) - - del subclass_instance - - # Test that setting __class__ modified the reference counts of the types - self.assertEqual(type_refcnt - 1, B.refcnt_in_del) - self.assertEqual(new_type_refcnt + 1, A.refcnt_in_del) - - # Test that the original type already has decreased its refcnt - self.assertEqual(type_refcnt - 1, sys.getrefcount(B)) - - # Test that subtype_dealloc decref the newly assigned __class__ only once - self.assertEqual(new_type_refcnt, sys.getrefcount(A)) - - def test_heaptype_with_dict(self): - inst = _testcapi.HeapCTypeWithDict() - inst.foo = 42 - self.assertEqual(inst.foo, 42) - self.assertEqual(inst.dictobj, inst.__dict__) - self.assertEqual(inst.dictobj, {"foo": 42}) - - inst = _testcapi.HeapCTypeWithDict() - self.assertEqual({}, inst.__dict__) - - def test_heaptype_with_negative_dict(self): - inst = _testcapi.HeapCTypeWithNegativeDict() - inst.foo = 42 - self.assertEqual(inst.foo, 42) - self.assertEqual(inst.dictobj, inst.__dict__) - self.assertEqual(inst.dictobj, {"foo": 42}) - - inst = _testcapi.HeapCTypeWithNegativeDict() - self.assertEqual({}, inst.__dict__) - - def test_heaptype_with_weakref(self): - inst = _testcapi.HeapCTypeWithWeakref() - ref = weakref.ref(inst) - self.assertEqual(ref(), inst) - self.assertEqual(inst.weakreflist, ref) - - def test_heaptype_with_buffer(self): - inst = _testcapi.HeapCTypeWithBuffer() - b = bytes(inst) - self.assertEqual(b, b"1234") - - def test_c_subclass_of_heap_ctype_with_tpdealloc_decrefs_once(self): - subclass_instance = _testcapi.HeapCTypeSubclass() - type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass) - - # Test that subclass instance was fully created - self.assertEqual(subclass_instance.value, 10) - self.assertEqual(subclass_instance.value2, 20) - - # Test that the type reference count is only decremented once - del subclass_instance - self.assertEqual(type_refcnt - 1, sys.getrefcount(_testcapi.HeapCTypeSubclass)) - - def test_c_subclass_of_heap_ctype_with_del_modifying_dunder_class_only_decrefs_once(self): - subclass_instance = _testcapi.HeapCTypeSubclassWithFinalizer() - type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclassWithFinalizer) - new_type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass) - - # Test that subclass instance was fully created - self.assertEqual(subclass_instance.value, 10) - self.assertEqual(subclass_instance.value2, 20) - - # The tp_finalize slot will set __class__ to HeapCTypeSubclass - del subclass_instance - - # Test that setting __class__ modified the reference counts of the types - self.assertEqual(type_refcnt - 1, _testcapi.HeapCTypeSubclassWithFinalizer.refcnt_in_del) - self.assertEqual(new_type_refcnt + 1, _testcapi.HeapCTypeSubclass.refcnt_in_del) - - # Test that the original type already has decreased its refcnt - self.assertEqual(type_refcnt - 1, sys.getrefcount(_testcapi.HeapCTypeSubclassWithFinalizer)) - - # Test that subtype_dealloc decref the newly assigned __class__ only once - self.assertEqual(new_type_refcnt, sys.getrefcount(_testcapi.HeapCTypeSubclass)) - - def test_heaptype_with_setattro(self): - obj = _testcapi.HeapCTypeSetattr() - self.assertEqual(obj.pvalue, 10) - obj.value = 12 - self.assertEqual(obj.pvalue, 12) - del obj.value - self.assertEqual(obj.pvalue, 0) - - def test_pynumber_tobase(self): - from _testcapi import pynumber_tobase - self.assertEqual(pynumber_tobase(123, 2), '0b1111011') - self.assertEqual(pynumber_tobase(123, 8), '0o173') - self.assertEqual(pynumber_tobase(123, 10), '123') - self.assertEqual(pynumber_tobase(123, 16), '0x7b') - self.assertEqual(pynumber_tobase(-123, 2), '-0b1111011') - self.assertEqual(pynumber_tobase(-123, 8), '-0o173') - self.assertEqual(pynumber_tobase(-123, 10), '-123') - self.assertEqual(pynumber_tobase(-123, 16), '-0x7b') - self.assertRaises(TypeError, pynumber_tobase, 123.0, 10) - self.assertRaises(TypeError, pynumber_tobase, '123', 10) - self.assertRaises(SystemError, pynumber_tobase, 123, 0) - - def check_fatal_error(self, code, expected, not_expected=()): - with support.SuppressCrashReport(): - rc, out, err = assert_python_failure('-sSI', '-c', code) - - err = decode_stderr(err) - self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n', - err) - - match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$', - err, re.MULTILINE) - if not match: - self.fail(f"Cannot find 'Extension modules:' in {err!r}") - modules = set(match.group(1).strip().split(', ')) - total = int(match.group(2)) - - for name in expected: - self.assertIn(name, modules) - for name in not_expected: - self.assertNotIn(name, modules) - self.assertEqual(len(modules), total) - - def test_fatal_error(self): - # By default, stdlib extension modules are ignored, - # but not test modules. - expected = ('_testcapi',) - not_expected = ('sys',) - code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")' - self.check_fatal_error(code, expected, not_expected) - - # Mark _testcapi as stdlib module, but not sys - expected = ('sys',) - not_expected = ('_testcapi',) - code = textwrap.dedent(''' - import _testcapi, sys - sys.stdlib_module_names = frozenset({"_testcapi"}) - _testcapi.fatal_error(b"MESSAGE") - ''') - self.check_fatal_error(code, expected) - - def test_pyobject_repr_from_null(self): - s = _testcapi.pyobject_repr_from_null() - self.assertEqual(s, '') - - def test_pyobject_str_from_null(self): - s = _testcapi.pyobject_str_from_null() - self.assertEqual(s, '') - - def test_pyobject_bytes_from_null(self): - s = _testcapi.pyobject_bytes_from_null() - self.assertEqual(s, b'') - - def test_Py_CompileString(self): - # Check that Py_CompileString respects the coding cookie - _compile = _testcapi.Py_CompileString - code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" - result = _compile(code) - expected = compile(code, "", "exec") - self.assertEqual(result.co_consts, expected.co_consts) - - -class TestPendingCalls(unittest.TestCase): - - def pendingcalls_submit(self, l, n): - def callback(): - #this function can be interrupted by thread switching so let's - #use an atomic operation - l.append(None) - - for i in range(n): - time.sleep(random.random()*0.02) #0.01 secs on average - #try submitting callback until successful. - #rely on regular interrupt to flush queue if we are - #unsuccessful. - while True: - if _testcapi._pending_threadfunc(callback): - break - - def pendingcalls_wait(self, l, n, context = None): - #now, stick around until l[0] has grown to 10 - count = 0 - while len(l) != n: - #this busy loop is where we expect to be interrupted to - #run our callbacks. Note that callbacks are only run on the - #main thread - if False and support.verbose: - print("(%i)"%(len(l),),) - for i in range(1000): - a = i*i - if context and not context.event.is_set(): - continue - count += 1 - self.assertTrue(count < 10000, - "timeout waiting for %i callbacks, got %i"%(n, len(l))) - if False and support.verbose: - print("(%i)"%(len(l),)) - - def test_pendingcalls_threaded(self): - - #do every callback on a separate thread - n = 32 #total callbacks - threads = [] - class foo(object):pass - context = foo() - context.l = [] - context.n = 2 #submits per thread - context.nThreads = n // context.n - context.nFinished = 0 - context.lock = threading.Lock() - context.event = threading.Event() - - threads = [threading.Thread(target=self.pendingcalls_thread, - args=(context,)) - for i in range(context.nThreads)] - with threading_helper.start_threads(threads): - self.pendingcalls_wait(context.l, n, context) - - def pendingcalls_thread(self, context): - try: - self.pendingcalls_submit(context.l, context.n) - finally: - with context.lock: - context.nFinished += 1 - nFinished = context.nFinished - if False and support.verbose: - print("finished threads: ", nFinished) - if nFinished == context.nThreads: - context.event.set() - - def test_pendingcalls_non_threaded(self): - #again, just using the main thread, likely they will all be dispatched at - #once. It is ok to ask for too many, because we loop until we find a slot. - #the loop can be interrupted to dispatch. - #there are only 32 dispatch slots, so we go for twice that! - l = [] - n = 64 - self.pendingcalls_submit(l, n) - self.pendingcalls_wait(l, n) - - -class SubinterpreterTest(unittest.TestCase): - - def test_subinterps(self): - import builtins - r, w = os.pipe() - code = """if 1: - import sys, builtins, pickle - with open({:d}, "wb") as f: - pickle.dump(id(sys.modules), f) - pickle.dump(id(builtins), f) - """.format(w) - with open(r, "rb") as f: - ret = support.run_in_subinterp(code) - self.assertEqual(ret, 0) - self.assertNotEqual(pickle.load(f), id(sys.modules)) - self.assertNotEqual(pickle.load(f), id(builtins)) - - def test_subinterps_recent_language_features(self): - r, w = os.pipe() - code = """if 1: - import pickle - with open({:d}, "wb") as f: - - @(lambda x:x) # Py 3.9 - def noop(x): return x - - a = (b := f'1{{2}}3') + noop('x') # Py 3.8 (:=) / 3.6 (f'') - - async def foo(arg): return await arg # Py 3.5 - - pickle.dump(dict(a=a, b=b), f) - """.format(w) - - with open(r, "rb") as f: - ret = support.run_in_subinterp(code) - self.assertEqual(ret, 0) - self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'}) - - def test_mutate_exception(self): - """ - Exceptions saved in global module state get shared between - individual module instances. This test checks whether or not - a change in one interpreter's module gets reflected into the - other ones. - """ - import binascii - - support.run_in_subinterp("import binascii; binascii.Error.foobar = 'foobar'") - - self.assertFalse(hasattr(binascii.Error, "foobar")) - - def test_module_state_shared_in_global(self): - """ - bpo-44050: Extension module state should be shared between interpreters - when it doesn't support sub-interpreters. - """ - r, w = os.pipe() - self.addCleanup(os.close, r) - self.addCleanup(os.close, w) - - script = textwrap.dedent(f""" - import importlib.machinery - import importlib.util - import os - - fullname = '_test_module_state_shared' - origin = importlib.util.find_spec('_testmultiphase').origin - loader = importlib.machinery.ExtensionFileLoader(fullname, origin) - spec = importlib.util.spec_from_loader(fullname, loader) - module = importlib.util.module_from_spec(spec) - attr_id = str(id(module.Error)).encode() - - os.write({w}, attr_id) - """) - exec(script) - main_attr_id = os.read(r, 100) - - ret = support.run_in_subinterp(script) - self.assertEqual(ret, 0) - subinterp_attr_id = os.read(r, 100) - self.assertEqual(main_attr_id, subinterp_attr_id) - - -class TestThreadState(unittest.TestCase): - - @threading_helper.reap_threads - def test_thread_state(self): - # some extra thread-state tests driven via _testcapi - def target(): - idents = [] - - def callback(): - idents.append(threading.get_ident()) - - _testcapi._test_thread_state(callback) - a = b = callback - time.sleep(1) - # Check our main thread is in the list exactly 3 times. - self.assertEqual(idents.count(threading.get_ident()), 3, - "Couldn't find main thread correctly in the list") - - target() - t = threading.Thread(target=target) - t.start() - t.join() - - @threading_helper.reap_threads - def test_gilstate_ensure_no_deadlock(self): - # See https://github.com/python/cpython/issues/96071 - code = textwrap.dedent(f""" - import _testcapi - - def callback(): - print('callback called') - - _testcapi._test_thread_state(callback) - """) - ret = assert_python_ok('-X', 'tracemalloc', '-c', code) - self.assertIn(b'callback called', ret.out) - - -class Test_testcapi(unittest.TestCase): - locals().update((name, getattr(_testcapi, name)) - for name in dir(_testcapi) - if name.startswith('test_') and not name.endswith('_code')) - - # Suppress warning from PyUnicode_FromUnicode(). - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_widechar(self): - _testcapi.test_widechar() - - -class Test_testinternalcapi(unittest.TestCase): - locals().update((name, getattr(_testinternalcapi, name)) - for name in dir(_testinternalcapi) - if name.startswith('test_')) - - -class PyMemDebugTests(unittest.TestCase): - PYTHONMALLOC = 'debug' - # '0x04c06e0' or '04C06E0' - PTR_REGEX = r'(?:0x)?[0-9a-fA-F]+' - - def check(self, code): - with support.SuppressCrashReport(): - out = assert_python_failure( - '-c', code, - PYTHONMALLOC=self.PYTHONMALLOC, - # FreeBSD: instruct jemalloc to not fill freed() memory - # with junk byte 0x5a, see JEMALLOC(3) - MALLOC_CONF="junk:false", - ) - stderr = out.err - return stderr.decode('ascii', 'replace') - - def test_buffer_overflow(self): - out = self.check('import _testcapi; _testcapi.pymem_buffer_overflow()') - regex = (r"Debug memory block at address p={ptr}: API 'm'\n" - r" 16 bytes originally requested\n" - r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n" - r" The [0-9] pad bytes at tail={ptr} are not all FORBIDDENBYTE \(0x[0-9a-f]{{2}}\):\n" - r" at tail\+0: 0x78 \*\*\* OUCH\n" - r" at tail\+1: 0xfd\n" - r" at tail\+2: 0xfd\n" - r" .*\n" - r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?" - r" Data at p: cd cd cd .*\n" - r"\n" - r"Enable tracemalloc to get the memory block allocation traceback\n" - r"\n" - r"Fatal Python error: _PyMem_DebugRawFree: bad trailing pad byte") - regex = regex.format(ptr=self.PTR_REGEX) - regex = re.compile(regex, flags=re.DOTALL) - self.assertRegex(out, regex) - - def test_api_misuse(self): - out = self.check('import _testcapi; _testcapi.pymem_api_misuse()') - regex = (r"Debug memory block at address p={ptr}: API 'm'\n" - r" 16 bytes originally requested\n" - r" The [0-9] pad bytes at p-[0-9] are FORBIDDENBYTE, as expected.\n" - r" The [0-9] pad bytes at tail={ptr} are FORBIDDENBYTE, as expected.\n" - r"( The block was made by call #[0-9]+ to debug malloc/realloc.\n)?" - r" Data at p: cd cd cd .*\n" - r"\n" - r"Enable tracemalloc to get the memory block allocation traceback\n" - r"\n" - r"Fatal Python error: _PyMem_DebugRawFree: bad ID: Allocated using API 'm', verified using API 'r'\n") - regex = regex.format(ptr=self.PTR_REGEX) - self.assertRegex(out, regex) - - def check_malloc_without_gil(self, code): - out = self.check(code) - expected = ('Fatal Python error: _PyMem_DebugMalloc: ' - 'Python memory allocator called without holding the GIL') - self.assertIn(expected, out) - - def test_pymem_malloc_without_gil(self): - # Debug hooks must raise an error if PyMem_Malloc() is called - # without holding the GIL - code = 'import _testcapi; _testcapi.pymem_malloc_without_gil()' - self.check_malloc_without_gil(code) - - def test_pyobject_malloc_without_gil(self): - # Debug hooks must raise an error if PyObject_Malloc() is called - # without holding the GIL - code = 'import _testcapi; _testcapi.pyobject_malloc_without_gil()' - self.check_malloc_without_gil(code) - - def check_pyobject_is_freed(self, func_name): - code = textwrap.dedent(f''' - import gc, os, sys, _testcapi - # Disable the GC to avoid crash on GC collection - gc.disable() - try: - _testcapi.{func_name}() - # Exit immediately to avoid a crash while deallocating - # the invalid object - os._exit(0) - except _testcapi.error: - os._exit(1) - ''') - assert_python_ok( - '-c', code, - PYTHONMALLOC=self.PYTHONMALLOC, - MALLOC_CONF="junk:false", - ) - - def test_pyobject_null_is_freed(self): - self.check_pyobject_is_freed('check_pyobject_null_is_freed') - - def test_pyobject_uninitialized_is_freed(self): - self.check_pyobject_is_freed('check_pyobject_uninitialized_is_freed') - - def test_pyobject_forbidden_bytes_is_freed(self): - self.check_pyobject_is_freed('check_pyobject_forbidden_bytes_is_freed') - - def test_pyobject_freed_is_freed(self): - self.check_pyobject_is_freed('check_pyobject_freed_is_freed') - - -class PyMemMallocDebugTests(PyMemDebugTests): - PYTHONMALLOC = 'malloc_debug' - - -@unittest.skipUnless(support.with_pymalloc(), 'need pymalloc') -class PyMemPymallocDebugTests(PyMemDebugTests): - PYTHONMALLOC = 'pymalloc_debug' - - -@unittest.skipUnless(Py_DEBUG, 'need Py_DEBUG') -class PyMemDefaultTests(PyMemDebugTests): - # test default allocator of Python compiled in debug mode - PYTHONMALLOC = '' - - -class Test_ModuleStateAccess(unittest.TestCase): - """Test access to module start (PEP 573)""" - - # The C part of the tests lives in _testmultiphase, in a module called - # _testmultiphase_meth_state_access. - # This module has multi-phase initialization, unlike _testcapi. - - def setUp(self): - fullname = '_testmultiphase_meth_state_access' # XXX - origin = importlib.util.find_spec('_testmultiphase').origin - loader = importlib.machinery.ExtensionFileLoader(fullname, origin) - spec = importlib.util.spec_from_loader(fullname, loader) - module = importlib.util.module_from_spec(spec) - loader.exec_module(module) - self.module = module - - def test_subclass_get_module(self): - """PyType_GetModule for defining_class""" - class StateAccessType_Subclass(self.module.StateAccessType): - pass - - instance = StateAccessType_Subclass() - self.assertIs(instance.get_defining_module(), self.module) - - def test_subclass_get_module_with_super(self): - class StateAccessType_Subclass(self.module.StateAccessType): - def get_defining_module(self): - return super().get_defining_module() - - instance = StateAccessType_Subclass() - self.assertIs(instance.get_defining_module(), self.module) - - def test_state_access(self): - """Checks methods defined with and without argument clinic - - This tests a no-arg method (get_count) and a method with - both a positional and keyword argument. - """ - - a = self.module.StateAccessType() - b = self.module.StateAccessType() - - methods = { - 'clinic': a.increment_count_clinic, - 'noclinic': a.increment_count_noclinic, - } - - for name, increment_count in methods.items(): - with self.subTest(name): - self.assertEqual(a.get_count(), b.get_count()) - self.assertEqual(a.get_count(), 0) - - increment_count() - self.assertEqual(a.get_count(), b.get_count()) - self.assertEqual(a.get_count(), 1) - - increment_count(3) - self.assertEqual(a.get_count(), b.get_count()) - self.assertEqual(a.get_count(), 4) - - increment_count(-2, twice=True) - self.assertEqual(a.get_count(), b.get_count()) - self.assertEqual(a.get_count(), 0) - - with self.assertRaises(TypeError): - increment_count(thrice=3) - - with self.assertRaises(TypeError): - increment_count(1, 2, 3) - - def test_get_module_bad_def(self): - # _PyType_GetModuleByDef fails gracefully if it doesn't - # find what it's looking for. - # see bpo-46433 - instance = self.module.StateAccessType() - with self.assertRaises(TypeError): - instance.getmodulebydef_bad_def() - - def test_get_module_static_in_mro(self): - # Here, the class _PyType_GetModuleByDef is looking for - # appears in the MRO after a static type (Exception). - # see bpo-46433 - class Subclass(BaseException, self.module.StateAccessType): - pass - self.assertIs(Subclass().get_defining_module(), self.module) - - -if __name__ == "__main__": - unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_clinic.py python3.10-3.10.12/Lib/test/test_clinic.py --- python3.10-3.10.7/Lib/test/test_clinic.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_clinic.py 2023-06-06 22:30:33.000000000 +0000 @@ -3,7 +3,7 @@ # Licensed to the PSF under a contributor agreement. from test import support, test_tools -from test.support import os_helper +from test.support import import_helper, os_helper from unittest import TestCase import collections import inspect @@ -820,5 +820,413 @@ self.assertEqual(new_mtime_ns, old_mtime_ns) +ac_tester = import_helper.import_module('_testclinic') + + +class ClinicFunctionalTest(unittest.TestCase): + locals().update((name, getattr(ac_tester, name)) + for name in dir(ac_tester) if name.startswith('test_')) + + def test_objects_converter(self): + with self.assertRaises(TypeError): + ac_tester.objects_converter() + self.assertEqual(ac_tester.objects_converter(1, 2), (1, 2)) + self.assertEqual(ac_tester.objects_converter([], 'whatever class'), ([], 'whatever class')) + self.assertEqual(ac_tester.objects_converter(1), (1, None)) + + def test_bytes_object_converter(self): + with self.assertRaises(TypeError): + ac_tester.bytes_object_converter(1) + self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject',)) + + def test_byte_array_object_converter(self): + with self.assertRaises(TypeError): + ac_tester.byte_array_object_converter(1) + byte_arr = bytearray(b'ByteArrayObject') + self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr,)) + + def test_unicode_converter(self): + with self.assertRaises(TypeError): + ac_tester.unicode_converter(1) + self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode',)) + + def test_bool_converter(self): + with self.assertRaises(TypeError): + ac_tester.bool_converter(False, False, 'not a int') + self.assertEqual(ac_tester.bool_converter(), (True, True, True)) + self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) + self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False)) + + def test_char_converter(self): + with self.assertRaises(TypeError): + ac_tester.char_converter(1) + with self.assertRaises(TypeError): + ac_tester.char_converter(b'ab') + chars = [b'A', b'\a', b'\b', b'\t', b'\n', b'\v', b'\f', b'\r', b'"', b"'", b'?', b'\\', b'\000', b'\377'] + expected = tuple(ord(c) for c in chars) + self.assertEqual(ac_tester.char_converter(), expected) + chars = [b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'a', b'b', b'c', b'd'] + expected = tuple(ord(c) for c in chars) + self.assertEqual(ac_tester.char_converter(*chars), expected) + + def test_unsigned_char_converter(self): + from _testcapi import UCHAR_MAX + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(UCHAR_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_char_converter(0, UCHAR_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_char_converter([]) + self.assertEqual(ac_tester.unsigned_char_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_char_converter(0, 0, UCHAR_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_char_converter(0, 0, (UCHAR_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_short_converter(self): + from _testcapi import SHRT_MIN, SHRT_MAX + with self.assertRaises(OverflowError): + ac_tester.short_converter(SHRT_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.short_converter(SHRT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.short_converter([]) + self.assertEqual(ac_tester.short_converter(-1234), (-1234,)) + self.assertEqual(ac_tester.short_converter(4321), (4321,)) + + def test_unsigned_short_converter(self): + from _testcapi import USHRT_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_short_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_short_converter(USHRT_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_short_converter(0, USHRT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_short_converter([]) + self.assertEqual(ac_tester.unsigned_short_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_short_converter(0, 0, USHRT_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_short_converter(0, 0, (USHRT_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_int_converter(self): + from _testcapi import INT_MIN, INT_MAX + with self.assertRaises(OverflowError): + ac_tester.int_converter(INT_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.int_converter(INT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.int_converter(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.int_converter([]) + self.assertEqual(ac_tester.int_converter(), (12, 34, 45)) + self.assertEqual(ac_tester.int_converter(1, 2, '3'), (1, 2, ord('3'))) + + def test_unsigned_int_converter(self): + from _testcapi import UINT_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_int_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_int_converter(UINT_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_int_converter(0, UINT_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_int_converter([]) + self.assertEqual(ac_tester.unsigned_int_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_int_converter(0, 0, UINT_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_int_converter(0, 0, (UINT_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_long_converter(self): + from _testcapi import LONG_MIN, LONG_MAX + with self.assertRaises(OverflowError): + ac_tester.long_converter(LONG_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.long_converter(LONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.long_converter([]) + self.assertEqual(ac_tester.long_converter(), (12,)) + self.assertEqual(ac_tester.long_converter(-1234), (-1234,)) + + def test_unsigned_long_converter(self): + from _testcapi import ULONG_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_long_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_converter(ULONG_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_converter(0, ULONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_long_converter([]) + self.assertEqual(ac_tester.unsigned_long_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_long_converter(0, 0, ULONG_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_long_converter(0, 0, (ULONG_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_long_long_converter(self): + from _testcapi import LLONG_MIN, LLONG_MAX + with self.assertRaises(OverflowError): + ac_tester.long_long_converter(LLONG_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.long_long_converter(LLONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.long_long_converter([]) + self.assertEqual(ac_tester.long_long_converter(), (12,)) + self.assertEqual(ac_tester.long_long_converter(-1234), (-1234,)) + + def test_unsigned_long_long_converter(self): + from _testcapi import ULLONG_MAX + with self.assertRaises(ValueError): + ac_tester.unsigned_long_long_converter(-1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_long_converter(ULLONG_MAX + 1) + with self.assertRaises(OverflowError): + ac_tester.unsigned_long_long_converter(0, ULLONG_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.unsigned_long_long_converter([]) + self.assertEqual(ac_tester.unsigned_long_long_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, ULLONG_MAX + 1), (0, 0, 0)) + self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, (ULLONG_MAX + 1) * 3 + 123), (0, 0, 123)) + + def test_py_ssize_t_converter(self): + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(OverflowError): + ac_tester.py_ssize_t_converter(PY_SSIZE_T_MIN - 1) + with self.assertRaises(OverflowError): + ac_tester.py_ssize_t_converter(PY_SSIZE_T_MAX + 1) + with self.assertRaises(TypeError): + ac_tester.py_ssize_t_converter([]) + self.assertEqual(ac_tester.py_ssize_t_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.py_ssize_t_converter(1, 2, None), (1, 2, 56)) + + def test_slice_index_converter(self): + from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(TypeError): + ac_tester.slice_index_converter([]) + self.assertEqual(ac_tester.slice_index_converter(), (12, 34, 56)) + self.assertEqual(ac_tester.slice_index_converter(1, 2, None), (1, 2, 56)) + self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MAX, PY_SSIZE_T_MAX + 1, PY_SSIZE_T_MAX + 1234), + (PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX)) + self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MIN, PY_SSIZE_T_MIN - 1, PY_SSIZE_T_MIN - 1234), + (PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, PY_SSIZE_T_MIN)) + + def test_size_t_converter(self): + with self.assertRaises(ValueError): + ac_tester.size_t_converter(-1) + with self.assertRaises(TypeError): + ac_tester.size_t_converter([]) + self.assertEqual(ac_tester.size_t_converter(), (12,)) + + def test_float_converter(self): + with self.assertRaises(TypeError): + ac_tester.float_converter([]) + self.assertEqual(ac_tester.float_converter(), (12.5,)) + self.assertEqual(ac_tester.float_converter(-0.5), (-0.5,)) + + def test_double_converter(self): + with self.assertRaises(TypeError): + ac_tester.double_converter([]) + self.assertEqual(ac_tester.double_converter(), (12.5,)) + self.assertEqual(ac_tester.double_converter(-0.5), (-0.5,)) + + def test_py_complex_converter(self): + with self.assertRaises(TypeError): + ac_tester.py_complex_converter([]) + self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2),)) + self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'),)) + self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5,)) + self.assertEqual(ac_tester.py_complex_converter(10), (10,)) + + def test_str_converter(self): + with self.assertRaises(TypeError): + ac_tester.str_converter(1) + with self.assertRaises(TypeError): + ac_tester.str_converter('a', 'b', 'c') + with self.assertRaises(ValueError): + ac_tester.str_converter('a', b'b\0b', 'c') + self.assertEqual(ac_tester.str_converter('a', b'b', 'c'), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter('a', b'b', b'c'), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter('a', b'b', 'c\0c'), ('a', 'b', 'c\0c')) + + def test_str_converter_encoding(self): + with self.assertRaises(TypeError): + ac_tester.str_converter_encoding(1) + self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c')) + with self.assertRaises(TypeError): + ac_tester.str_converter_encoding('a', b'b\0b', 'c') + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c')) + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])), + ('a', 'b', 'c\x00c')) + self.assertEqual(ac_tester.str_converter_encoding('a', b'b', b'c\x00c'), ('a', 'b', 'c\x00c')) + + def test_py_buffer_converter(self): + with self.assertRaises(TypeError): + ac_tester.py_buffer_converter('a', 'b') + self.assertEqual(ac_tester.py_buffer_converter('abc', bytearray([1, 2, 3])), (b'abc', b'\x01\x02\x03')) + + def test_keywords(self): + self.assertEqual(ac_tester.keywords(1, 2), (1, 2)) + self.assertEqual(ac_tester.keywords(1, b=2), (1, 2)) + self.assertEqual(ac_tester.keywords(a=1, b=2), (1, 2)) + + def test_keywords_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.keywords_kwonly(1, 2) + self.assertEqual(ac_tester.keywords_kwonly(1, b=2), (1, 2)) + self.assertEqual(ac_tester.keywords_kwonly(a=1, b=2), (1, 2)) + + def test_keywords_opt(self): + self.assertEqual(ac_tester.keywords_opt(1), (1, None, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2, 3), (1, 2, 3)) + self.assertEqual(ac_tester.keywords_opt(1, b=2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_opt(1, 2, c=3), (1, 2, 3)) + self.assertEqual(ac_tester.keywords_opt(a=1, c=3), (1, None, 3)) + self.assertEqual(ac_tester.keywords_opt(a=1, b=2, c=3), (1, 2, 3)) + + def test_keywords_opt_kwonly(self): + self.assertEqual(ac_tester.keywords_opt_kwonly(1), (1, None, None, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.keywords_opt_kwonly(1, 2, 3) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, c=3), (1, None, 3, None)) + self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, b=2, c=3, d=4), (1, 2, 3, 4)) + + def test_keywords_kwonly_opt(self): + self.assertEqual(ac_tester.keywords_kwonly_opt(1), (1, None, None)) + with self.assertRaises(TypeError): + ac_tester.keywords_kwonly_opt(1, 2) + self.assertEqual(ac_tester.keywords_kwonly_opt(1, b=2), (1, 2, None)) + self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, c=3), (1, None, 3)) + self.assertEqual(ac_tester.keywords_kwonly_opt(a=1, b=2, c=3), (1, 2, 3)) + + def test_posonly_keywords(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords(a=1, b=2) + self.assertEqual(ac_tester.posonly_keywords(1, 2), (1, 2)) + self.assertEqual(ac_tester.posonly_keywords(1, b=2), (1, 2)) + + def test_posonly_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(1) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(1, 2) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly(a=1, b=2) + self.assertEqual(ac_tester.posonly_kwonly(1, b=2), (1, 2)) + + def test_posonly_keywords_kwonly(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly(a=1, b=2, c=3) + self.assertEqual(ac_tester.posonly_keywords_kwonly(1, 2, c=3), (1, 2, 3)) + self.assertEqual(ac_tester.posonly_keywords_kwonly(1, b=2, c=3), (1, 2, 3)) + + def test_posonly_keywords_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt(1) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt(1, 2, c=3), (1, 2, 3, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt(a=1, b=2, c=3, d=4) + self.assertEqual(ac_tester.posonly_keywords_opt(1, b=2, c=3, d=4), (1, 2, 3, 4)) + + def test_posonly_opt_keywords_opt(self): + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, 3, 4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt(a=1, b=2, c=3, d=4) + + def test_posonly_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(1) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(1, 2) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2), (1, 2, None, None)) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_kwonly_opt(1, b=2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_kwonly_opt(a=1, b=2, c=3, d=4) + + def test_posonly_opt_kwonly_opt(self): + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_kwonly_opt(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_kwonly_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + + def test_posonly_keywords_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, 2) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, b=2) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(1, 2, 3) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_kwonly_opt(a=1, b=2, c=3) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + + def test_posonly_keywords_opt_kwonly_opt(self): + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(1) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2), (1, 2, None, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, 4) + with self.assertRaises(TypeError): + ac_tester.posonly_keywords_opt_kwonly_opt(a=1, b=2) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4, e=5), (1, 2, 3, 4, 5)) + self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + + def test_posonly_opt_keywords_opt_kwonly_opt(self): + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1), (1, None, None, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, b=2) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4)) + self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + with self.assertRaises(TypeError): + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, 4) + + def test_keyword_only_parameter(self): + with self.assertRaises(TypeError): + ac_tester.keyword_only_parameter() + with self.assertRaises(TypeError): + ac_tester.keyword_only_parameter(1) + self.assertEqual(ac_tester.keyword_only_parameter(a=1), (1,)) + + def test_gh_99240_double_free(self): + expected_error = r'gh_99240_double_free\(\) argument 2 must be encoded string without null bytes, not str' + with self.assertRaisesRegex(TypeError, expected_error): + ac_tester.gh_99240_double_free('a', '\0b') + + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_cmd_line.py python3.10-3.10.12/Lib/test/test_cmd_line.py --- python3.10-3.10.7/Lib/test/test_cmd_line.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_cmd_line.py 2023-06-06 22:30:33.000000000 +0000 @@ -831,6 +831,8 @@ assert_python_failure('-X', 'int_max_str_digits', '-c', code) assert_python_failure('-X', 'int_max_str_digits=foo', '-c', code) assert_python_failure('-X', 'int_max_str_digits=100', '-c', code) + assert_python_failure('-X', 'int_max_str_digits', '-c', code, + PYTHONINTMAXSTRDIGITS='4000') assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='foo') assert_python_failure('-c', code, PYTHONINTMAXSTRDIGITS='100') diff -Nru python3.10-3.10.7/Lib/test/test_cmd_line_script.py python3.10-3.10.12/Lib/test/test_cmd_line_script.py --- python3.10-3.10.7/Lib/test/test_cmd_line_script.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_cmd_line_script.py 2023-06-06 22:30:33.000000000 +0000 @@ -738,6 +738,20 @@ self.assertIn(": can't open file ", err) self.assertNotEqual(proc.returncode, 0) + @unittest.skipUnless(os.path.exists('/dev/fd/0'), 'requires /dev/fd platform') + def test_script_as_dev_fd(self): + # GH-87235: On macOS passing a non-trivial script to /dev/fd/N can cause + # problems because all open /dev/fd/N file descriptors share the same + # offset. + script = 'print("12345678912345678912345")' + with os_helper.temp_dir() as work_dir: + script_name = _make_test_script(work_dir, 'script.py', script) + with open(script_name, "r") as fp: + p = spawn_python(f"/dev/fd/{fp.fileno()}", close_fds=False, pass_fds=(0,1,2,fp.fileno())) + out, err = p.communicate() + self.assertEqual(out, b"12345678912345678912345\n") + + def tearDownModule(): support.reap_children() diff -Nru python3.10-3.10.7/Lib/test/test_codecs.py python3.10-3.10.12/Lib/test/test_codecs.py --- python3.10-3.10.7/Lib/test/test_codecs.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_codecs.py 2023-06-06 22:30:33.000000000 +0000 @@ -705,7 +705,8 @@ "spamspam", self.spambe) def test_bug691291(self): - # Files are always opened in binary mode, even if no binary mode was + # If encoding is not None, then + # files are always opened in binary mode, even if no binary mode was # specified. This means that no automatic conversion of '\n' is done # on reading and writing. s1 = 'Hello\r\nworld\r\n' @@ -1534,6 +1535,12 @@ self.assertEqual("pyth\xf6n.org".encode("idna"), b"xn--pythn-mua.org") self.assertEqual("pyth\xf6n.org.".encode("idna"), b"xn--pythn-mua.org.") + def test_builtin_decode_length_limit(self): + with self.assertRaisesRegex(UnicodeError, "too long"): + (b"xn--016c"+b"a"*1100).decode("idna") + with self.assertRaisesRegex(UnicodeError, "too long"): + (b"xn--016c"+b"a"*70).decode("idna") + def test_stream(self): r = codecs.getreader("idna")(io.BytesIO(b"abc")) r.read(3) diff -Nru python3.10-3.10.7/Lib/test/test_codeop.py python3.10-3.10.12/Lib/test/test_codeop.py --- python3.10-3.10.7/Lib/test/test_codeop.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_codeop.py 2023-06-06 22:30:33.000000000 +0000 @@ -321,6 +321,26 @@ warnings.simplefilter('error', SyntaxWarning) compile_command('1 is 1', symbol='exec') + # Check DeprecationWarning treated as an SyntaxError + with warnings.catch_warnings(), self.assertRaises(SyntaxError): + warnings.simplefilter('error', DeprecationWarning) + compile_command(r"'\e'", symbol='exec') + + def test_incomplete_warning(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.assertIncomplete("'\\e' + (") + self.assertEqual(w, []) + + def test_invalid_warning(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + self.assertInvalid("'\\e' 1") + self.assertEqual(len(w), 1) + self.assertEqual(w[0].category, DeprecationWarning) + self.assertRegex(str(w[0].message), 'invalid escape sequence') + self.assertEqual(w[0].filename, '') + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_collections.py python3.10-3.10.12/Lib/test/test_collections.py --- python3.10-3.10.7/Lib/test/test_collections.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_collections.py 2023-06-06 22:30:33.000000000 +0000 @@ -788,6 +788,8 @@ def __await__(self): yield + self.validate_abstract_methods(Awaitable, '__await__') + non_samples = [None, int(), gen(), object()] for x in non_samples: self.assertNotIsInstance(x, Awaitable) @@ -838,6 +840,8 @@ def __await__(self): yield + self.validate_abstract_methods(Coroutine, '__await__', 'send', 'throw') + non_samples = [None, int(), gen(), object(), Bar()] for x in non_samples: self.assertNotIsInstance(x, Coroutine) @@ -1580,6 +1584,7 @@ containers = [ seq, ItemsView({1: nan, 2: obj}), + KeysView({1: nan, 2: obj}), ValuesView({1: nan, 2: obj}) ] for container in containers: @@ -1843,6 +1848,8 @@ mymap['red'] = 5 self.assertIsInstance(mymap.keys(), Set) self.assertIsInstance(mymap.keys(), KeysView) + self.assertIsInstance(mymap.values(), Collection) + self.assertIsInstance(mymap.values(), ValuesView) self.assertIsInstance(mymap.items(), Set) self.assertIsInstance(mymap.items(), ItemsView) @@ -1918,6 +1925,7 @@ self.assertFalse(issubclass(sample, ByteString)) self.assertNotIsInstance(memoryview(b""), ByteString) self.assertFalse(issubclass(memoryview, ByteString)) + self.validate_abstract_methods(ByteString, '__getitem__', '__len__') def test_MutableSequence(self): for sample in [tuple, str, bytes]: diff -Nru python3.10-3.10.7/Lib/test/test_compileall.py python3.10-3.10.12/Lib/test/test_compileall.py --- python3.10-3.10.7/Lib/test/test_compileall.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_compileall.py 2023-06-06 22:30:33.000000000 +0000 @@ -167,6 +167,20 @@ quiet=2)) self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_file_pathlike_stripdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_file(pathlib.Path(self.source_path), + stripdir=pathlib.Path('stripdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + + def test_compile_file_pathlike_prependdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_file(pathlib.Path(self.source_path), + prependdir=pathlib.Path('prependdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_path(self): with test.test_importlib.util.import_state(path=[self.directory]): self.assertTrue(compileall.compile_path(quiet=2)) @@ -219,6 +233,20 @@ self.assertRegex(line, r'Listing ([^WindowsPath|PosixPath].*)') self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_dir_pathlike_stripdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_dir(pathlib.Path(self.directory), + stripdir=pathlib.Path('stripdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + + def test_compile_dir_pathlike_prependdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_dir(pathlib.Path(self.directory), + prependdir=pathlib.Path('prependdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + @skipUnless(_have_multiprocessing, "requires multiprocessing") @mock.patch('concurrent.futures.ProcessPoolExecutor') def test_compile_pool_called(self, pool_mock): diff -Nru python3.10-3.10.7/Lib/test/test_compile.py python3.10-3.10.12/Lib/test/test_compile.py --- python3.10-3.10.7/Lib/test/test_compile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_compile.py 2023-06-06 22:30:33.000000000 +0000 @@ -984,6 +984,38 @@ elif instr.opname in HANDLED_JUMPS: self.assertNotEqual(instr.arg, (line + 1)*INSTR_SIZE) + def test_compare_positions(self): + for opname, op in [ + ("COMPARE_OP", "<"), + ("COMPARE_OP", "<="), + ("COMPARE_OP", ">"), + ("COMPARE_OP", ">="), + ("CONTAINS_OP", "in"), + ("CONTAINS_OP", "not in"), + ("IS_OP", "is"), + ("IS_OP", "is not"), + ]: + expr = f'a {op} b {op} c' + expected_lines = 2 * [2] + for source in [ + f"\\\n{expr}", f'if \\\n{expr}: x', f"x if \\\n{expr} else y" + ]: + code = compile(source, "", "exec") + all_lines = ( + line + for start, stop, line in code.co_lines() + for _ in range(start, stop, 2) + ) + actual_lines = [ + line + for instruction, line in zip( + dis.get_instructions(code), all_lines, strict=True + ) + if instruction.opname == opname + ] + with self.subTest(source): + self.assertEqual(actual_lines, expected_lines) + class TestExpressionStackSize(unittest.TestCase): # These tests check that the computed stack size for a code object diff -Nru python3.10-3.10.7/Lib/test/test_complex.py python3.10-3.10.12/Lib/test/test_complex.py --- python3.10-3.10.7/Lib/test/test_complex.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_complex.py 2023-06-06 22:30:33.000000000 +0000 @@ -306,15 +306,10 @@ self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j) def test_constructor(self): - class OS: + class NS: def __init__(self, value): self.value = value def __complex__(self): return self.value - class NS(object): - def __init__(self, value): self.value = value - def __complex__(self): return self.value - self.assertEqual(complex(OS(1+10j)), 1+10j) self.assertEqual(complex(NS(1+10j)), 1+10j) - self.assertRaises(TypeError, complex, OS(None)) self.assertRaises(TypeError, complex, NS(None)) self.assertRaises(TypeError, complex, {}) self.assertRaises(TypeError, complex, NS(1.5)) diff -Nru python3.10-3.10.7/Lib/test/test_concurrent_futures.py python3.10-3.10.12/Lib/test/test_concurrent_futures.py --- python3.10-3.10.7/Lib/test/test_concurrent_futures.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_concurrent_futures.py 2023-06-06 22:30:33.000000000 +0000 @@ -14,6 +14,7 @@ from logging.handlers import QueueHandler import os import queue +import signal import sys import threading import time @@ -397,6 +398,33 @@ self.assertFalse(err) self.assertEqual(out.strip(), b"apple") + def test_hang_gh94440(self): + """shutdown(wait=True) doesn't hang when a future was submitted and + quickly canceled right before shutdown. + + See https://github.com/python/cpython/issues/94440. + """ + if not hasattr(signal, 'alarm'): + raise unittest.SkipTest( + "Tested platform does not support the alarm signal") + + def timeout(_signum, _frame): + raise RuntimeError("timed out waiting for shutdown") + + kwargs = {} + if getattr(self, 'ctx', None): + kwargs['mp_context'] = self.get_context() + executor = self.executor_type(max_workers=1, **kwargs) + executor.submit(int).result() + old_handler = signal.signal(signal.SIGALRM, timeout) + try: + signal.alarm(5) + executor.submit(int).cancel() + executor.shutdown(wait=True) + finally: + signal.alarm(0) + signal.signal(signal.SIGALRM, old_handler) + class ThreadPoolShutdownTest(ThreadPoolMixin, ExecutorShutdownTest, BaseTestCase): def test_threads_terminate(self): diff -Nru python3.10-3.10.7/Lib/test/test_contextlib_async.py python3.10-3.10.12/Lib/test/test_contextlib_async.py --- python3.10-3.10.7/Lib/test/test_contextlib_async.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_contextlib_async.py 2023-06-06 22:30:33.000000000 +0000 @@ -4,6 +4,7 @@ AsyncExitStack, nullcontext, aclosing, contextmanager) import functools from test import support +import traceback import unittest from test.test_contextlib import TestBaseExitStack @@ -125,6 +126,63 @@ self.assertEqual(state, [1, 42, 999]) @_async_test + async def test_contextmanager_traceback(self): + @asynccontextmanager + async def f(): + yield + + try: + async with f(): + 1/0 + except ZeroDivisionError as e: + frames = traceback.extract_tb(e.__traceback__) + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, '1/0') + + # Repeat with RuntimeError (which goes through a different code path) + class RuntimeErrorSubclass(RuntimeError): + pass + + try: + async with f(): + raise RuntimeErrorSubclass(42) + except RuntimeErrorSubclass as e: + frames = traceback.extract_tb(e.__traceback__) + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, 'raise RuntimeErrorSubclass(42)') + + class StopIterationSubclass(StopIteration): + pass + + class StopAsyncIterationSubclass(StopAsyncIteration): + pass + + for stop_exc in ( + StopIteration('spam'), + StopAsyncIteration('ham'), + StopIterationSubclass('spam'), + StopAsyncIterationSubclass('spam') + ): + with self.subTest(type=type(stop_exc)): + try: + async with f(): + raise stop_exc + except type(stop_exc) as e: + self.assertIs(e, stop_exc) + frames = traceback.extract_tb(e.__traceback__) + else: + self.fail(f'{stop_exc} was suppressed') + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, 'raise stop_exc') + + + @_async_test async def test_contextmanager_no_reraise(self): @asynccontextmanager async def whee(): diff -Nru python3.10-3.10.7/Lib/test/test_contextlib.py python3.10-3.10.12/Lib/test/test_contextlib.py --- python3.10-3.10.7/Lib/test/test_contextlib.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_contextlib.py 2023-06-06 22:30:33.000000000 +0000 @@ -87,6 +87,56 @@ raise ZeroDivisionError() self.assertEqual(state, [1, 42, 999]) + def test_contextmanager_traceback(self): + @contextmanager + def f(): + yield + + try: + with f(): + 1/0 + except ZeroDivisionError as e: + frames = traceback.extract_tb(e.__traceback__) + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, '1/0') + + # Repeat with RuntimeError (which goes through a different code path) + class RuntimeErrorSubclass(RuntimeError): + pass + + try: + with f(): + raise RuntimeErrorSubclass(42) + except RuntimeErrorSubclass as e: + frames = traceback.extract_tb(e.__traceback__) + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, 'raise RuntimeErrorSubclass(42)') + + class StopIterationSubclass(StopIteration): + pass + + for stop_exc in ( + StopIteration('spam'), + StopIterationSubclass('spam'), + ): + with self.subTest(type=type(stop_exc)): + try: + with f(): + raise stop_exc + except type(stop_exc) as e: + self.assertIs(e, stop_exc) + frames = traceback.extract_tb(e.__traceback__) + else: + self.fail(f'{stop_exc} was suppressed') + + self.assertEqual(len(frames), 1) + self.assertEqual(frames[0].name, 'test_contextmanager_traceback') + self.assertEqual(frames[0].line, 'raise stop_exc') + def test_contextmanager_no_reraise(self): @contextmanager def whee(): diff -Nru python3.10-3.10.7/Lib/test/test_copy.py python3.10-3.10.12/Lib/test/test_copy.py --- python3.10-3.10.7/Lib/test/test_copy.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_copy.py 2023-06-06 22:30:33.000000000 +0000 @@ -51,6 +51,9 @@ self.assertRaises(TypeError, copy.copy, x) copyreg.pickle(C, pickle_C, C) y = copy.copy(x) + self.assertIsNot(x, y) + self.assertEqual(type(y), C) + self.assertEqual(y.foo, x.foo) def test_copy_reduce_ex(self): class C(object): @@ -313,6 +316,9 @@ self.assertRaises(TypeError, copy.deepcopy, x) copyreg.pickle(C, pickle_C, C) y = copy.deepcopy(x) + self.assertIsNot(x, y) + self.assertEqual(type(y), C) + self.assertEqual(y.foo, x.foo) def test_deepcopy_reduce_ex(self): class C(object): @@ -356,8 +362,8 @@ pass def f(): pass - tests = [None, 42, 2**100, 3.14, True, False, 1j, - "hello", "hello\u1234", f.__code__, + tests = [None, ..., NotImplemented, 42, 2**100, 3.14, True, False, 1j, + b"bytes", "hello", "hello\u1234", f.__code__, NewStyle, range(10), Classic, max, property()] for x in tests: self.assertIs(copy.deepcopy(x), x) diff -Nru python3.10-3.10.7/Lib/test/test_coroutines.py python3.10-3.10.12/Lib/test/test_coroutines.py --- python3.10-3.10.7/Lib/test/test_coroutines.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_coroutines.py 2023-06-06 22:30:33.000000000 +0000 @@ -1262,7 +1262,7 @@ async def func(): async with CM(): - assert (1, ) == 1 + self.assertEqual((1, ), 1) with self.assertRaises(AssertionError): run_async(func()) @@ -2319,7 +2319,8 @@ def test_unawaited_warning_during_shutdown(self): code = ("import asyncio\n" "async def f(): pass\n" - "asyncio.gather(f())\n") + "async def t(): asyncio.gather(f())\n" + "asyncio.run(t())\n") assert_python_ok("-c", code) code = ("import sys\n" diff -Nru python3.10-3.10.7/Lib/test/test_csv.py python3.10-3.10.12/Lib/test/test_csv.py --- python3.10-3.10.7/Lib/test/test_csv.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_csv.py 2023-06-06 22:30:33.000000000 +0000 @@ -335,6 +335,11 @@ ['abc,3'], [[]], quoting=csv.QUOTE_NONNUMERIC) + def test_read_skipinitialspace(self): + self._read_test(['no space, space, spaces,\ttab'], + [['no space', 'space', 'spaces', '\ttab']], + skipinitialspace=True) + def test_read_bigfield(self): # This exercises the buffer realloc functionality and field size # limits. diff -Nru python3.10-3.10.7/Lib/test/test_dataclasses.py python3.10-3.10.12/Lib/test/test_dataclasses.py --- python3.10-3.10.7/Lib/test/test_dataclasses.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_dataclasses.py 2023-06-06 22:30:33.000000000 +0000 @@ -5,10 +5,12 @@ from dataclasses import * import abc +import io import pickle import inspect import builtins import types +import traceback import unittest from unittest.mock import Mock from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol @@ -67,6 +69,24 @@ self.assertEqual(repr_output, expected_output) + def test_field_recursive_repr(self): + rec_field = field() + rec_field.type = rec_field + rec_field.name = "id" + repr_output = repr(rec_field) + + self.assertIn(",type=...,", repr_output) + + def test_recursive_annotation(self): + class C: + pass + + @dataclass + class D: + C: C = field() + + self.assertIn(",type=...,", repr(D.__dataclass_fields__["C"])) + def test_named_init_params(self): @dataclass class C: @@ -230,6 +250,14 @@ c = C('foo') self.assertEqual(c.object, 'foo') + def test_field_named_BUILTINS_frozen(self): + # gh-96151 + @dataclass(frozen=True) + class C: + BUILTINS: int + c = C(5) + self.assertEqual(c.BUILTINS, 5) + def test_field_named_like_builtin(self): # Attribute names can shadow built-in names # since code generation is used. @@ -1388,6 +1416,16 @@ with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): fields(C()) + def test_clean_traceback_from_fields_exception(self): + stdout = io.StringIO() + try: + fields(object) + except TypeError as exc: + traceback.print_exception(exc, file=stdout) + printed_traceback = stdout.getvalue() + self.assertNotIn("AttributeError", printed_traceback) + self.assertNotIn("__dataclass_fields__", printed_traceback) + def test_helper_asdict(self): # Basic tests for asdict(), it should return a new dictionary. @dataclass diff -Nru python3.10-3.10.7/Lib/test/test_dictviews.py python3.10-3.10.12/Lib/test/test_dictviews.py --- python3.10-3.10.7/Lib/test/test_dictviews.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_dictviews.py 2023-06-06 22:30:33.000000000 +0000 @@ -320,6 +320,9 @@ self.assertIsInstance(d.values(), collections.abc.ValuesView) self.assertIsInstance(d.values(), collections.abc.MappingView) self.assertIsInstance(d.values(), collections.abc.Sized) + self.assertIsInstance(d.values(), collections.abc.Collection) + self.assertIsInstance(d.values(), collections.abc.Iterable) + self.assertIsInstance(d.values(), collections.abc.Container) self.assertIsInstance(d.items(), collections.abc.ItemsView) self.assertIsInstance(d.items(), collections.abc.MappingView) diff -Nru python3.10-3.10.7/Lib/test/test_dis.py python3.10-3.10.12/Lib/test/test_dis.py --- python3.10-3.10.7/Lib/test/test_dis.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_dis.py 2023-06-06 22:30:33.000000000 +0000 @@ -707,7 +707,7 @@ return output.getvalue() -if sys.flags.optimize: +if dis.code_info.__doc__ is None: code_info_consts = "0: None" else: code_info_consts = "0: 'Formatted details of methods, functions, or code.'" diff -Nru python3.10-3.10.7/Lib/test/test_exceptions.py python3.10-3.10.12/Lib/test/test_exceptions.py --- python3.10-3.10.7/Lib/test/test_exceptions.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_exceptions.py 2023-06-06 22:30:33.000000000 +0000 @@ -1981,6 +1981,11 @@ except AttributeError as exc: self.assertEqual("bluch", exc.name) self.assertEqual(obj, exc.obj) + try: + object.__getattribute__(obj, "bluch") + except AttributeError as exc: + self.assertEqual("bluch", exc.name) + self.assertEqual(obj, exc.obj) def test_getattr_has_name_and_obj_for_method(self): class A: diff -Nru python3.10-3.10.7/Lib/test/test_fcntl.py python3.10-3.10.12/Lib/test/test_fcntl.py --- python3.10-3.10.7/Lib/test/test_fcntl.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_fcntl.py 2023-06-06 22:30:33.000000000 +0000 @@ -200,7 +200,7 @@ pipesize_default = fcntl.fcntl(test_pipe_w, fcntl.F_GETPIPE_SZ) pipesize = pipesize_default // 2 # A new value to detect change. if pipesize < 512: # the POSIX minimum - raise unittest.SkitTest( + raise unittest.SkipTest( 'default pipesize too small to perform test.') fcntl.fcntl(test_pipe_w, fcntl.F_SETPIPE_SZ, pipesize) self.assertEqual(fcntl.fcntl(test_pipe_w, fcntl.F_GETPIPE_SZ), diff -Nru python3.10-3.10.7/Lib/test/test_fileinput.py python3.10-3.10.12/Lib/test/test_fileinput.py --- python3.10-3.10.7/Lib/test/test_fileinput.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_fileinput.py 2023-06-06 22:30:33.000000000 +0000 @@ -903,29 +903,29 @@ self.fake_open = InvocationRecorder() def test_empty_string(self): - self.do_test_use_builtin_open("", 1) + self.do_test_use_builtin_open_text("", "r") def test_no_ext(self): - self.do_test_use_builtin_open("abcd", 2) + self.do_test_use_builtin_open_text("abcd", "r") @unittest.skipUnless(gzip, "Requires gzip and zlib") def test_gz_ext_fake(self): original_open = gzip.open gzip.open = self.fake_open try: - result = fileinput.hook_compressed("test.gz", "3") + result = fileinput.hook_compressed("test.gz", "r") finally: gzip.open = original_open self.assertEqual(self.fake_open.invocation_count, 1) - self.assertEqual(self.fake_open.last_invocation, (("test.gz", "3"), {})) + self.assertEqual(self.fake_open.last_invocation, (("test.gz", "r"), {})) @unittest.skipUnless(gzip, "Requires gzip and zlib") def test_gz_with_encoding_fake(self): original_open = gzip.open gzip.open = lambda filename, mode: io.BytesIO(b'Ex-binary string') try: - result = fileinput.hook_compressed("test.gz", "3", encoding="utf-8") + result = fileinput.hook_compressed("test.gz", "r", encoding="utf-8") finally: gzip.open = original_open self.assertEqual(list(result), ['Ex-binary string']) @@ -935,23 +935,40 @@ original_open = bz2.BZ2File bz2.BZ2File = self.fake_open try: - result = fileinput.hook_compressed("test.bz2", "4") + result = fileinput.hook_compressed("test.bz2", "r") finally: bz2.BZ2File = original_open self.assertEqual(self.fake_open.invocation_count, 1) - self.assertEqual(self.fake_open.last_invocation, (("test.bz2", "4"), {})) + self.assertEqual(self.fake_open.last_invocation, (("test.bz2", "r"), {})) def test_blah_ext(self): - self.do_test_use_builtin_open("abcd.blah", "5") + self.do_test_use_builtin_open_binary("abcd.blah", "rb") def test_gz_ext_builtin(self): - self.do_test_use_builtin_open("abcd.Gz", "6") + self.do_test_use_builtin_open_binary("abcd.Gz", "rb") def test_bz2_ext_builtin(self): - self.do_test_use_builtin_open("abcd.Bz2", "7") + self.do_test_use_builtin_open_binary("abcd.Bz2", "rb") - def do_test_use_builtin_open(self, filename, mode): + def test_binary_mode_encoding(self): + self.do_test_use_builtin_open_binary("abcd", "rb") + + def test_text_mode_encoding(self): + self.do_test_use_builtin_open_text("abcd", "r") + + def do_test_use_builtin_open_binary(self, filename, mode): + original_open = self.replace_builtin_open(self.fake_open) + try: + result = fileinput.hook_compressed(filename, mode) + finally: + self.replace_builtin_open(original_open) + + self.assertEqual(self.fake_open.invocation_count, 1) + self.assertEqual(self.fake_open.last_invocation, + ((filename, mode), {'encoding': None, 'errors': None})) + + def do_test_use_builtin_open_text(self, filename, mode): original_open = self.replace_builtin_open(self.fake_open) try: result = fileinput.hook_compressed(filename, mode) diff -Nru python3.10-3.10.7/Lib/test/test_getargs2.py python3.10-3.10.12/Lib/test/test_getargs2.py --- python3.10-3.10.7/Lib/test/test_getargs2.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_getargs2.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,1318 +0,0 @@ -import unittest -import math -import string -import sys -import warnings -from test import support -from test.support import import_helper -from test.support import warnings_helper -# Skip this test if the _testcapi module isn't available. -_testcapi = import_helper.import_module('_testcapi') -from _testcapi import getargs_keywords, getargs_keyword_only - -# > How about the following counterproposal. This also changes some of -# > the other format codes to be a little more regular. -# > -# > Code C type Range check -# > -# > b unsigned char 0..UCHAR_MAX -# > h signed short SHRT_MIN..SHRT_MAX -# > B unsigned char none ** -# > H unsigned short none ** -# > k * unsigned long none -# > I * unsigned int 0..UINT_MAX -# -# -# > i int INT_MIN..INT_MAX -# > l long LONG_MIN..LONG_MAX -# -# > K * unsigned long long none -# > L long long LLONG_MIN..LLONG_MAX -# -# > Notes: -# > -# > * New format codes. -# > -# > ** Changed from previous "range-and-a-half" to "none"; the -# > range-and-a-half checking wasn't particularly useful. -# -# Plus a C API or two, e.g. PyLong_AsUnsignedLongMask() -> -# unsigned long and PyLong_AsUnsignedLongLongMask() -> unsigned -# long long (if that exists). - -LARGE = 0x7FFFFFFF -VERY_LARGE = 0xFF0000121212121212121242 - -from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \ - INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \ - SHRT_MIN, SHRT_MAX, FLT_MIN, FLT_MAX, DBL_MIN, DBL_MAX - -DBL_MAX_EXP = sys.float_info.max_exp -INF = float('inf') -NAN = float('nan') - -# fake, they are not defined in Python's header files -LLONG_MAX = 2**63-1 -LLONG_MIN = -2**63 -ULLONG_MAX = 2**64-1 - -class Index: - def __index__(self): - return 99 - -class IndexIntSubclass(int): - def __index__(self): - return 99 - -class BadIndex: - def __index__(self): - return 1.0 - -class BadIndex2: - def __index__(self): - return True - -class BadIndex3(int): - def __index__(self): - return True - - -class Int: - def __int__(self): - return 99 - -class IntSubclass(int): - def __int__(self): - return 99 - -class BadInt: - def __int__(self): - return 1.0 - -class BadInt2: - def __int__(self): - return True - -class BadInt3(int): - def __int__(self): - return True - - -class Float: - def __float__(self): - return 4.25 - -class FloatSubclass(float): - pass - -class FloatSubclass2(float): - def __float__(self): - return 4.25 - -class BadFloat: - def __float__(self): - return 687 - -class BadFloat2: - def __float__(self): - return FloatSubclass(4.25) - -class BadFloat3(float): - def __float__(self): - return FloatSubclass(4.25) - - -class Complex: - def __complex__(self): - return 4.25+0.5j - -class ComplexSubclass(complex): - pass - -class ComplexSubclass2(complex): - def __complex__(self): - return 4.25+0.5j - -class BadComplex: - def __complex__(self): - return 1.25 - -class BadComplex2: - def __complex__(self): - return ComplexSubclass(4.25+0.5j) - -class BadComplex3(complex): - def __complex__(self): - return ComplexSubclass(4.25+0.5j) - - -class TupleSubclass(tuple): - pass - -class DictSubclass(dict): - pass - - -class Unsigned_TestCase(unittest.TestCase): - def test_b(self): - from _testcapi import getargs_b - # b returns 'unsigned char', and does range checking (0 ... UCHAR_MAX) - self.assertRaises(TypeError, getargs_b, 3.14) - self.assertEqual(99, getargs_b(Index())) - self.assertEqual(0, getargs_b(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_b, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_b(BadIndex2())) - self.assertEqual(0, getargs_b(BadIndex3())) - self.assertRaises(TypeError, getargs_b, Int()) - self.assertEqual(0, getargs_b(IntSubclass())) - self.assertRaises(TypeError, getargs_b, BadInt()) - self.assertRaises(TypeError, getargs_b, BadInt2()) - self.assertEqual(0, getargs_b(BadInt3())) - - self.assertRaises(OverflowError, getargs_b, -1) - self.assertEqual(0, getargs_b(0)) - self.assertEqual(UCHAR_MAX, getargs_b(UCHAR_MAX)) - self.assertRaises(OverflowError, getargs_b, UCHAR_MAX + 1) - - self.assertEqual(42, getargs_b(42)) - self.assertRaises(OverflowError, getargs_b, VERY_LARGE) - - def test_B(self): - from _testcapi import getargs_B - # B returns 'unsigned char', no range checking - self.assertRaises(TypeError, getargs_B, 3.14) - self.assertEqual(99, getargs_B(Index())) - self.assertEqual(0, getargs_B(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_B, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_B(BadIndex2())) - self.assertEqual(0, getargs_B(BadIndex3())) - self.assertRaises(TypeError, getargs_B, Int()) - self.assertEqual(0, getargs_B(IntSubclass())) - self.assertRaises(TypeError, getargs_B, BadInt()) - self.assertRaises(TypeError, getargs_B, BadInt2()) - self.assertEqual(0, getargs_B(BadInt3())) - - self.assertEqual(UCHAR_MAX, getargs_B(-1)) - self.assertEqual(0, getargs_B(0)) - self.assertEqual(UCHAR_MAX, getargs_B(UCHAR_MAX)) - self.assertEqual(0, getargs_B(UCHAR_MAX+1)) - - self.assertEqual(42, getargs_B(42)) - self.assertEqual(UCHAR_MAX & VERY_LARGE, getargs_B(VERY_LARGE)) - - def test_H(self): - from _testcapi import getargs_H - # H returns 'unsigned short', no range checking - self.assertRaises(TypeError, getargs_H, 3.14) - self.assertEqual(99, getargs_H(Index())) - self.assertEqual(0, getargs_H(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_H, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_H(BadIndex2())) - self.assertEqual(0, getargs_H(BadIndex3())) - self.assertRaises(TypeError, getargs_H, Int()) - self.assertEqual(0, getargs_H(IntSubclass())) - self.assertRaises(TypeError, getargs_H, BadInt()) - self.assertRaises(TypeError, getargs_H, BadInt2()) - self.assertEqual(0, getargs_H(BadInt3())) - - self.assertEqual(USHRT_MAX, getargs_H(-1)) - self.assertEqual(0, getargs_H(0)) - self.assertEqual(USHRT_MAX, getargs_H(USHRT_MAX)) - self.assertEqual(0, getargs_H(USHRT_MAX+1)) - - self.assertEqual(42, getargs_H(42)) - - self.assertEqual(VERY_LARGE & USHRT_MAX, getargs_H(VERY_LARGE)) - - def test_I(self): - from _testcapi import getargs_I - # I returns 'unsigned int', no range checking - self.assertRaises(TypeError, getargs_I, 3.14) - self.assertEqual(99, getargs_I(Index())) - self.assertEqual(0, getargs_I(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_I, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_I(BadIndex2())) - self.assertEqual(0, getargs_I(BadIndex3())) - self.assertRaises(TypeError, getargs_I, Int()) - self.assertEqual(0, getargs_I(IntSubclass())) - self.assertRaises(TypeError, getargs_I, BadInt()) - self.assertRaises(TypeError, getargs_I, BadInt2()) - self.assertEqual(0, getargs_I(BadInt3())) - - self.assertEqual(UINT_MAX, getargs_I(-1)) - self.assertEqual(0, getargs_I(0)) - self.assertEqual(UINT_MAX, getargs_I(UINT_MAX)) - self.assertEqual(0, getargs_I(UINT_MAX+1)) - - self.assertEqual(42, getargs_I(42)) - - self.assertEqual(VERY_LARGE & UINT_MAX, getargs_I(VERY_LARGE)) - - def test_k(self): - from _testcapi import getargs_k - # k returns 'unsigned long', no range checking - # it does not accept float, or instances with __int__ - self.assertRaises(TypeError, getargs_k, 3.14) - self.assertRaises(TypeError, getargs_k, Index()) - self.assertEqual(0, getargs_k(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_k, BadIndex()) - self.assertRaises(TypeError, getargs_k, BadIndex2()) - self.assertEqual(0, getargs_k(BadIndex3())) - self.assertRaises(TypeError, getargs_k, Int()) - self.assertEqual(0, getargs_k(IntSubclass())) - self.assertRaises(TypeError, getargs_k, BadInt()) - self.assertRaises(TypeError, getargs_k, BadInt2()) - self.assertEqual(0, getargs_k(BadInt3())) - - self.assertEqual(ULONG_MAX, getargs_k(-1)) - self.assertEqual(0, getargs_k(0)) - self.assertEqual(ULONG_MAX, getargs_k(ULONG_MAX)) - self.assertEqual(0, getargs_k(ULONG_MAX+1)) - - self.assertEqual(42, getargs_k(42)) - - self.assertEqual(VERY_LARGE & ULONG_MAX, getargs_k(VERY_LARGE)) - -class Signed_TestCase(unittest.TestCase): - def test_h(self): - from _testcapi import getargs_h - # h returns 'short', and does range checking (SHRT_MIN ... SHRT_MAX) - self.assertRaises(TypeError, getargs_h, 3.14) - self.assertEqual(99, getargs_h(Index())) - self.assertEqual(0, getargs_h(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_h, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_h(BadIndex2())) - self.assertEqual(0, getargs_h(BadIndex3())) - self.assertRaises(TypeError, getargs_h, Int()) - self.assertEqual(0, getargs_h(IntSubclass())) - self.assertRaises(TypeError, getargs_h, BadInt()) - self.assertRaises(TypeError, getargs_h, BadInt2()) - self.assertEqual(0, getargs_h(BadInt3())) - - self.assertRaises(OverflowError, getargs_h, SHRT_MIN-1) - self.assertEqual(SHRT_MIN, getargs_h(SHRT_MIN)) - self.assertEqual(SHRT_MAX, getargs_h(SHRT_MAX)) - self.assertRaises(OverflowError, getargs_h, SHRT_MAX+1) - - self.assertEqual(42, getargs_h(42)) - self.assertRaises(OverflowError, getargs_h, VERY_LARGE) - - def test_i(self): - from _testcapi import getargs_i - # i returns 'int', and does range checking (INT_MIN ... INT_MAX) - self.assertRaises(TypeError, getargs_i, 3.14) - self.assertEqual(99, getargs_i(Index())) - self.assertEqual(0, getargs_i(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_i, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_i(BadIndex2())) - self.assertEqual(0, getargs_i(BadIndex3())) - self.assertRaises(TypeError, getargs_i, Int()) - self.assertEqual(0, getargs_i(IntSubclass())) - self.assertRaises(TypeError, getargs_i, BadInt()) - self.assertRaises(TypeError, getargs_i, BadInt2()) - self.assertEqual(0, getargs_i(BadInt3())) - - self.assertRaises(OverflowError, getargs_i, INT_MIN-1) - self.assertEqual(INT_MIN, getargs_i(INT_MIN)) - self.assertEqual(INT_MAX, getargs_i(INT_MAX)) - self.assertRaises(OverflowError, getargs_i, INT_MAX+1) - - self.assertEqual(42, getargs_i(42)) - self.assertRaises(OverflowError, getargs_i, VERY_LARGE) - - def test_l(self): - from _testcapi import getargs_l - # l returns 'long', and does range checking (LONG_MIN ... LONG_MAX) - self.assertRaises(TypeError, getargs_l, 3.14) - self.assertEqual(99, getargs_l(Index())) - self.assertEqual(0, getargs_l(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_l, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_l(BadIndex2())) - self.assertEqual(0, getargs_l(BadIndex3())) - self.assertRaises(TypeError, getargs_l, Int()) - self.assertEqual(0, getargs_l(IntSubclass())) - self.assertRaises(TypeError, getargs_l, BadInt()) - self.assertRaises(TypeError, getargs_l, BadInt2()) - self.assertEqual(0, getargs_l(BadInt3())) - - self.assertRaises(OverflowError, getargs_l, LONG_MIN-1) - self.assertEqual(LONG_MIN, getargs_l(LONG_MIN)) - self.assertEqual(LONG_MAX, getargs_l(LONG_MAX)) - self.assertRaises(OverflowError, getargs_l, LONG_MAX+1) - - self.assertEqual(42, getargs_l(42)) - self.assertRaises(OverflowError, getargs_l, VERY_LARGE) - - def test_n(self): - from _testcapi import getargs_n - # n returns 'Py_ssize_t', and does range checking - # (PY_SSIZE_T_MIN ... PY_SSIZE_T_MAX) - self.assertRaises(TypeError, getargs_n, 3.14) - self.assertEqual(99, getargs_n(Index())) - self.assertEqual(0, getargs_n(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_n, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_n(BadIndex2())) - self.assertEqual(0, getargs_n(BadIndex3())) - self.assertRaises(TypeError, getargs_n, Int()) - self.assertEqual(0, getargs_n(IntSubclass())) - self.assertRaises(TypeError, getargs_n, BadInt()) - self.assertRaises(TypeError, getargs_n, BadInt2()) - self.assertEqual(0, getargs_n(BadInt3())) - - self.assertRaises(OverflowError, getargs_n, PY_SSIZE_T_MIN-1) - self.assertEqual(PY_SSIZE_T_MIN, getargs_n(PY_SSIZE_T_MIN)) - self.assertEqual(PY_SSIZE_T_MAX, getargs_n(PY_SSIZE_T_MAX)) - self.assertRaises(OverflowError, getargs_n, PY_SSIZE_T_MAX+1) - - self.assertEqual(42, getargs_n(42)) - self.assertRaises(OverflowError, getargs_n, VERY_LARGE) - - -class LongLong_TestCase(unittest.TestCase): - def test_L(self): - from _testcapi import getargs_L - # L returns 'long long', and does range checking (LLONG_MIN - # ... LLONG_MAX) - self.assertRaises(TypeError, getargs_L, 3.14) - self.assertRaises(TypeError, getargs_L, "Hello") - self.assertEqual(99, getargs_L(Index())) - self.assertEqual(0, getargs_L(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_L, BadIndex()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(1, getargs_L(BadIndex2())) - self.assertEqual(0, getargs_L(BadIndex3())) - self.assertRaises(TypeError, getargs_L, Int()) - self.assertEqual(0, getargs_L(IntSubclass())) - self.assertRaises(TypeError, getargs_L, BadInt()) - self.assertRaises(TypeError, getargs_L, BadInt2()) - self.assertEqual(0, getargs_L(BadInt3())) - - self.assertRaises(OverflowError, getargs_L, LLONG_MIN-1) - self.assertEqual(LLONG_MIN, getargs_L(LLONG_MIN)) - self.assertEqual(LLONG_MAX, getargs_L(LLONG_MAX)) - self.assertRaises(OverflowError, getargs_L, LLONG_MAX+1) - - self.assertEqual(42, getargs_L(42)) - self.assertRaises(OverflowError, getargs_L, VERY_LARGE) - - def test_K(self): - from _testcapi import getargs_K - # K return 'unsigned long long', no range checking - self.assertRaises(TypeError, getargs_K, 3.14) - self.assertRaises(TypeError, getargs_K, Index()) - self.assertEqual(0, getargs_K(IndexIntSubclass())) - self.assertRaises(TypeError, getargs_K, BadIndex()) - self.assertRaises(TypeError, getargs_K, BadIndex2()) - self.assertEqual(0, getargs_K(BadIndex3())) - self.assertRaises(TypeError, getargs_K, Int()) - self.assertEqual(0, getargs_K(IntSubclass())) - self.assertRaises(TypeError, getargs_K, BadInt()) - self.assertRaises(TypeError, getargs_K, BadInt2()) - self.assertEqual(0, getargs_K(BadInt3())) - - self.assertEqual(ULLONG_MAX, getargs_K(ULLONG_MAX)) - self.assertEqual(0, getargs_K(0)) - self.assertEqual(0, getargs_K(ULLONG_MAX+1)) - - self.assertEqual(42, getargs_K(42)) - - self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE)) - - -class Float_TestCase(unittest.TestCase): - def assertEqualWithSign(self, actual, expected): - self.assertEqual(actual, expected) - self.assertEqual(math.copysign(1, actual), math.copysign(1, expected)) - - def test_f(self): - from _testcapi import getargs_f - self.assertEqual(getargs_f(4.25), 4.25) - self.assertEqual(getargs_f(4), 4.0) - self.assertRaises(TypeError, getargs_f, 4.25+0j) - self.assertEqual(getargs_f(Float()), 4.25) - self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5) - self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5) - self.assertRaises(TypeError, getargs_f, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_f(BadFloat2()), 4.25) - self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5) - self.assertEqual(getargs_f(Index()), 99.0) - self.assertRaises(TypeError, getargs_f, Int()) - - for x in (FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX, INF, -INF): - self.assertEqual(getargs_f(x), x) - if FLT_MAX < DBL_MAX: - self.assertEqual(getargs_f(DBL_MAX), INF) - self.assertEqual(getargs_f(-DBL_MAX), -INF) - if FLT_MIN > DBL_MIN: - self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0) - self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0) - self.assertEqualWithSign(getargs_f(0.0), 0.0) - self.assertEqualWithSign(getargs_f(-0.0), -0.0) - r = getargs_f(NAN) - self.assertNotEqual(r, r) - - @support.requires_IEEE_754 - def test_f_rounding(self): - from _testcapi import getargs_f - self.assertEqual(getargs_f(3.40282356e38), FLT_MAX) - self.assertEqual(getargs_f(-3.40282356e38), -FLT_MAX) - - def test_d(self): - from _testcapi import getargs_d - self.assertEqual(getargs_d(4.25), 4.25) - self.assertEqual(getargs_d(4), 4.0) - self.assertRaises(TypeError, getargs_d, 4.25+0j) - self.assertEqual(getargs_d(Float()), 4.25) - self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5) - self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5) - self.assertRaises(TypeError, getargs_d, BadFloat()) - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_d(BadFloat2()), 4.25) - self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5) - self.assertEqual(getargs_d(Index()), 99.0) - self.assertRaises(TypeError, getargs_d, Int()) - - for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF): - self.assertEqual(getargs_d(x), x) - self.assertRaises(OverflowError, getargs_d, 1< 1 - self.assertEqual(getargs_c(b'a'), 97) - self.assertEqual(getargs_c(bytearray(b'a')), 97) - self.assertRaises(TypeError, getargs_c, memoryview(b'a')) - self.assertRaises(TypeError, getargs_c, 's') - self.assertRaises(TypeError, getargs_c, 97) - self.assertRaises(TypeError, getargs_c, None) - - def test_y(self): - from _testcapi import getargs_y - self.assertRaises(TypeError, getargs_y, 'abc\xe9') - self.assertEqual(getargs_y(b'bytes'), b'bytes') - self.assertRaises(ValueError, getargs_y, b'nul:\0') - self.assertRaises(TypeError, getargs_y, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_y, memoryview(b'memoryview')) - self.assertRaises(TypeError, getargs_y, None) - - def test_y_star(self): - from _testcapi import getargs_y_star - self.assertRaises(TypeError, getargs_y_star, 'abc\xe9') - self.assertEqual(getargs_y_star(b'bytes'), b'bytes') - self.assertEqual(getargs_y_star(b'nul:\0'), b'nul:\0') - self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray') - self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview') - self.assertRaises(TypeError, getargs_y_star, None) - - def test_y_hash(self): - from _testcapi import getargs_y_hash - self.assertRaises(TypeError, getargs_y_hash, 'abc\xe9') - self.assertEqual(getargs_y_hash(b'bytes'), b'bytes') - self.assertEqual(getargs_y_hash(b'nul:\0'), b'nul:\0') - self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview')) - self.assertRaises(TypeError, getargs_y_hash, None) - - def test_w_star(self): - # getargs_w_star() modifies first and last byte - from _testcapi import getargs_w_star - self.assertRaises(TypeError, getargs_w_star, 'abc\xe9') - self.assertRaises(TypeError, getargs_w_star, b'bytes') - self.assertRaises(TypeError, getargs_w_star, b'nul:\0') - self.assertRaises(TypeError, getargs_w_star, memoryview(b'bytes')) - buf = bytearray(b'bytearray') - self.assertEqual(getargs_w_star(buf), b'[ytearra]') - self.assertEqual(buf, bytearray(b'[ytearra]')) - buf = bytearray(b'memoryview') - self.assertEqual(getargs_w_star(memoryview(buf)), b'[emoryvie]') - self.assertEqual(buf, bytearray(b'[emoryvie]')) - self.assertRaises(TypeError, getargs_w_star, None) - - -class String_TestCase(unittest.TestCase): - def test_C(self): - from _testcapi import getargs_C - self.assertRaises(TypeError, getargs_C, 'abc') # len > 1 - self.assertEqual(getargs_C('a'), 97) - self.assertEqual(getargs_C('\u20ac'), 0x20ac) - self.assertEqual(getargs_C('\U0001f40d'), 0x1f40d) - self.assertRaises(TypeError, getargs_C, b'a') - self.assertRaises(TypeError, getargs_C, bytearray(b'a')) - self.assertRaises(TypeError, getargs_C, memoryview(b'a')) - self.assertRaises(TypeError, getargs_C, 97) - self.assertRaises(TypeError, getargs_C, None) - - def test_s(self): - from _testcapi import getargs_s - self.assertEqual(getargs_s('abc\xe9'), b'abc\xc3\xa9') - self.assertRaises(ValueError, getargs_s, 'nul:\0') - self.assertRaises(TypeError, getargs_s, b'bytes') - self.assertRaises(TypeError, getargs_s, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_s, memoryview(b'memoryview')) - self.assertRaises(TypeError, getargs_s, None) - - def test_s_star(self): - from _testcapi import getargs_s_star - self.assertEqual(getargs_s_star('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_s_star('nul:\0'), b'nul:\0') - self.assertEqual(getargs_s_star(b'bytes'), b'bytes') - self.assertEqual(getargs_s_star(bytearray(b'bytearray')), b'bytearray') - self.assertEqual(getargs_s_star(memoryview(b'memoryview')), b'memoryview') - self.assertRaises(TypeError, getargs_s_star, None) - - def test_s_hash(self): - from _testcapi import getargs_s_hash - self.assertEqual(getargs_s_hash('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_s_hash('nul:\0'), b'nul:\0') - self.assertEqual(getargs_s_hash(b'bytes'), b'bytes') - self.assertRaises(TypeError, getargs_s_hash, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_s_hash, memoryview(b'memoryview')) - self.assertRaises(TypeError, getargs_s_hash, None) - - def test_s_hash_int(self): - # "s#" without PY_SSIZE_T_CLEAN defined. - from _testcapi import getargs_s_hash_int - from _testcapi import getargs_s_hash_int2 - buf = bytearray([1, 2]) - self.assertRaises(SystemError, getargs_s_hash_int, buf, "abc") - self.assertRaises(SystemError, getargs_s_hash_int, buf, x=42) - self.assertRaises(SystemError, getargs_s_hash_int, buf, x="abc") - self.assertRaises(SystemError, getargs_s_hash_int2, buf, ("abc",)) - self.assertRaises(SystemError, getargs_s_hash_int2, buf, x=42) - self.assertRaises(SystemError, getargs_s_hash_int2, buf, x="abc") - buf.append(3) # still mutable -- not locked by a buffer export - # getargs_s_hash_int(buf) may not raise SystemError because skipitem() - # is not called. But it is an implementation detail. - # getargs_s_hash_int(buf) - # getargs_s_hash_int2(buf) - - def test_z(self): - from _testcapi import getargs_z - self.assertEqual(getargs_z('abc\xe9'), b'abc\xc3\xa9') - self.assertRaises(ValueError, getargs_z, 'nul:\0') - self.assertRaises(TypeError, getargs_z, b'bytes') - self.assertRaises(TypeError, getargs_z, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_z, memoryview(b'memoryview')) - self.assertIsNone(getargs_z(None)) - - def test_z_star(self): - from _testcapi import getargs_z_star - self.assertEqual(getargs_z_star('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_z_star('nul:\0'), b'nul:\0') - self.assertEqual(getargs_z_star(b'bytes'), b'bytes') - self.assertEqual(getargs_z_star(bytearray(b'bytearray')), b'bytearray') - self.assertEqual(getargs_z_star(memoryview(b'memoryview')), b'memoryview') - self.assertIsNone(getargs_z_star(None)) - - def test_z_hash(self): - from _testcapi import getargs_z_hash - self.assertEqual(getargs_z_hash('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_z_hash('nul:\0'), b'nul:\0') - self.assertEqual(getargs_z_hash(b'bytes'), b'bytes') - self.assertRaises(TypeError, getargs_z_hash, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_z_hash, memoryview(b'memoryview')) - self.assertIsNone(getargs_z_hash(None)) - - def test_es(self): - from _testcapi import getargs_es - self.assertEqual(getargs_es('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_es('abc\xe9', 'latin1'), b'abc\xe9') - self.assertRaises(UnicodeEncodeError, getargs_es, 'abc\xe9', 'ascii') - self.assertRaises(LookupError, getargs_es, 'abc\xe9', 'spam') - self.assertRaises(TypeError, getargs_es, b'bytes', 'latin1') - self.assertRaises(TypeError, getargs_es, bytearray(b'bytearray'), 'latin1') - self.assertRaises(TypeError, getargs_es, memoryview(b'memoryview'), 'latin1') - self.assertRaises(TypeError, getargs_es, None, 'latin1') - self.assertRaises(TypeError, getargs_es, 'nul:\0', 'latin1') - - def test_et(self): - from _testcapi import getargs_et - self.assertEqual(getargs_et('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_et('abc\xe9', 'latin1'), b'abc\xe9') - self.assertRaises(UnicodeEncodeError, getargs_et, 'abc\xe9', 'ascii') - self.assertRaises(LookupError, getargs_et, 'abc\xe9', 'spam') - self.assertEqual(getargs_et(b'bytes', 'latin1'), b'bytes') - self.assertEqual(getargs_et(bytearray(b'bytearray'), 'latin1'), b'bytearray') - self.assertRaises(TypeError, getargs_et, memoryview(b'memoryview'), 'latin1') - self.assertRaises(TypeError, getargs_et, None, 'latin1') - self.assertRaises(TypeError, getargs_et, 'nul:\0', 'latin1') - self.assertRaises(TypeError, getargs_et, b'nul:\0', 'latin1') - self.assertRaises(TypeError, getargs_et, bytearray(b'nul:\0'), 'latin1') - - def test_es_hash(self): - from _testcapi import getargs_es_hash - self.assertEqual(getargs_es_hash('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_es_hash('abc\xe9', 'latin1'), b'abc\xe9') - self.assertRaises(UnicodeEncodeError, getargs_es_hash, 'abc\xe9', 'ascii') - self.assertRaises(LookupError, getargs_es_hash, 'abc\xe9', 'spam') - self.assertRaises(TypeError, getargs_es_hash, b'bytes', 'latin1') - self.assertRaises(TypeError, getargs_es_hash, bytearray(b'bytearray'), 'latin1') - self.assertRaises(TypeError, getargs_es_hash, memoryview(b'memoryview'), 'latin1') - self.assertRaises(TypeError, getargs_es_hash, None, 'latin1') - self.assertEqual(getargs_es_hash('nul:\0', 'latin1'), b'nul:\0') - - buf = bytearray(b'x'*8) - self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9') - self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx')) - buf = bytearray(b'x'*5) - self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9') - self.assertEqual(buf, bytearray(b'abc\xe9\x00')) - buf = bytearray(b'x'*4) - self.assertRaises(ValueError, getargs_es_hash, 'abc\xe9', 'latin1', buf) - self.assertEqual(buf, bytearray(b'x'*4)) - buf = bytearray() - self.assertRaises(ValueError, getargs_es_hash, 'abc\xe9', 'latin1', buf) - - def test_et_hash(self): - from _testcapi import getargs_et_hash - self.assertEqual(getargs_et_hash('abc\xe9'), b'abc\xc3\xa9') - self.assertEqual(getargs_et_hash('abc\xe9', 'latin1'), b'abc\xe9') - self.assertRaises(UnicodeEncodeError, getargs_et_hash, 'abc\xe9', 'ascii') - self.assertRaises(LookupError, getargs_et_hash, 'abc\xe9', 'spam') - self.assertEqual(getargs_et_hash(b'bytes', 'latin1'), b'bytes') - self.assertEqual(getargs_et_hash(bytearray(b'bytearray'), 'latin1'), b'bytearray') - self.assertRaises(TypeError, getargs_et_hash, memoryview(b'memoryview'), 'latin1') - self.assertRaises(TypeError, getargs_et_hash, None, 'latin1') - self.assertEqual(getargs_et_hash('nul:\0', 'latin1'), b'nul:\0') - self.assertEqual(getargs_et_hash(b'nul:\0', 'latin1'), b'nul:\0') - self.assertEqual(getargs_et_hash(bytearray(b'nul:\0'), 'latin1'), b'nul:\0') - - buf = bytearray(b'x'*8) - self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9') - self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx')) - buf = bytearray(b'x'*5) - self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9') - self.assertEqual(buf, bytearray(b'abc\xe9\x00')) - buf = bytearray(b'x'*4) - self.assertRaises(ValueError, getargs_et_hash, 'abc\xe9', 'latin1', buf) - self.assertEqual(buf, bytearray(b'x'*4)) - buf = bytearray() - self.assertRaises(ValueError, getargs_et_hash, 'abc\xe9', 'latin1', buf) - - @support.requires_legacy_unicode_capi - def test_u(self): - from _testcapi import getargs_u - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertRaises(ValueError, getargs_u, 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u, None) - with warnings.catch_warnings(): - warnings.simplefilter('error', DeprecationWarning) - self.assertRaises(DeprecationWarning, getargs_u, 'abc\xe9') - - @support.requires_legacy_unicode_capi - def test_u_hash(self): - from _testcapi import getargs_u_hash - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u_hash('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_u_hash('nul:\0'), 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_u_hash, None) - with warnings.catch_warnings(): - warnings.simplefilter('error', DeprecationWarning) - self.assertRaises(DeprecationWarning, getargs_u_hash, 'abc\xe9') - - @support.requires_legacy_unicode_capi - def test_Z(self): - from _testcapi import getargs_Z - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertRaises(ValueError, getargs_Z, 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertIsNone(getargs_Z(None)) - with warnings.catch_warnings(): - warnings.simplefilter('error', DeprecationWarning) - self.assertRaises(DeprecationWarning, getargs_Z, 'abc\xe9') - - @support.requires_legacy_unicode_capi - def test_Z_hash(self): - from _testcapi import getargs_Z_hash - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z_hash('abc\xe9'), 'abc\xe9') - with self.assertWarns(DeprecationWarning): - self.assertEqual(getargs_Z_hash('nul:\0'), 'nul:\0') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, b'bytes') - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, bytearray(b'bytearray')) - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, getargs_Z_hash, memoryview(b'memoryview')) - with self.assertWarns(DeprecationWarning): - self.assertIsNone(getargs_Z_hash(None)) - with warnings.catch_warnings(): - warnings.simplefilter('error', DeprecationWarning) - self.assertRaises(DeprecationWarning, getargs_Z_hash, 'abc\xe9') - - -class Object_TestCase(unittest.TestCase): - def test_S(self): - from _testcapi import getargs_S - obj = b'bytes' - self.assertIs(getargs_S(obj), obj) - self.assertRaises(TypeError, getargs_S, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_S, 'str') - self.assertRaises(TypeError, getargs_S, None) - self.assertRaises(TypeError, getargs_S, memoryview(obj)) - - def test_Y(self): - from _testcapi import getargs_Y - obj = bytearray(b'bytearray') - self.assertIs(getargs_Y(obj), obj) - self.assertRaises(TypeError, getargs_Y, b'bytes') - self.assertRaises(TypeError, getargs_Y, 'str') - self.assertRaises(TypeError, getargs_Y, None) - self.assertRaises(TypeError, getargs_Y, memoryview(obj)) - - def test_U(self): - from _testcapi import getargs_U - obj = 'str' - self.assertIs(getargs_U(obj), obj) - self.assertRaises(TypeError, getargs_U, b'bytes') - self.assertRaises(TypeError, getargs_U, bytearray(b'bytearray')) - self.assertRaises(TypeError, getargs_U, None) - - -# Bug #6012 -class Test6012(unittest.TestCase): - def test(self): - self.assertEqual(_testcapi.argparsing("Hello", "World"), 1) - - -class SkipitemTest(unittest.TestCase): - - # u, and Z raises DeprecationWarning - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_skipitem(self): - """ - If this test failed, you probably added a new "format unit" - in Python/getargs.c, but neglected to update our poor friend - skipitem() in the same file. (If so, shame on you!) - - With a few exceptions**, this function brute-force tests all - printable ASCII*** characters (32 to 126 inclusive) as format units, - checking to see that PyArg_ParseTupleAndKeywords() return consistent - errors both when the unit is attempted to be used and when it is - skipped. If the format unit doesn't exist, we'll get one of two - specific error messages (one for used, one for skipped); if it does - exist we *won't* get that error--we'll get either no error or some - other error. If we get the specific "does not exist" error for one - test and not for the other, there's a mismatch, and the test fails. - - ** Some format units have special funny semantics and it would - be difficult to accommodate them here. Since these are all - well-established and properly skipped in skipitem() we can - get away with not testing them--this test is really intended - to catch *new* format units. - - *** Python C source files must be ASCII. Therefore it's impossible - to have non-ASCII format units. - - """ - empty_tuple = () - tuple_1 = (0,) - dict_b = {'b':1} - keywords = ["a", "b"] - - for i in range(32, 127): - c = chr(i) - - # skip parentheses, the error reporting is inconsistent about them - # skip 'e', it's always a two-character code - # skip '|' and '$', they don't represent arguments anyway - if c in '()e|$': - continue - - # test the format unit when not skipped - format = c + "i" - try: - _testcapi.parse_tuple_and_keywords(tuple_1, dict_b, - format, keywords) - when_not_skipped = False - except SystemError as e: - s = "argument 1 (impossible)" - when_not_skipped = (str(e) == s) - except TypeError: - when_not_skipped = False - - # test the format unit when skipped - optional_format = "|" + format - try: - _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b, - optional_format, keywords) - when_skipped = False - except SystemError as e: - s = "impossible: '{}'".format(format) - when_skipped = (str(e) == s) - - message = ("test_skipitem_parity: " - "detected mismatch between convertsimple and skipitem " - "for format unit '{}' ({}), not skipped {}, skipped {}".format( - c, i, when_skipped, when_not_skipped)) - self.assertIs(when_skipped, when_not_skipped, message) - - def test_skipitem_with_suffix(self): - parse = _testcapi.parse_tuple_and_keywords - empty_tuple = () - tuple_1 = (0,) - dict_b = {'b':1} - keywords = ["a", "b"] - - supported = ('s#', 's*', 'z#', 'z*', 'u#', 'Z#', 'y#', 'y*', 'w#', 'w*') - for c in string.ascii_letters: - for c2 in '#*': - f = c + c2 - with self.subTest(format=f): - optional_format = "|" + f + "i" - if f in supported: - parse(empty_tuple, dict_b, optional_format, keywords) - else: - with self.assertRaisesRegex(SystemError, - 'impossible'): - parse(empty_tuple, dict_b, optional_format, keywords) - - for c in map(chr, range(32, 128)): - f = 'e' + c - optional_format = "|" + f + "i" - with self.subTest(format=f): - if c in 'st': - parse(empty_tuple, dict_b, optional_format, keywords) - else: - with self.assertRaisesRegex(SystemError, - 'impossible'): - parse(empty_tuple, dict_b, optional_format, keywords) - - -class ParseTupleAndKeywords_Test(unittest.TestCase): - - def test_parse_tuple_and_keywords(self): - # Test handling errors in the parse_tuple_and_keywords helper itself - self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords, - (), {}, 42, []) - self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, - (), {}, '', 42) - self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, - (), {}, '', [''] * 42) - self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords, - (), {}, '', [42]) - - def test_bad_use(self): - # Test handling invalid format and keywords in - # PyArg_ParseTupleAndKeywords() - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (1,), {}, '||O', ['a']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (1, 2), {}, '|O|O', ['a', 'b']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {'a': 1}, '$$O', ['a']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {'a': 1}, '$|O', ['a']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (1,), {}, '|O', ['a', 'b']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (1,), {}, '|OO', ['a']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {}, '|$O', ['']) - self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords, - (), {}, '|OO', ['a', '']) - - def test_positional_only(self): - parse = _testcapi.parse_tuple_and_keywords - - parse((1, 2, 3), {}, 'OOO', ['', '', 'a']) - parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a']) - with self.assertRaisesRegex(TypeError, - r'function takes at least 2 positional arguments \(1 given\)'): - parse((1,), {'a': 3}, 'OOO', ['', '', 'a']) - parse((1,), {}, 'O|OO', ['', '', 'a']) - with self.assertRaisesRegex(TypeError, - r'function takes at least 1 positional argument \(0 given\)'): - parse((), {}, 'O|OO', ['', '', 'a']) - parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a']) - with self.assertRaisesRegex(TypeError, - r'function takes exactly 2 positional arguments \(1 given\)'): - parse((1,), {'a': 3}, 'OO$O', ['', '', 'a']) - parse((1,), {}, 'O|O$O', ['', '', 'a']) - with self.assertRaisesRegex(TypeError, - r'function takes at least 1 positional argument \(0 given\)'): - parse((), {}, 'O|O$O', ['', '', 'a']) - with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'): - parse((1,), {}, 'O|$OO', ['', '', 'a']) - with self.assertRaisesRegex(SystemError, 'Empty keyword'): - parse((1,), {}, 'O|OO', ['', 'a', '']) - - -class Test_testcapi(unittest.TestCase): - locals().update((name, getattr(_testcapi, name)) - for name in dir(_testcapi) - if name.startswith('test_') and name.endswith('_code')) - - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_u_code(self): - _testcapi.test_u_code() - - @warnings_helper.ignore_warnings(category=DeprecationWarning) - def test_Z_code(self): - _testcapi.test_Z_code() - - -if __name__ == "__main__": - unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_grammar.py python3.10-3.10.12/Lib/test/test_grammar.py --- python3.10-3.10.7/Lib/test/test_grammar.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_grammar.py 2023-06-06 22:30:33.000000000 +0000 @@ -406,6 +406,28 @@ x: int x.y: list = [] + def test_annotations_inheritance(self): + # Check that annotations are not inherited by derived classes + class A: + attr: int + class B(A): + pass + class C(A): + attr: str + class D: + attr2: int + class E(A, D): + pass + class F(C, A): + pass + self.assertEqual(A.__annotations__, {"attr": int}) + self.assertEqual(B.__annotations__, {}) + self.assertEqual(C.__annotations__, {"attr" : str}) + self.assertEqual(D.__annotations__, {"attr2" : int}) + self.assertEqual(E.__annotations__, {}) + self.assertEqual(F.__annotations__, {}) + + def test_var_annot_metaclass_semantics(self): class CMeta(type): @classmethod diff -Nru python3.10-3.10.7/Lib/test/test_hashlib.py python3.10-3.10.12/Lib/test/test_hashlib.py --- python3.10-3.10.7/Lib/test/test_hashlib.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_hashlib.py 2023-06-06 22:30:33.000000000 +0000 @@ -495,6 +495,15 @@ def test_case_md5_uintmax(self, size): self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3') + @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems') + @bigmemtest(size=_4G - 1, memuse=1, dry_run=False) + def test_sha3_update_overflow(self, size): + """Regression test for gh-98517 CVE-2022-37454.""" + h = hashlib.sha3_224() + h.update(b'\x01') + h.update(b'\x01'*0xffff_ffff) + self.assertEqual(h.hexdigest(), '80762e8ce6700f114fec0f621fd97c4b9c00147fa052215294cceeed') + # use the three examples from Federal Information Processing Standards # Publication 180-1, Secure Hash Standard, 1995 April 17 # http://www.itl.nist.gov/div897/pubs/fip180-1.htm diff -Nru python3.10-3.10.7/Lib/test/test_httpservers.py python3.10-3.10.12/Lib/test/test_httpservers.py --- python3.10-3.10.7/Lib/test/test_httpservers.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_httpservers.py 2023-06-06 22:30:33.000000000 +0000 @@ -26,7 +26,7 @@ import datetime import threading from unittest import mock -from io import BytesIO +from io import BytesIO, StringIO import unittest from test import support @@ -417,6 +417,14 @@ self.check_status_and_reason(response, HTTPStatus.OK, data=os_helper.TESTFN_UNDECODABLE) + def test_undecodable_parameter(self): + # sanity check using a valid parameter + response = self.request(self.base_url + '/?x=123').read() + self.assertRegex(response, f'listing for {self.base_url}/\?x=123'.encode('latin1')) + # now the bogus encoding + response = self.request(self.base_url + '/?x=%bb').read() + self.assertRegex(response, f'listing for {self.base_url}/\?x=\xef\xbf\xbd'.encode('latin1')) + def test_get_dir_redirect_location_domain_injection_bug(self): """Ensure //evil.co/..%2f../../X does not put //evil.co/ in Location. @@ -488,6 +496,9 @@ self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) response = self.request('/' + 'ThisDoesNotExist' + '/') self.check_status_and_reason(response, HTTPStatus.NOT_FOUND) + os.makedirs(os.path.join(self.tempdir, 'spam', 'index.html')) + response = self.request(self.base_url + '/spam/') + self.check_status_and_reason(response, HTTPStatus.OK) data = b"Dummy index file\r\n" with open(os.path.join(self.tempdir_name, 'index.html'), 'wb') as f: @@ -984,6 +995,27 @@ match = self.HTTPResponseMatch.search(response) self.assertIsNotNone(match) + def test_unprintable_not_logged(self): + # We call the method from the class directly as our Socketless + # Handler subclass overrode it... nice for everything BUT this test. + self.handler.client_address = ('127.0.0.1', 1337) + log_message = BaseHTTPRequestHandler.log_message + with mock.patch.object(sys, 'stderr', StringIO()) as fake_stderr: + log_message(self.handler, '/foo') + log_message(self.handler, '/\033bar\000\033') + log_message(self.handler, '/spam %s.', 'a') + log_message(self.handler, '/spam %s.', '\033\x7f\x9f\xa0beans') + log_message(self.handler, '"GET /foo\\b"ar\007 HTTP/1.0"') + stderr = fake_stderr.getvalue() + self.assertNotIn('\033', stderr) # non-printable chars are caught. + self.assertNotIn('\000', stderr) # non-printable chars are caught. + lines = stderr.splitlines() + self.assertIn('/foo', lines[0]) + self.assertIn(r'/\x1bbar\x00\x1b', lines[1]) + self.assertIn('/spam a.', lines[2]) + self.assertIn('/spam \\x1b\\x7f\\x9f\xa0beans.', lines[3]) + self.assertIn(r'"GET /foo\\b"ar\x07 HTTP/1.0"', lines[4]) + def test_http_1_1(self): result = self.send_typical_request(b'GET / HTTP/1.1\r\n\r\n') self.verify_http_server_response(result[0]) diff -Nru python3.10-3.10.7/Lib/test/test_importlib/test_metadata_api.py python3.10-3.10.12/Lib/test/test_importlib/test_metadata_api.py --- python3.10-3.10.7/Lib/test/test_importlib/test_metadata_api.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_importlib/test_metadata_api.py 2023-06-06 22:30:33.000000000 +0000 @@ -89,13 +89,15 @@ self.assertIn(ep.dist.name, ('distinfo-pkg', 'egginfo-pkg')) self.assertEqual(ep.dist.version, "1.0.0") - def test_entry_points_unique_packages(self): - # Entry points should only be exposed for the first package - # on sys.path with a given name. + def test_entry_points_unique_packages_normalized(self): + """ + Entry points should only be exposed for the first package + on sys.path with a given name (even when normalized). + """ alt_site_dir = self.fixtures.enter_context(fixtures.tempdir()) self.fixtures.enter_context(self.add_sys_path(alt_site_dir)) alt_pkg = { - "distinfo_pkg-1.1.0.dist-info": { + "DistInfo_pkg-1.1.0.dist-info": { "METADATA": """ Name: distinfo-pkg Version: 1.1.0 diff -Nru python3.10-3.10.7/Lib/test/test_importlib/util.py python3.10-3.10.12/Lib/test/test_importlib/util.py --- python3.10-3.10.7/Lib/test/test_importlib/util.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_importlib/util.py 2023-06-06 22:30:33.000000000 +0000 @@ -307,7 +307,7 @@ """Decorator to protect sys.dont_write_bytecode from mutation and to skip tests that require it to be set to False.""" if sys.dont_write_bytecode: - return lambda *args, **kwargs: None + return unittest.skip("relies on writing bytecode")(fxn) @functools.wraps(fxn) def wrapper(*args, **kwargs): original = sys.dont_write_bytecode diff -Nru python3.10-3.10.7/Lib/test/test_imp.py python3.10-3.10.12/Lib/test/test_imp.py --- python3.10-3.10.7/Lib/test/test_imp.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_imp.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,3 +1,4 @@ +import gc import importlib import importlib.util import os @@ -379,6 +380,35 @@ self.assertEqual(mod.x, 42) + @support.cpython_only + def test_create_builtin_subinterp(self): + # gh-99578: create_builtin() behavior changes after the creation of the + # first sub-interpreter. Test both code paths, before and after the + # creation of a sub-interpreter. Previously, create_builtin() had + # a reference leak after the creation of the first sub-interpreter. + + import builtins + create_builtin = support.get_attribute(_imp, "create_builtin") + class Spec: + name = "builtins" + spec = Spec() + + def check_get_builtins(): + refcnt = sys.getrefcount(builtins) + mod = _imp.create_builtin(spec) + self.assertIs(mod, builtins) + self.assertEqual(sys.getrefcount(builtins), refcnt + 1) + # Check that a GC collection doesn't crash + gc.collect() + + check_get_builtins() + + ret = support.run_in_subinterp("import builtins") + self.assertEqual(ret, 0) + + check_get_builtins() + + class ReloadTests(unittest.TestCase): """Very basic tests to make sure that imp.reload() operates just like diff -Nru python3.10-3.10.7/Lib/test/test_inspect.py python3.10-3.10.12/Lib/test/test_inspect.py --- python3.10-3.10.7/Lib/test/test_inspect.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_inspect.py 2023-06-06 22:30:33.000000000 +0000 @@ -825,6 +825,12 @@ self.assertSourceEqual(self.fodderModule.X, 1, 2) +class TestComplexDecorator(GetSourceBase): + fodderModule = mod2 + + def test_parens_in_decorator(self): + self.assertSourceEqual(self.fodderModule.complex_decorated, 273, 275) + class _BrokenDataDescriptor(object): """ A broken data descriptor. See bug #1785. @@ -1418,6 +1424,13 @@ self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int}) +class TestFormatAnnotation(unittest.TestCase): + def test_typing_replacement(self): + from test.typinganndata.ann_module9 import ann, ann1 + self.assertEqual(inspect.formatannotation(ann), 'Union[List[str], int]') + self.assertEqual(inspect.formatannotation(ann1), 'Union[List[testModule.typing.A], int]') + + class TestIsDataDescriptor(unittest.TestCase): def test_custom_descriptors(self): @@ -2464,7 +2477,7 @@ self.assertEqual(p('f'), False) self.assertEqual(p('local'), 3) self.assertEqual(p('sys'), sys.maxsize) - self.assertNotIn('exp', signature.parameters) + self.assertEqual(p('exp'), sys.maxsize - 1) test_callable(object) @@ -2950,8 +2963,6 @@ self.assertEqual(str(inspect.signature(foo)), '(a)') def test_signature_on_decorated(self): - import functools - def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs) -> int: @@ -2963,6 +2974,8 @@ def bar(self, a, b): pass + bar = decorator(Foo().bar) + self.assertEqual(self.signature(Foo.bar), ((('self', ..., ..., "positional_or_keyword"), ('a', ..., ..., "positional_or_keyword"), @@ -2981,6 +2994,11 @@ # from "func" to "wrapper", hence no # return_annotation + self.assertEqual(self.signature(bar), + ((('a', ..., ..., "positional_or_keyword"), + ('b', ..., ..., "positional_or_keyword")), + ...)) + # Test that we handle method wrappers correctly def decorator(func): @functools.wraps(func) @@ -4228,10 +4246,29 @@ sig = inspect.signature(func) self.assertIsNotNone(sig) self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)') + func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)' sig = inspect.signature(func) self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)') + func.__text_signature__ = '(self, a=1+2, b=4-3, c=1 | 3 | 16)' + sig = inspect.signature(func) + self.assertEqual(str(sig), '(self, a=3, b=1, c=19)') + + func.__text_signature__ = '(self, a=1,\nb=2,\n\n\n c=3)' + sig = inspect.signature(func) + self.assertEqual(str(sig), '(self, a=1, b=2, c=3)') + + func.__text_signature__ = '(self, x=does_not_exist)' + with self.assertRaises(ValueError): + inspect.signature(func) + func.__text_signature__ = '(self, x=sys, y=inspect)' + with self.assertRaises(ValueError): + inspect.signature(func) + func.__text_signature__ = '(self, 123)' + with self.assertRaises(ValueError): + inspect.signature(func) + def test_base_class_have_text_signature(self): # see issue 43118 from test.ann_module7 import BufferedReader diff -Nru python3.10-3.10.7/Lib/test/test_int.py python3.10-3.10.12/Lib/test/test_int.py --- python3.10-3.10.7/Lib/test/test_int.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_int.py 2023-06-06 22:30:33.000000000 +0000 @@ -641,7 +641,8 @@ self.assertEqual(len(huge_decimal), digits) # Ensuring that we chose a slow enough conversion to measure. # It takes 0.1 seconds on a Zen based cloud VM in an opt build. - if seconds_to_convert < 0.005: + # Some OSes have a low res 1/64s timer, skip if hard to measure. + if seconds_to_convert < 1/64: raise unittest.SkipTest('"slow" conversion took only ' f'{seconds_to_convert} seconds.') @@ -653,7 +654,7 @@ str(huge_int) seconds_to_fail_huge = get_time() - start self.assertIn('conversion', str(err.exception)) - self.assertLess(seconds_to_fail_huge, seconds_to_convert/8) + self.assertLessEqual(seconds_to_fail_huge, seconds_to_convert/2) # Now we test that a conversion that would take 30x as long also fails # in a similarly fast fashion. @@ -664,7 +665,7 @@ str(extra_huge_int) seconds_to_fail_extra_huge = get_time() - start self.assertIn('conversion', str(err.exception)) - self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8) + self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/2) def test_denial_of_service_prevented_str_to_int(self): """Regression test: ensure we fail before performing O(N**2) work.""" @@ -682,7 +683,8 @@ seconds_to_convert = get_time() - start # Ensuring that we chose a slow enough conversion to measure. # It takes 0.1 seconds on a Zen based cloud VM in an opt build. - if seconds_to_convert < 0.005: + # Some OSes have a low res 1/64s timer, skip if hard to measure. + if seconds_to_convert < 1/64: raise unittest.SkipTest('"slow" conversion took only ' f'{seconds_to_convert} seconds.') @@ -692,7 +694,7 @@ int(huge) seconds_to_fail_huge = get_time() - start self.assertIn('conversion', str(err.exception)) - self.assertLess(seconds_to_fail_huge, seconds_to_convert/8) + self.assertLessEqual(seconds_to_fail_huge, seconds_to_convert/2) # Now we test that a conversion that would take 30x as long also fails # in a similarly fast fashion. @@ -703,7 +705,7 @@ int(extra_huge) seconds_to_fail_extra_huge = get_time() - start self.assertIn('conversion', str(err.exception)) - self.assertLess(seconds_to_fail_extra_huge, seconds_to_convert/8) + self.assertLessEqual(seconds_to_fail_extra_huge, seconds_to_convert/2) def test_power_of_two_bases_unlimited(self): """The limit does not apply to power of 2 bases.""" diff -Nru python3.10-3.10.7/Lib/test/test_io.py python3.10-3.10.12/Lib/test/test_io.py --- python3.10-3.10.7/Lib/test/test_io.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_io.py 2023-06-06 22:30:33.000000000 +0000 @@ -880,6 +880,14 @@ open('non-existent', 'r', opener=badopener) self.assertEqual(str(cm.exception), 'opener returned -2') + def test_opener_invalid_fd(self): + # Check that OSError is raised with error code EBADF if the + # opener returns an invalid file descriptor (see gh-82212). + fd = os_helper.make_bad_fd() + with self.assertRaises(OSError) as cm: + self.open('foo', opener=lambda name, flags: fd) + self.assertEqual(cm.exception.errno, errno.EBADF) + def test_fileio_closefd(self): # Issue #4841 with self.open(__file__, 'rb') as f1, \ @@ -3918,7 +3926,15 @@ self.assertEqual(decoder.decode(b"\r\r\n"), "\r\r\n") class CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): - pass + @support.cpython_only + def test_uninitialized(self): + uninitialized = self.IncrementalNewlineDecoder.__new__( + self.IncrementalNewlineDecoder) + self.assertRaises(ValueError, uninitialized.decode, b'bar') + self.assertRaises(ValueError, uninitialized.getstate) + self.assertRaises(ValueError, uninitialized.setstate, (b'foo', 0)) + self.assertRaises(ValueError, uninitialized.reset) + class PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): pass diff -Nru python3.10-3.10.7/Lib/test/test_ipaddress.py python3.10-3.10.12/Lib/test/test_ipaddress.py --- python3.10-3.10.7/Lib/test/test_ipaddress.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_ipaddress.py 2023-06-06 22:30:33.000000000 +0000 @@ -1653,7 +1653,7 @@ self.assertRaises(IndexError, self.ipv6_scoped_network.__getitem__, 1 << 64) def testGetitem(self): - # http://code.google.com/p/ipaddr-py/issues/detail?id=15 + # https://code.google.com/p/ipaddr-py/issues/detail?id=15 addr = ipaddress.IPv4Network('172.31.255.128/255.255.255.240') self.assertEqual(28, addr.prefixlen) addr_list = list(addr) diff -Nru python3.10-3.10.7/Lib/test/test_iter.py python3.10-3.10.12/Lib/test/test_iter.py --- python3.10-3.10.7/Lib/test/test_iter.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_iter.py 2023-06-06 22:30:33.000000000 +0000 @@ -7,6 +7,9 @@ from test.support import check_free_after_iterating, ALWAYS_EQ, NEVER_EQ import pickle import collections.abc +import functools +import contextlib +import builtins # Test result of triple loop (too big to inline) TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), @@ -81,6 +84,12 @@ def __iter__(self): raise ZeroDivisionError +class EmptyIterClass: + def __len__(self): + return 0 + def __getitem__(self, i): + raise StopIteration + # Main test suite class TestCase(unittest.TestCase): @@ -228,6 +237,77 @@ self.assertEqual(list(empit), [5, 6]) self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6]) + def test_reduce_mutating_builtins_iter(self): + # This is a reproducer of issue #101765 + # where iter `__reduce__` calls could lead to a segfault or SystemError + # depending on the order of C argument evaluation, which is undefined + + # Backup builtins + builtins_dict = builtins.__dict__ + orig = {"iter": iter, "reversed": reversed} + + def run(builtin_name, item, sentinel=None): + it = iter(item) if sentinel is None else iter(item, sentinel) + + class CustomStr: + def __init__(self, name, iterator): + self.name = name + self.iterator = iterator + def __hash__(self): + return hash(self.name) + def __eq__(self, other): + # Here we exhaust our iterator, possibly changing + # its `it_seq` pointer to NULL + # The `__reduce__` call should correctly get + # the pointers after this call + list(self.iterator) + return other == self.name + + # del is required here + # to not prematurely call __eq__ from + # the hash collision with the old key + del builtins_dict[builtin_name] + builtins_dict[CustomStr(builtin_name, it)] = orig[builtin_name] + + return it.__reduce__() + + types = [ + (EmptyIterClass(),), + (bytes(8),), + (bytearray(8),), + ((1, 2, 3),), + (lambda: 0, 0), + ] + + try: + run_iter = functools.partial(run, "iter") + # The returned value of `__reduce__` should not only be valid + # but also *empty*, as `it` was exhausted during `__eq__` + # i.e "xyz" returns (iter, ("",)) + self.assertEqual(run_iter("xyz"), (orig["iter"], ("",))) + self.assertEqual(run_iter([1, 2, 3]), (orig["iter"], ([],))) + + # _PyEval_GetBuiltin is also called for `reversed` in a branch of + # listiter_reduce_general + self.assertEqual( + run("reversed", orig["reversed"](list(range(8)))), + (iter, ([],)) + ) + + for case in types: + self.assertEqual(run_iter(*case), (orig["iter"], ((),))) + finally: + # Restore original builtins + for key, func in orig.items(): + # need to suppress KeyErrors in case + # a failed test deletes the key without setting anything + with contextlib.suppress(KeyError): + # del is required here + # to not invoke our custom __eq__ from + # the hash collision with the old key + del builtins_dict[key] + builtins_dict[key] = func + # Test a new_style class with __iter__ but no next() method def test_new_style_iter_class(self): class IterClass(object): @@ -266,6 +346,31 @@ return i self.check_iterator(iter(spam, 20), list(range(10)), pickle=False) + def test_iter_function_concealing_reentrant_exhaustion(self): + # gh-101892: Test two-argument iter() with a function that + # exhausts its associated iterator but forgets to either return + # a sentinel value or raise StopIteration. + HAS_MORE = 1 + NO_MORE = 2 + + def exhaust(iterator): + """Exhaust an iterator without raising StopIteration.""" + list(iterator) + + def spam(): + # Touching the iterator with exhaust() below will call + # spam() once again so protect against recursion. + if spam.is_recursive_call: + return NO_MORE + spam.is_recursive_call = True + exhaust(spam.iterator) + return HAS_MORE + + spam.is_recursive_call = False + spam.iterator = iter(spam, NO_MORE) + with self.assertRaises(StopIteration): + next(spam.iterator) + # Test exception propagation through function iterator def test_exception_function(self): def spam(state=[0]): diff -Nru python3.10-3.10.7/Lib/test/test_itertools.py python3.10-3.10.12/Lib/test/test_itertools.py --- python3.10-3.10.7/Lib/test/test_itertools.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_itertools.py 2023-06-06 22:30:33.000000000 +0000 @@ -634,6 +634,7 @@ self.assertRaises(TypeError, cycle, 5) self.assertEqual(list(islice(cycle(gen3()),10)), [0,1,2,0,1,2,0,1,2,0]) + def test_cycle_copy_pickle(self): # check copy, deepcopy, pickle c = cycle('abc') self.assertEqual(next(c), 'a') @@ -669,6 +670,37 @@ d = pickle.loads(p) # rebuild the cycle object self.assertEqual(take(20, d), list('cdeabcdeabcdeabcdeab')) + def test_cycle_unpickle_compat(self): + testcases = [ + b'citertools\ncycle\n(c__builtin__\niter\n((lI1\naI2\naI3\natRI1\nbtR((lI1\naI0\ntb.', + b'citertools\ncycle\n(c__builtin__\niter\n(](K\x01K\x02K\x03etRK\x01btR(]K\x01aK\x00tb.', + b'\x80\x02citertools\ncycle\nc__builtin__\niter\n](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01aK\x00\x86b.', + b'\x80\x03citertools\ncycle\ncbuiltins\niter\n](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01aK\x00\x86b.', + b'\x80\x04\x95=\x00\x00\x00\x00\x00\x00\x00\x8c\titertools\x8c\x05cycle\x93\x8c\x08builtins\x8c\x04iter\x93](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01aK\x00\x86b.', + + b'citertools\ncycle\n(c__builtin__\niter\n((lp0\nI1\naI2\naI3\natRI1\nbtR(g0\nI1\ntb.', + b'citertools\ncycle\n(c__builtin__\niter\n(]q\x00(K\x01K\x02K\x03etRK\x01btR(h\x00K\x01tb.', + b'\x80\x02citertools\ncycle\nc__builtin__\niter\n]q\x00(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00K\x01\x86b.', + b'\x80\x03citertools\ncycle\ncbuiltins\niter\n]q\x00(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00K\x01\x86b.', + b'\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\titertools\x8c\x05cycle\x93\x8c\x08builtins\x8c\x04iter\x93]\x94(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00K\x01\x86b.', + + b'citertools\ncycle\n(c__builtin__\niter\n((lI1\naI2\naI3\natRI1\nbtR((lI1\naI00\ntb.', + b'citertools\ncycle\n(c__builtin__\niter\n(](K\x01K\x02K\x03etRK\x01btR(]K\x01aI00\ntb.', + b'\x80\x02citertools\ncycle\nc__builtin__\niter\n](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01a\x89\x86b.', + b'\x80\x03citertools\ncycle\ncbuiltins\niter\n](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01a\x89\x86b.', + b'\x80\x04\x95<\x00\x00\x00\x00\x00\x00\x00\x8c\titertools\x8c\x05cycle\x93\x8c\x08builtins\x8c\x04iter\x93](K\x01K\x02K\x03e\x85RK\x01b\x85R]K\x01a\x89\x86b.', + + b'citertools\ncycle\n(c__builtin__\niter\n((lp0\nI1\naI2\naI3\natRI1\nbtR(g0\nI01\ntb.', + b'citertools\ncycle\n(c__builtin__\niter\n(]q\x00(K\x01K\x02K\x03etRK\x01btR(h\x00I01\ntb.', + b'\x80\x02citertools\ncycle\nc__builtin__\niter\n]q\x00(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00\x88\x86b.', + b'\x80\x03citertools\ncycle\ncbuiltins\niter\n]q\x00(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00\x88\x86b.', + b'\x80\x04\x95;\x00\x00\x00\x00\x00\x00\x00\x8c\titertools\x8c\x05cycle\x93\x8c\x08builtins\x8c\x04iter\x93]\x94(K\x01K\x02K\x03e\x85RK\x01b\x85Rh\x00\x88\x86b.', + ] + assert len(testcases) == 20 + for t in testcases: + it = pickle.loads(t) + self.assertEqual(take(10, it), [2, 3, 1, 2, 3, 1, 2, 3, 1, 2]) + def test_cycle_setstate(self): # Verify both modes for restoring state diff -Nru python3.10-3.10.7/Lib/test/test_json/test_default.py python3.10-3.10.12/Lib/test/test_json/test_default.py --- python3.10-3.10.7/Lib/test/test_json/test_default.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_json/test_default.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,3 +1,4 @@ +import collections from test.test_json import PyTest, CTest @@ -7,6 +8,16 @@ self.dumps(type, default=repr), self.dumps(repr(type))) + def test_ordereddict(self): + od = collections.OrderedDict(a=1, b=2) + od.move_to_end('a') + self.assertEqual( + self.dumps(od), + '{"b": 2, "a": 1}') + self.assertEqual( + self.dumps(od, sort_keys=True), + '{"a": 1, "b": 2}') + class TestPyDefault(TestDefault, PyTest): pass class TestCDefault(TestDefault, CTest): pass diff -Nru python3.10-3.10.7/Lib/test/test_json/test_fail.py python3.10-3.10.12/Lib/test/test_json/test_fail.py --- python3.10-3.10.7/Lib/test/test_json/test_fail.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_json/test_fail.py 2023-06-06 22:30:33.000000000 +0000 @@ -2,73 +2,73 @@ # 2007-10-05 JSONDOCS = [ - # http://json.org/JSON_checker/test/fail1.json + # https://json.org/JSON_checker/test/fail1.json '"A JSON payload should be an object or array, not a string."', - # http://json.org/JSON_checker/test/fail2.json + # https://json.org/JSON_checker/test/fail2.json '["Unclosed array"', - # http://json.org/JSON_checker/test/fail3.json + # https://json.org/JSON_checker/test/fail3.json '{unquoted_key: "keys must be quoted"}', - # http://json.org/JSON_checker/test/fail4.json + # https://json.org/JSON_checker/test/fail4.json '["extra comma",]', - # http://json.org/JSON_checker/test/fail5.json + # https://json.org/JSON_checker/test/fail5.json '["double extra comma",,]', - # http://json.org/JSON_checker/test/fail6.json + # https://json.org/JSON_checker/test/fail6.json '[ , "<-- missing value"]', - # http://json.org/JSON_checker/test/fail7.json + # https://json.org/JSON_checker/test/fail7.json '["Comma after the close"],', - # http://json.org/JSON_checker/test/fail8.json + # https://json.org/JSON_checker/test/fail8.json '["Extra close"]]', - # http://json.org/JSON_checker/test/fail9.json + # https://json.org/JSON_checker/test/fail9.json '{"Extra comma": true,}', - # http://json.org/JSON_checker/test/fail10.json + # https://json.org/JSON_checker/test/fail10.json '{"Extra value after close": true} "misplaced quoted value"', - # http://json.org/JSON_checker/test/fail11.json + # https://json.org/JSON_checker/test/fail11.json '{"Illegal expression": 1 + 2}', - # http://json.org/JSON_checker/test/fail12.json + # https://json.org/JSON_checker/test/fail12.json '{"Illegal invocation": alert()}', - # http://json.org/JSON_checker/test/fail13.json + # https://json.org/JSON_checker/test/fail13.json '{"Numbers cannot have leading zeroes": 013}', - # http://json.org/JSON_checker/test/fail14.json + # https://json.org/JSON_checker/test/fail14.json '{"Numbers cannot be hex": 0x14}', - # http://json.org/JSON_checker/test/fail15.json + # https://json.org/JSON_checker/test/fail15.json '["Illegal backslash escape: \\x15"]', - # http://json.org/JSON_checker/test/fail16.json + # https://json.org/JSON_checker/test/fail16.json '[\\naked]', - # http://json.org/JSON_checker/test/fail17.json + # https://json.org/JSON_checker/test/fail17.json '["Illegal backslash escape: \\017"]', - # http://json.org/JSON_checker/test/fail18.json + # https://json.org/JSON_checker/test/fail18.json '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', - # http://json.org/JSON_checker/test/fail19.json + # https://json.org/JSON_checker/test/fail19.json '{"Missing colon" null}', - # http://json.org/JSON_checker/test/fail20.json + # https://json.org/JSON_checker/test/fail20.json '{"Double colon":: null}', - # http://json.org/JSON_checker/test/fail21.json + # https://json.org/JSON_checker/test/fail21.json '{"Comma instead of colon", null}', - # http://json.org/JSON_checker/test/fail22.json + # https://json.org/JSON_checker/test/fail22.json '["Colon instead of comma": false]', - # http://json.org/JSON_checker/test/fail23.json + # https://json.org/JSON_checker/test/fail23.json '["Bad value", truth]', - # http://json.org/JSON_checker/test/fail24.json + # https://json.org/JSON_checker/test/fail24.json "['single quote']", - # http://json.org/JSON_checker/test/fail25.json + # https://json.org/JSON_checker/test/fail25.json '["\ttab\tcharacter\tin\tstring\t"]', - # http://json.org/JSON_checker/test/fail26.json + # https://json.org/JSON_checker/test/fail26.json '["tab\\ character\\ in\\ string\\ "]', - # http://json.org/JSON_checker/test/fail27.json + # https://json.org/JSON_checker/test/fail27.json '["line\nbreak"]', - # http://json.org/JSON_checker/test/fail28.json + # https://json.org/JSON_checker/test/fail28.json '["line\\\nbreak"]', - # http://json.org/JSON_checker/test/fail29.json + # https://json.org/JSON_checker/test/fail29.json '[0e]', - # http://json.org/JSON_checker/test/fail30.json + # https://json.org/JSON_checker/test/fail30.json '[0e+]', - # http://json.org/JSON_checker/test/fail31.json + # https://json.org/JSON_checker/test/fail31.json '[0e+-1]', - # http://json.org/JSON_checker/test/fail32.json + # https://json.org/JSON_checker/test/fail32.json '{"Comma instead if closing brace": true,', - # http://json.org/JSON_checker/test/fail33.json + # https://json.org/JSON_checker/test/fail33.json '["mismatch"}', - # http://code.google.com/p/simplejson/issues/detail?id=3 + # https://code.google.com/archive/p/simplejson/issues/3 '["A\u001FZ control characters in string"]', ] diff -Nru python3.10-3.10.7/Lib/test/test_json/test_pass1.py python3.10-3.10.12/Lib/test/test_json/test_pass1.py --- python3.10-3.10.7/Lib/test/test_json/test_pass1.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_json/test_pass1.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,7 +1,7 @@ from test.test_json import PyTest, CTest -# from http://json.org/JSON_checker/test/pass1.json +# from https://json.org/JSON_checker/test/pass1.json JSON = r''' [ "JSON Test Pattern pass1", diff -Nru python3.10-3.10.7/Lib/test/test_json/test_pass2.py python3.10-3.10.12/Lib/test/test_json/test_pass2.py --- python3.10-3.10.7/Lib/test/test_json/test_pass2.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_json/test_pass2.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,7 +1,7 @@ from test.test_json import PyTest, CTest -# from http://json.org/JSON_checker/test/pass2.json +# from https://json.org/JSON_checker/test/pass2.json JSON = r''' [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] ''' diff -Nru python3.10-3.10.7/Lib/test/test_json/test_pass3.py python3.10-3.10.12/Lib/test/test_json/test_pass3.py --- python3.10-3.10.7/Lib/test/test_json/test_pass3.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_json/test_pass3.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,7 +1,7 @@ from test.test_json import PyTest, CTest -# from http://json.org/JSON_checker/test/pass3.json +# from https://json.org/JSON_checker/test/pass3.json JSON = r''' { "JSON Test Pattern pass3": { diff -Nru python3.10-3.10.7/Lib/test/test_keyword.py python3.10-3.10.12/Lib/test/test_keyword.py --- python3.10-3.10.7/Lib/test/test_keyword.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_keyword.py 2023-06-06 22:30:33.000000000 +0000 @@ -20,18 +20,36 @@ keyword.kwlist = ['its', 'all', 'eggs', 'beans', 'and', 'a', 'slice'] self.assertFalse(keyword.iskeyword('eggs')) + def test_changing_the_softkwlist_does_not_affect_issoftkeyword(self): + oldlist = keyword.softkwlist + self.addCleanup(setattr, keyword, "softkwlist", oldlist) + keyword.softkwlist = ["foo", "bar", "spam", "egs", "case"] + self.assertFalse(keyword.issoftkeyword("spam")) + def test_all_keywords_fail_to_be_used_as_names(self): for key in keyword.kwlist: with self.assertRaises(SyntaxError): exec(f"{key} = 42") + def test_all_soft_keywords_can_be_used_as_names(self): + for key in keyword.softkwlist: + exec(f"{key} = 42") + def test_async_and_await_are_keywords(self): self.assertIn("async", keyword.kwlist) self.assertIn("await", keyword.kwlist) + def test_match_and_case_are_soft_keywords(self): + self.assertIn("match", keyword.softkwlist) + self.assertIn("case", keyword.softkwlist) + self.assertIn("_", keyword.softkwlist) + def test_keywords_are_sorted(self): self.assertListEqual(sorted(keyword.kwlist), keyword.kwlist) + def test_softkeywords_are_sorted(self): + self.assertListEqual(sorted(keyword.softkwlist), keyword.softkwlist) + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_list.py python3.10-3.10.12/Lib/test/test_list.py --- python3.10-3.10.7/Lib/test/test_list.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_list.py 2023-06-06 22:30:33.000000000 +0000 @@ -68,6 +68,19 @@ self.assertRaises((MemoryError, OverflowError), mul, lst, n) self.assertRaises((MemoryError, OverflowError), imul, lst, n) + def test_list_resize_overflow(self): + # gh-97616: test new_allocated * sizeof(PyObject*) overflow + # check in list_resize() + lst = [0] * 65 + del lst[1:] + self.assertEqual(len(lst), 1) + + size = ((2 ** (tuple.__itemsize__ * 8) - 1) // 2) + with self.assertRaises((MemoryError, OverflowError)): + lst * size + with self.assertRaises((MemoryError, OverflowError)): + lst *= size + def test_repr_large(self): # Check the repr of large list objects def check(n): diff -Nru python3.10-3.10.7/Lib/test/test_long.py python3.10-3.10.12/Lib/test/test_long.py --- python3.10-3.10.7/Lib/test/test_long.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_long.py 2023-06-06 22:30:33.000000000 +0000 @@ -1350,6 +1350,26 @@ self.assertEqual(i, 1) self.assertEqual(getattr(i, 'foo', 'none'), 'bar') + class ValidBytes: + def __bytes__(self): + return b'\x01' + class InvalidBytes: + def __bytes__(self): + return 'abc' + class MissingBytes: ... + class RaisingBytes: + def __bytes__(self): + 1 / 0 + + for byte_order in ('big', 'little'): + self.assertEqual(int.from_bytes(ValidBytes(), byte_order), 1) + self.assertRaises( + TypeError, int.from_bytes, InvalidBytes(), byte_order) + self.assertRaises( + TypeError, int.from_bytes, MissingBytes(), byte_order) + self.assertRaises( + ZeroDivisionError, int.from_bytes, RaisingBytes(), byte_order) + def test_access_to_nonexistent_digit_0(self): # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that # ob_digit[0] was being incorrectly accessed for instances of a diff -Nru python3.10-3.10.7/Lib/test/test_mailcap.py python3.10-3.10.12/Lib/test/test_mailcap.py --- python3.10-3.10.7/Lib/test/test_mailcap.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_mailcap.py 2023-06-06 22:30:33.000000000 +0000 @@ -123,7 +123,8 @@ (["", "audio/*", "foo.txt"], ""), (["echo foo", "audio/*", "foo.txt"], "echo foo"), (["echo %s", "audio/*", "foo.txt"], "echo foo.txt"), - (["echo %t", "audio/*", "foo.txt"], "echo audio/*"), + (["echo %t", "audio/*", "foo.txt"], None), + (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"), (["echo \\%t", "audio/*", "foo.txt"], "echo %t"), (["echo foo", "audio/*", "foo.txt", plist], "echo foo"), (["echo %{total}", "audio/*", "foo.txt", plist], "echo 3") @@ -207,7 +208,10 @@ ('"An audio fragment"', audio_basic_entry)), ([c, "audio/*"], {"filename": fname}, - ("/usr/local/bin/showaudio audio/*", audio_entry)), + (None, None)), + ([c, "audio/wav"], + {"filename": fname}, + ("/usr/local/bin/showaudio audio/wav", audio_entry)), ([c, "message/external-body"], {"plist": plist}, ("showexternal /dev/null default john python.org /tmp foo bar", message_entry)) diff -Nru python3.10-3.10.7/Lib/test/test_math.py python3.10-3.10.12/Lib/test/test_math.py --- python3.10-3.10.7/Lib/test/test_math.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_math.py 2023-06-06 22:30:33.000000000 +0000 @@ -979,6 +979,11 @@ self.assertEqual(math.dist(p, q), 5*scale) self.assertEqual(math.dist(q, p), 5*scale) + def test_math_dist_leak(self): + # gh-98897: Check for error handling does not leak memory + with self.assertRaises(ValueError): + math.dist([1, 2], [3, 4, 5]) + def testIsqrt(self): # Test a variety of inputs, large and small. test_values = ( diff -Nru python3.10-3.10.7/Lib/test/_test_multiprocessing.py python3.10-3.10.12/Lib/test/_test_multiprocessing.py --- python3.10-3.10.7/Lib/test/_test_multiprocessing.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/_test_multiprocessing.py 2023-06-06 22:30:33.000000000 +0000 @@ -5377,6 +5377,14 @@ self.assertTrue(is_resource_tracker_reused) + def test_too_long_name_resource(self): + # gh-96819: Resource names that will make the length of a write to a pipe + # greater than PIPE_BUF are not allowed + rtype = "shared_memory" + too_long_name_resource = "a" * (512 - len(rtype)) + with self.assertRaises(ValueError): + resource_tracker.register(too_long_name_resource, rtype) + class TestSimpleQueue(unittest.TestCase): @@ -5974,5 +5982,5 @@ class SemLock(_multiprocessing.SemLock): pass name = f'test_semlock_subclass-{os.getpid()}' - s = SemLock(1, 0, 10, name, 0) + s = SemLock(1, 0, 10, name, False) _multiprocessing.sem_unlink(name) diff -Nru python3.10-3.10.7/Lib/test/test_os.py python3.10-3.10.12/Lib/test/test_os.py --- python3.10-3.10.7/Lib/test/test_os.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_os.py 2023-06-06 22:30:33.000000000 +0000 @@ -2143,6 +2143,22 @@ def test_dup2(self): self.check(os.dup2, 20) + @unittest.skipUnless(hasattr(os, 'dup2'), 'test needs os.dup2()') + def test_dup2_negative_fd(self): + valid_fd = os.open(__file__, os.O_RDONLY) + self.addCleanup(os.close, valid_fd) + fds = [ + valid_fd, + -1, + -2**31, + ] + for fd, fd2 in itertools.product(fds, repeat=2): + if fd != fd2: + with self.subTest(fd=fd, fd2=fd2): + with self.assertRaises(OSError) as ctx: + os.dup2(fd, fd2) + self.assertEqual(ctx.exception.errno, errno.EBADF) + @unittest.skipUnless(hasattr(os, 'fchmod'), 'test needs os.fchmod()') def test_fchmod(self): self.check(os.fchmod, 0) diff -Nru python3.10-3.10.7/Lib/test/test_pdb.py python3.10-3.10.12/Lib/test/test_pdb.py --- python3.10-3.10.7/Lib/test/test_pdb.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_pdb.py 2023-06-06 22:30:33.000000000 +0000 @@ -562,6 +562,156 @@ (Pdb) continue """ +def test_pdb_display_command(): + """Test display command + + >>> def test_function(): + ... a = 0 + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... a = 1 + ... a = 2 + ... a = 3 + ... a = 4 + + >>> with PdbTestInput([ # doctest: +ELLIPSIS + ... 'display a', + ... 'n', + ... 'display', + ... 'undisplay a', + ... 'n', + ... 'display a', + ... 'undisplay', + ... 'display a < 1', + ... 'n', + ... 'continue', + ... ]): + ... test_function() + > (4)test_function() + -> a = 1 + (Pdb) display a + display a: 0 + (Pdb) n + > (5)test_function() + -> a = 2 + display a: 1 [old: 0] + (Pdb) display + Currently displaying: + a: 1 + (Pdb) undisplay a + (Pdb) n + > (6)test_function() + -> a = 3 + (Pdb) display a + display a: 2 + (Pdb) undisplay + (Pdb) display a < 1 + display a < 1: False + (Pdb) n + > (7)test_function() + -> a = 4 + (Pdb) continue + """ + +def test_pdb_alias_command(): + """Test alias command + + >>> class A: + ... def __init__(self): + ... self.attr1 = 10 + ... self.attr2 = 'str' + ... def method(self): + ... pass + + >>> def test_function(): + ... o = A() + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... o.method() + + >>> with PdbTestInput([ # doctest: +ELLIPSIS + ... 'alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")', + ... 'alias ps pi self', + ... 'pi o', + ... 's', + ... 'ps', + ... 'continue', + ... ]): + ... test_function() + > (4)test_function() + -> o.method() + (Pdb) alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}") + (Pdb) alias ps pi self + (Pdb) pi o + o.attr1 = 10 + o.attr2 = str + (Pdb) s + --Call-- + > (5)method() + -> def method(self): + (Pdb) ps + self.attr1 = 10 + self.attr2 = str + (Pdb) continue + """ + +def test_pdb_where_command(): + """Test where command + + >>> def g(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> def f(): + ... g(); + + >>> def test_function(): + ... f() + + >>> with PdbTestInput([ # doctest: +ELLIPSIS + ... 'w', + ... 'where', + ... 'u', + ... 'w', + ... 'continue', + ... ]): + ... test_function() + --Return-- + > (2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) w + ... + (8)() + -> test_function() + (2)test_function() + -> f() + (2)f() + -> g(); + > (2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) where + ... + (8)() + -> test_function() + (2)test_function() + -> f() + (2)f() + -> g(); + > (2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) u + > (2)f() + -> g(); + (Pdb) w + ... + (8)() + -> test_function() + (2)test_function() + -> f() + > (2)f() + -> g(); + (2)g()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) continue + """ + def test_post_mortem(): """Test post mortem traceback debugging. @@ -1351,6 +1501,35 @@ 4 """ +def test_pdb_issue_gh_101673(): + """See GH-101673 + + Make sure ll won't revert local variable assignment + + >>> def test_function(): + ... a = 1 + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... '!a = 2', + ... 'll', + ... 'p a', + ... 'continue' + ... ]): + ... test_function() + --Return-- + > (3)test_function()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) !a = 2 + (Pdb) ll + 1 def test_function(): + 2 a = 1 + 3 -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) p a + 2 + (Pdb) continue + """ + class PdbTestCase(unittest.TestCase): def tearDown(self): @@ -1915,6 +2094,52 @@ self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected) + def test_gh_93696_frozen_list(self): + frozen_src = """ + def func(): + x = "Sentinel string for gh-93696" + print(x) + """ + host_program = """ + import os + import sys + + def _create_fake_frozen_module(): + with open('gh93696.py') as f: + src = f.read() + + # this function has a co_filename as if it were in a frozen module + dummy_mod = compile(src, "", "exec") + func_code = dummy_mod.co_consts[0] + + mod = type(sys)("gh93696") + mod.func = type(lambda: None)(func_code, mod.__dict__) + mod.__file__ = 'gh93696.py' + + return mod + + mod = _create_fake_frozen_module() + mod.func() + """ + commands = """ + break 20 + continue + step + list + quit + """ + with open('gh93696.py', 'w') as f: + f.write(textwrap.dedent(frozen_src)) + + with open('gh93696_host.py', 'w') as f: + f.write(textwrap.dedent(host_program)) + + self.addCleanup(os_helper.unlink, 'gh93696.py') + self.addCleanup(os_helper.unlink, 'gh93696_host.py') + stdout, stderr = self._run_pdb(["gh93696_host.py"], commands) + # verify that pdb found the source of the "frozen" function + self.assertIn('x = "Sentinel string for gh-93696"', stdout, "Sentinel statement not found") + class ChecklineTests(unittest.TestCase): def setUp(self): linecache.clearcache() # Pdb.checkline() uses linecache.getline() diff -Nru python3.10-3.10.7/Lib/test/test_platform.py python3.10-3.10.12/Lib/test/test_platform.py --- python3.10-3.10.7/Lib/test/test_platform.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_platform.py 2023-06-06 22:30:33.000000000 +0000 @@ -268,6 +268,14 @@ self.assertEqual(res[:], expected) self.assertEqual(res[:5], expected[:5]) + def test_uname_fields(self): + self.assertIn('processor', platform.uname()._fields) + + def test_uname_asdict(self): + res = platform.uname()._asdict() + self.assertEqual(len(res), 6) + self.assertIn('processor', res) + @unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used") def test_uname_processor(self): """ diff -Nru python3.10-3.10.7/Lib/test/test_posixpath.py python3.10-3.10.12/Lib/test/test_posixpath.py --- python3.10-3.10.7/Lib/test/test_posixpath.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_posixpath.py 2023-06-06 22:30:33.000000000 +0000 @@ -178,6 +178,8 @@ def test_ismount(self): self.assertIs(posixpath.ismount("/"), True) self.assertIs(posixpath.ismount(b"/"), True) + self.assertIs(posixpath.ismount(FakePath("/")), True) + self.assertIs(posixpath.ismount(FakePath(b"/")), True) def test_ismount_non_existent(self): # Non-existent mountpoint. diff -Nru python3.10-3.10.7/Lib/test/test_posix.py python3.10-3.10.12/Lib/test/test_posix.py --- python3.10-3.10.7/Lib/test/test_posix.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_posix.py 2023-06-06 22:30:33.000000000 +0000 @@ -2066,6 +2066,28 @@ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"): os.mkdir("dir", dir_fd=0) + def test_mkfifo(self): + self._verify_available("HAVE_MKFIFOAT") + if self.mac_ver >= (13, 0): + self.assertIn("HAVE_MKFIFOAT", posix._have_functions) + + else: + self.assertNotIn("HAVE_MKFIFOAT", posix._have_functions) + + with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"): + os.mkfifo("path", dir_fd=0) + + def test_mknod(self): + self._verify_available("HAVE_MKNODAT") + if self.mac_ver >= (13, 0): + self.assertIn("HAVE_MKNODAT", posix._have_functions) + + else: + self.assertNotIn("HAVE_MKNODAT", posix._have_functions) + + with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"): + os.mknod("path", dir_fd=0) + def test_rename_replace(self): self._verify_available("HAVE_RENAMEAT") if self.mac_ver >= (10, 10): diff -Nru python3.10-3.10.7/Lib/test/test_pow.py python3.10-3.10.12/Lib/test/test_pow.py --- python3.10-3.10.7/Lib/test/test_pow.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_pow.py 2023-06-06 22:30:33.000000000 +0000 @@ -19,12 +19,11 @@ self.assertEqual(pow(2, i), pow2) if i != 30 : pow2 = pow2*2 - for othertype in (int,): - for i in list(range(-10, 0)) + list(range(1, 10)): - ii = type(i) - for j in range(1, 11): - jj = -othertype(j) - pow(ii, jj) + for i in list(range(-10, 0)) + list(range(1, 10)): + ii = type(i) + inv = pow(ii, -1) # inverse of ii + for jj in range(-10, 0): + self.assertAlmostEqual(pow(ii, jj), pow(inv, -jj)) for othertype in int, float: for i in range(1, 100): diff -Nru python3.10-3.10.7/Lib/test/test_property.py python3.10-3.10.12/Lib/test/test_property.py --- python3.10-3.10.7/Lib/test/test_property.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_property.py 2023-06-06 22:30:33.000000000 +0000 @@ -214,6 +214,23 @@ ): p.__set_name__(*([0] * i)) + def test_property_setname_on_property_subclass(self): + # https://github.com/python/cpython/issues/100942 + # Copy was setting the name field without first + # verifying that the copy was an actual property + # instance. As a result, the code below was + # causing a segfault. + + class pro(property): + def __new__(typ, *args, **kwargs): + return "abcdef" + + class A: + pass + + p = property.__new__(pro) + p.__set_name__(A, 1) + np = p.getter(lambda self: 1) # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): diff -Nru python3.10-3.10.7/Lib/test/test_re.py python3.10-3.10.12/Lib/test/test_re.py --- python3.10-3.10.7/Lib/test/test_re.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_re.py 2023-06-06 22:30:33.000000000 +0000 @@ -578,6 +578,11 @@ self.checkPatternError(r'()(?(2)a)', "invalid group reference 2", 5) + def test_re_groupref_exists_validation_bug(self): + for i in range(256): + with self.subTest(code=i): + re.compile(r'()(?(1)\x%02x?)' % i) + def test_re_groupref_overflow(self): from sre_constants import MAXGROUPS self.checkTemplateError('()', r'\g<%s>' % MAXGROUPS, 'xx', diff -Nru python3.10-3.10.7/Lib/test/test_sched.py python3.10-3.10.12/Lib/test/test_sched.py --- python3.10-3.10.7/Lib/test/test_sched.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_sched.py 2023-06-06 22:30:33.000000000 +0000 @@ -91,10 +91,23 @@ l = [] fun = lambda x: l.append(x) scheduler = sched.scheduler(time.time, time.sleep) - for priority in [1, 2, 3, 4, 5]: - z = scheduler.enterabs(0.01, priority, fun, (priority,)) - scheduler.run() - self.assertEqual(l, [1, 2, 3, 4, 5]) + + cases = [ + ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5]), + ([5, 4, 3, 2, 1], [1, 2, 3, 4, 5]), + ([2, 5, 3, 1, 4], [1, 2, 3, 4, 5]), + ([1, 2, 3, 2, 1], [1, 1, 2, 2, 3]), + ] + for priorities, expected in cases: + with self.subTest(priorities=priorities, expected=expected): + for priority in priorities: + scheduler.enterabs(0.01, priority, fun, (priority,)) + scheduler.run() + self.assertEqual(l, expected) + + # Cleanup: + self.assertTrue(scheduler.empty()) + l.clear() def test_cancel(self): l = [] diff -Nru python3.10-3.10.7/Lib/test/test_shutil.py python3.10-3.10.12/Lib/test/test_shutil.py --- python3.10-3.10.7/Lib/test/test_shutil.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_shutil.py 2023-06-06 22:30:33.000000000 +0000 @@ -32,6 +32,7 @@ from test import support from test.support import os_helper from test.support.os_helper import TESTFN, FakePath +from test.support import warnings_helper TESTFN2 = TESTFN + "2" TESTFN_SRC = TESTFN + "_SRC" @@ -731,18 +732,25 @@ @os_helper.skip_unless_symlink def test_copytree_dangling_symlinks(self): - # a dangling symlink raises an error at the end src_dir = self.mkdtemp() + valid_file = os.path.join(src_dir, 'test.txt') + write_file(valid_file, 'abc') + dir_a = os.path.join(src_dir, 'dir_a') + os.mkdir(dir_a) + for d in src_dir, dir_a: + os.symlink('IDONTEXIST', os.path.join(d, 'broken')) + os.symlink(valid_file, os.path.join(d, 'valid')) + + # A dangling symlink should raise an error. dst_dir = os.path.join(self.mkdtemp(), 'destination') - os.symlink('IDONTEXIST', os.path.join(src_dir, 'test.txt')) - os.mkdir(os.path.join(src_dir, 'test_dir')) - write_file((src_dir, 'test_dir', 'test.txt'), '456') self.assertRaises(Error, shutil.copytree, src_dir, dst_dir) - # a dangling symlink is ignored with the proper flag + # Dangling symlinks should be ignored with the proper flag. dst_dir = os.path.join(self.mkdtemp(), 'destination2') shutil.copytree(src_dir, dst_dir, ignore_dangling_symlinks=True) - self.assertNotIn('test.txt', os.listdir(dst_dir)) + for root, dirs, files in os.walk(dst_dir): + self.assertNotIn('broken', files) + self.assertIn('valid', files) # a dangling symlink is copied if symlinks=True dst_dir = os.path.join(self.mkdtemp(), 'destination3') @@ -1603,12 +1611,14 @@ ### shutil.unpack_archive - def check_unpack_archive(self, format): - self.check_unpack_archive_with_converter(format, lambda path: path) - self.check_unpack_archive_with_converter(format, pathlib.Path) - self.check_unpack_archive_with_converter(format, FakePath) + def check_unpack_archive(self, format, **kwargs): + self.check_unpack_archive_with_converter( + format, lambda path: path, **kwargs) + self.check_unpack_archive_with_converter( + format, pathlib.Path, **kwargs) + self.check_unpack_archive_with_converter(format, FakePath, **kwargs) - def check_unpack_archive_with_converter(self, format, converter): + def check_unpack_archive_with_converter(self, format, converter, **kwargs): root_dir, base_dir = self._create_files() expected = rlistdir(root_dir) expected.remove('outer') @@ -1618,36 +1628,47 @@ # let's try to unpack it now tmpdir2 = self.mkdtemp() - unpack_archive(converter(filename), converter(tmpdir2)) + unpack_archive(converter(filename), converter(tmpdir2), **kwargs) self.assertEqual(rlistdir(tmpdir2), expected) # and again, this time with the format specified tmpdir3 = self.mkdtemp() - unpack_archive(converter(filename), converter(tmpdir3), format=format) + unpack_archive(converter(filename), converter(tmpdir3), format=format, + **kwargs) self.assertEqual(rlistdir(tmpdir3), expected) - self.assertRaises(shutil.ReadError, unpack_archive, converter(TESTFN)) - self.assertRaises(ValueError, unpack_archive, converter(TESTFN), format='xxx') + with self.assertRaises(shutil.ReadError): + unpack_archive(converter(TESTFN), **kwargs) + with self.assertRaises(ValueError): + unpack_archive(converter(TESTFN), format='xxx', **kwargs) + + def check_unpack_tarball(self, format): + self.check_unpack_archive(format, filter='fully_trusted') + self.check_unpack_archive(format, filter='data') + with warnings_helper.check_no_warnings(self): + self.check_unpack_archive(format) def test_unpack_archive_tar(self): - self.check_unpack_archive('tar') + self.check_unpack_tarball('tar') @support.requires_zlib() def test_unpack_archive_gztar(self): - self.check_unpack_archive('gztar') + self.check_unpack_tarball('gztar') @support.requires_bz2() def test_unpack_archive_bztar(self): - self.check_unpack_archive('bztar') + self.check_unpack_tarball('bztar') @support.requires_lzma() @unittest.skipIf(AIX and not _maxdataOK(), "AIX MAXDATA must be 0x20000000 or larger") def test_unpack_archive_xztar(self): - self.check_unpack_archive('xztar') + self.check_unpack_tarball('xztar') @support.requires_zlib() def test_unpack_archive_zip(self): self.check_unpack_archive('zip') + with self.assertRaises(TypeError): + self.check_unpack_archive('zip', filter='data') def test_unpack_registry(self): diff -Nru python3.10-3.10.7/Lib/test/test_signal.py python3.10-3.10.12/Lib/test/test_signal.py --- python3.10-3.10.7/Lib/test/test_signal.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_signal.py 2023-06-06 22:30:33.000000000 +0000 @@ -1349,6 +1349,21 @@ signal.raise_signal(signal.SIGINT) self.assertTrue(is_ok) + def test__thread_interrupt_main(self): + # See https://github.com/python/cpython/issues/102397 + code = """if 1: + import _thread + class Foo(): + def __del__(self): + _thread.interrupt_main() + + x = Foo() + """ + + rc, out, err = assert_python_ok('-c', code) + self.assertIn(b'OSError: Signal 2 ignored due to race condition', err) + + class PidfdSignalTest(unittest.TestCase): diff -Nru python3.10-3.10.7/Lib/test/test_slice.py python3.10-3.10.12/Lib/test/test_slice.py --- python3.10-3.10.7/Lib/test/test_slice.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_slice.py 2023-06-06 22:30:33.000000000 +0000 @@ -5,6 +5,7 @@ import sys import unittest import weakref +import copy from pickle import loads, dumps from test import support @@ -235,13 +236,50 @@ self.assertEqual(tmp, [(slice(1, 2), 42)]) def test_pickle(self): + import pickle + s = slice(10, 20, 3) - for protocol in (0,1,2): + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): t = loads(dumps(s, protocol)) self.assertEqual(s, t) self.assertEqual(s.indices(15), t.indices(15)) self.assertNotEqual(id(s), id(t)) + def test_copy(self): + s = slice(1, 10) + c = copy.copy(s) + self.assertIs(s, c) + + s = slice(1, 10, 2) + c = copy.copy(s) + self.assertIs(s, c) + + # Corner case for mutable indices: + s = slice([1, 2], [3, 4], [5, 6]) + c = copy.copy(s) + self.assertIs(s, c) + self.assertIs(s.start, c.start) + self.assertIs(s.stop, c.stop) + self.assertIs(s.step, c.step) + + def test_deepcopy(self): + s = slice(1, 10) + c = copy.deepcopy(s) + self.assertEqual(s, c) + + s = slice(1, 10, 2) + c = copy.deepcopy(s) + self.assertEqual(s, c) + + # Corner case for mutable indices: + s = slice([1, 2], [3, 4], [5, 6]) + c = copy.deepcopy(s) + self.assertIsNot(s, c) + self.assertEqual(s, c) + self.assertIsNot(s.start, c.start) + self.assertIsNot(s.stop, c.stop) + self.assertIsNot(s.step, c.step) + def test_cycle(self): class myobj(): pass o = myobj() diff -Nru python3.10-3.10.7/Lib/test/test_socket.py python3.10-3.10.12/Lib/test/test_socket.py --- python3.10-3.10.7/Lib/test/test_socket.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_socket.py 2023-06-06 22:30:33.000000000 +0000 @@ -1743,6 +1743,10 @@ ) self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0)) + def test_getfqdn_filter_localhost(self): + self.assertEqual(socket.getfqdn(), socket.getfqdn("0.0.0.0")) + self.assertEqual(socket.getfqdn(), socket.getfqdn("::")) + @unittest.skipUnless(socket_helper.IPV6_ENABLED, 'IPv6 required for this test.') @unittest.skipIf(sys.platform == 'win32', 'does not work on Windows') @unittest.skipIf(AIX, 'Symbolic scope id does not work') diff -Nru python3.10-3.10.7/Lib/test/test_source_encoding.py python3.10-3.10.12/Lib/test/test_source_encoding.py --- python3.10-3.10.7/Lib/test/test_source_encoding.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_source_encoding.py 2023-06-06 22:30:33.000000000 +0000 @@ -147,6 +147,18 @@ self.assertTrue(c.exception.args[0].startswith(expected), msg=c.exception.args[0]) + def test_file_parse_error_multiline(self): + # gh96611: + with open(TESTFN, "wb") as fd: + fd.write(b'print("""\n\xb1""")\n') + + try: + retcode, stdout, stderr = script_helper.assert_python_failure(TESTFN) + + self.assertGreater(retcode, 0) + self.assertIn(b"Non-UTF-8 code starting with '\\xb1'", stderr) + finally: + os.unlink(TESTFN) class AbstractSourceEncodingTest: diff -Nru python3.10-3.10.7/Lib/test/test_ssl.py python3.10-3.10.12/Lib/test/test_ssl.py --- python3.10-3.10.7/Lib/test/test_ssl.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_ssl.py 2023-06-06 22:30:33.000000000 +0000 @@ -155,7 +155,6 @@ OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0) OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0) -OP_IGNORE_UNEXPECTED_EOF = getattr(ssl, "OP_IGNORE_UNEXPECTED_EOF", 0) # Ubuntu has patched OpenSSL and changed behavior of security level 2 # see https://bugs.python.org/issue41561#msg389003 @@ -1199,8 +1198,7 @@ # SSLContext also enables these by default default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE | OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE | - OP_ENABLE_MIDDLEBOX_COMPAT | - OP_IGNORE_UNEXPECTED_EOF) + OP_ENABLE_MIDDLEBOX_COMPAT) self.assertEqual(default, ctx.options) with warnings_helper.check_warnings(): ctx.options |= ssl.OP_NO_TLSv1 @@ -2326,13 +2324,13 @@ self.assertIs(sslobj._sslobj.owner, sslobj) self.assertIsNone(sslobj.cipher()) self.assertIsNone(sslobj.version()) - self.assertIsNotNone(sslobj.shared_ciphers()) + self.assertIsNone(sslobj.shared_ciphers()) self.assertRaises(ValueError, sslobj.getpeercert) if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES: self.assertIsNone(sslobj.get_channel_binding('tls-unique')) self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake) self.assertTrue(sslobj.cipher()) - self.assertIsNotNone(sslobj.shared_ciphers()) + self.assertIsNone(sslobj.shared_ciphers()) self.assertIsNotNone(sslobj.version()) self.assertTrue(sslobj.getpeercert()) if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES: @@ -2362,6 +2360,20 @@ self.assertEqual(buf, b'foo\n') self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap) + def test_transport_eof(self): + client_context, server_context, hostname = testing_context() + with socket.socket(socket.AF_INET) as sock: + sock.connect(self.server_addr) + incoming = ssl.MemoryBIO() + outgoing = ssl.MemoryBIO() + sslobj = client_context.wrap_bio(incoming, outgoing, + server_hostname=hostname) + self.ssl_io_loop(sock, incoming, outgoing, sslobj.do_handshake) + + # Simulate EOF from the transport. + incoming.write_eof() + self.assertRaises(ssl.SSLEOFError, sslobj.read) + @support.requires_resource('network') class NetworkedTests(unittest.TestCase): @@ -4310,7 +4322,7 @@ def test_shared_ciphers(self): client_context, server_context, hostname = testing_context() client_context.set_ciphers("AES128:AES256") - server_context.set_ciphers("AES256") + server_context.set_ciphers("AES256:eNULL") expected_algs = [ "AES256", "AES-256", # TLS 1.3 ciphers are always enabled diff -Nru python3.10-3.10.7/Lib/test/test_statistics.py python3.10-3.10.12/Lib/test/test_statistics.py --- python3.10-3.10.7/Lib/test/test_statistics.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_statistics.py 2023-06-06 22:30:33.000000000 +0000 @@ -2880,14 +2880,19 @@ nd = NormalDist(100, 15) self.assertNotEqual(nd, lnd) - def test_pickle_and_copy(self): + def test_copy(self): nd = self.module.NormalDist(37.5, 5.625) nd1 = copy.copy(nd) self.assertEqual(nd, nd1) nd2 = copy.deepcopy(nd) self.assertEqual(nd, nd2) - nd3 = pickle.loads(pickle.dumps(nd)) - self.assertEqual(nd, nd3) + + def test_pickle(self): + nd = self.module.NormalDist(37.5, 5.625) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(proto=proto): + pickled = pickle.loads(pickle.dumps(nd, protocol=proto)) + self.assertEqual(nd, pickled) def test_hashability(self): ND = self.module.NormalDist diff -Nru python3.10-3.10.7/Lib/test/test_string_literals.py python3.10-3.10.12/Lib/test/test_string_literals.py --- python3.10-3.10.7/Lib/test/test_string_literals.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_string_literals.py 2023-06-06 22:30:33.000000000 +0000 @@ -213,6 +213,13 @@ self.assertRaises(SyntaxError, eval, """ bu'' """) self.assertRaises(SyntaxError, eval, """ ub'' """) + def test_uppercase_prefixes(self): + self.assertEqual(eval(""" B'x' """), b'x') + self.assertEqual(eval(r""" R'\x01' """), r'\x01') + self.assertEqual(eval(r""" BR'\x01' """), br'\x01') + self.assertEqual(eval(""" F'{1+1}' """), f'{1+1}') + self.assertEqual(eval(r""" U'\U0001d120' """), u'\U0001d120') + def check_encoding(self, encoding, extra=""): modname = "xx_" + encoding.replace("-", "_") fn = os.path.join(self.tmpdir, modname + ".py") diff -Nru python3.10-3.10.7/Lib/test/test_structmembers.py python3.10-3.10.12/Lib/test/test_structmembers.py --- python3.10-3.10.7/Lib/test/test_structmembers.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_structmembers.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,145 +0,0 @@ -import unittest -from test.support import import_helper -from test.support import warnings_helper - -# Skip this test if the _testcapi module isn't available. -import_helper.import_module('_testcapi') -from _testcapi import _test_structmembersType, \ - CHAR_MAX, CHAR_MIN, UCHAR_MAX, \ - SHRT_MAX, SHRT_MIN, USHRT_MAX, \ - INT_MAX, INT_MIN, UINT_MAX, \ - LONG_MAX, LONG_MIN, ULONG_MAX, \ - LLONG_MAX, LLONG_MIN, ULLONG_MAX, \ - PY_SSIZE_T_MAX, PY_SSIZE_T_MIN - -ts=_test_structmembersType(False, # T_BOOL - 1, # T_BYTE - 2, # T_UBYTE - 3, # T_SHORT - 4, # T_USHORT - 5, # T_INT - 6, # T_UINT - 7, # T_LONG - 8, # T_ULONG - 23, # T_PYSSIZET - 9.99999,# T_FLOAT - 10.1010101010, # T_DOUBLE - "hi" # T_STRING_INPLACE - ) - -class ReadWriteTests(unittest.TestCase): - - def test_bool(self): - ts.T_BOOL = True - self.assertEqual(ts.T_BOOL, True) - ts.T_BOOL = False - self.assertEqual(ts.T_BOOL, False) - self.assertRaises(TypeError, setattr, ts, 'T_BOOL', 1) - - def test_byte(self): - ts.T_BYTE = CHAR_MAX - self.assertEqual(ts.T_BYTE, CHAR_MAX) - ts.T_BYTE = CHAR_MIN - self.assertEqual(ts.T_BYTE, CHAR_MIN) - ts.T_UBYTE = UCHAR_MAX - self.assertEqual(ts.T_UBYTE, UCHAR_MAX) - - def test_short(self): - ts.T_SHORT = SHRT_MAX - self.assertEqual(ts.T_SHORT, SHRT_MAX) - ts.T_SHORT = SHRT_MIN - self.assertEqual(ts.T_SHORT, SHRT_MIN) - ts.T_USHORT = USHRT_MAX - self.assertEqual(ts.T_USHORT, USHRT_MAX) - - def test_int(self): - ts.T_INT = INT_MAX - self.assertEqual(ts.T_INT, INT_MAX) - ts.T_INT = INT_MIN - self.assertEqual(ts.T_INT, INT_MIN) - ts.T_UINT = UINT_MAX - self.assertEqual(ts.T_UINT, UINT_MAX) - - def test_long(self): - ts.T_LONG = LONG_MAX - self.assertEqual(ts.T_LONG, LONG_MAX) - ts.T_LONG = LONG_MIN - self.assertEqual(ts.T_LONG, LONG_MIN) - ts.T_ULONG = ULONG_MAX - self.assertEqual(ts.T_ULONG, ULONG_MAX) - - def test_py_ssize_t(self): - ts.T_PYSSIZET = PY_SSIZE_T_MAX - self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MAX) - ts.T_PYSSIZET = PY_SSIZE_T_MIN - self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MIN) - - @unittest.skipUnless(hasattr(ts, "T_LONGLONG"), "long long not present") - def test_longlong(self): - ts.T_LONGLONG = LLONG_MAX - self.assertEqual(ts.T_LONGLONG, LLONG_MAX) - ts.T_LONGLONG = LLONG_MIN - self.assertEqual(ts.T_LONGLONG, LLONG_MIN) - - ts.T_ULONGLONG = ULLONG_MAX - self.assertEqual(ts.T_ULONGLONG, ULLONG_MAX) - - ## make sure these will accept a plain int as well as a long - ts.T_LONGLONG = 3 - self.assertEqual(ts.T_LONGLONG, 3) - ts.T_ULONGLONG = 4 - self.assertEqual(ts.T_ULONGLONG, 4) - - def test_bad_assignments(self): - integer_attributes = [ - 'T_BOOL', - 'T_BYTE', 'T_UBYTE', - 'T_SHORT', 'T_USHORT', - 'T_INT', 'T_UINT', - 'T_LONG', 'T_ULONG', - 'T_PYSSIZET' - ] - if hasattr(ts, 'T_LONGLONG'): - integer_attributes.extend(['T_LONGLONG', 'T_ULONGLONG']) - - # issue8014: this produced 'bad argument to internal function' - # internal error - for nonint in None, 3.2j, "full of eels", {}, []: - for attr in integer_attributes: - self.assertRaises(TypeError, setattr, ts, attr, nonint) - - def test_inplace_string(self): - self.assertEqual(ts.T_STRING_INPLACE, "hi") - self.assertRaises(TypeError, setattr, ts, "T_STRING_INPLACE", "s") - self.assertRaises(TypeError, delattr, ts, "T_STRING_INPLACE") - - -class TestWarnings(unittest.TestCase): - - def test_byte_max(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_BYTE = CHAR_MAX+1 - - def test_byte_min(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_BYTE = CHAR_MIN-1 - - def test_ubyte_max(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_UBYTE = UCHAR_MAX+1 - - def test_short_max(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_SHORT = SHRT_MAX+1 - - def test_short_min(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_SHORT = SHRT_MIN-1 - - def test_ushort_max(self): - with warnings_helper.check_warnings(('', RuntimeWarning)): - ts.T_USHORT = USHRT_MAX+1 - - -if __name__ == "__main__": - unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_subprocess.py python3.10-3.10.12/Lib/test/test_subprocess.py --- python3.10-3.10.7/Lib/test/test_subprocess.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_subprocess.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,6 +1,7 @@ import unittest from unittest import mock from test import support +from test.support import check_sanitizer from test.support import import_helper from test.support import os_helper from test.support import warnings_helper @@ -227,6 +228,12 @@ input=None, universal_newlines=True) self.assertNotIn('XX', output) + def test_check_output_input_none_encoding_errors(self): + output = subprocess.check_output( + [sys.executable, "-c", "print('foo')"], + input=None, encoding='utf-8', errors='ignore') + self.assertIn('foo', output) + def test_check_output_stdout_arg(self): # check_output() refuses to accept 'stdout' argument with self.assertRaises(ValueError) as c: @@ -701,7 +708,7 @@ os.close(test_pipe_w) pipesize = pipesize_default // 2 if pipesize < 512: # the POSIX minimum - raise unittest.SkitTest( + raise unittest.SkipTest( 'default pipesize too small to perform test.') p = subprocess.Popen( [sys.executable, "-c", @@ -768,6 +775,8 @@ @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1, 'The Python shared library cannot be loaded ' 'with an empty environment.') + @unittest.skipIf(check_sanitizer(address=True), + 'AddressSanitizer adds to the environment.') def test_empty_env(self): """Verify that env={} is as empty as possible.""" diff -Nru python3.10-3.10.7/Lib/test/test_syntax.py python3.10-3.10.12/Lib/test/test_syntax.py --- python3.10-3.10.7/Lib/test/test_syntax.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_syntax.py 2023-06-06 22:30:33.000000000 +0000 @@ -1410,9 +1410,6 @@ """ self._check_error(source, "parameter and nonlocal", lineno=3) - def test_break_outside_loop(self): - self._check_error("break", "outside loop") - def test_yield_outside_function(self): self._check_error("if 0: yield", "outside function") self._check_error("if 0: yield\nelse: x=1", "outside function") @@ -1441,20 +1438,27 @@ "outside function") def test_break_outside_loop(self): - self._check_error("if 0: break", "outside loop") - self._check_error("if 0: break\nelse: x=1", "outside loop") - self._check_error("if 1: pass\nelse: break", "outside loop") - self._check_error("class C:\n if 0: break", "outside loop") + msg = "outside loop" + self._check_error("break", msg, lineno=1) + self._check_error("if 0: break", msg, lineno=1) + self._check_error("if 0: break\nelse: x=1", msg, lineno=1) + self._check_error("if 1: pass\nelse: break", msg, lineno=2) + self._check_error("class C:\n if 0: break", msg, lineno=2) self._check_error("class C:\n if 1: pass\n else: break", - "outside loop") + msg, lineno=3) + self._check_error("with object() as obj:\n break", + msg, lineno=2) def test_continue_outside_loop(self): - self._check_error("if 0: continue", "not properly in loop") - self._check_error("if 0: continue\nelse: x=1", "not properly in loop") - self._check_error("if 1: pass\nelse: continue", "not properly in loop") - self._check_error("class C:\n if 0: continue", "not properly in loop") + msg = "not properly in loop" + self._check_error("if 0: continue", msg, lineno=1) + self._check_error("if 0: continue\nelse: x=1", msg, lineno=1) + self._check_error("if 1: pass\nelse: continue", msg, lineno=2) + self._check_error("class C:\n if 0: continue", msg, lineno=2) self._check_error("class C:\n if 1: pass\n else: continue", - "not properly in loop") + msg, lineno=3) + self._check_error("with object() as obj:\n continue", + msg, lineno=2) def test_unexpected_indent(self): self._check_error("foo()\n bar()\n", "unexpected indent", @@ -1587,6 +1591,22 @@ for paren in ")]}": self._check_error(paren + "1 + 2", f"unmatched '\\{paren}'") + # Some more complex examples: + code = """\ +func( + a=["unclosed], # Need a quote in this comment: " + b=2, +) +""" + self._check_error(code, "parenthesis '\\)' does not match opening parenthesis '\\['") + + def test_error_string_literal(self): + + self._check_error("'blech", "unterminated string literal") + self._check_error('"blech', "unterminated string literal") + self._check_error("'''blech", "unterminated triple-quoted string literal") + self._check_error('"""blech', "unterminated triple-quoted string literal") + def test_match_call_does_not_raise_syntax_error(self): code = """ def match(x): diff -Nru python3.10-3.10.7/Lib/test/test_syslog.py python3.10-3.10.12/Lib/test/test_syslog.py --- python3.10-3.10.7/Lib/test/test_syslog.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_syslog.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,5 +1,9 @@ -from test.support import import_helper +from test.support import import_helper, threading_helper syslog = import_helper.import_module("syslog") #skip if not supported +from test import support +import sys +import threading +import time import unittest # XXX(nnorwitz): This test sucks. I don't know of a platform independent way @@ -8,6 +12,9 @@ class Test(unittest.TestCase): + def tearDown(self): + syslog.closelog() + def test_openlog(self): syslog.openlog('python') # Issue #6697. @@ -18,22 +25,58 @@ syslog.syslog('test message from python test_syslog') syslog.syslog(syslog.LOG_ERR, 'test error from python test_syslog') + def test_syslog_implicit_open(self): + syslog.closelog() # Make sure log is closed + syslog.syslog('test message from python test_syslog') + syslog.syslog(syslog.LOG_ERR, 'test error from python test_syslog') + def test_closelog(self): syslog.openlog('python') syslog.closelog() + syslog.closelog() # idempotent operation def test_setlogmask(self): - syslog.setlogmask(syslog.LOG_DEBUG) + mask = syslog.LOG_UPTO(syslog.LOG_WARNING) + oldmask = syslog.setlogmask(mask) + self.assertEqual(syslog.setlogmask(0), mask) + self.assertEqual(syslog.setlogmask(oldmask), mask) def test_log_mask(self): - syslog.LOG_MASK(syslog.LOG_INFO) - - def test_log_upto(self): - syslog.LOG_UPTO(syslog.LOG_INFO) + mask = syslog.LOG_UPTO(syslog.LOG_WARNING) + self.assertTrue(mask & syslog.LOG_MASK(syslog.LOG_WARNING)) + self.assertTrue(mask & syslog.LOG_MASK(syslog.LOG_ERR)) + self.assertFalse(mask & syslog.LOG_MASK(syslog.LOG_INFO)) def test_openlog_noargs(self): syslog.openlog() syslog.syslog('test message from python test_syslog') + def test_syslog_threaded(self): + start = threading.Event() + stop = False + def opener(): + start.wait(10) + i = 1 + while not stop: + syslog.openlog(f'python-test-{i}') # new string object + i += 1 + def logger(): + start.wait(10) + while not stop: + syslog.syslog('test message from python test_syslog') + + orig_si = sys.getswitchinterval() + support.setswitchinterval(1e-9) + try: + threads = [threading.Thread(target=opener)] + threads += [threading.Thread(target=logger) for k in range(10)] + with threading_helper.start_threads(threads): + start.set() + time.sleep(0.1) + stop = True + finally: + sys.setswitchinterval(orig_si) + + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_sys_settrace.py python3.10-3.10.12/Lib/test/test_sys_settrace.py --- python3.10-3.10.7/Lib/test/test_sys_settrace.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_sys_settrace.py 2023-06-06 22:30:33.000000000 +0000 @@ -1310,6 +1310,20 @@ finally: sys.settrace(existing) + def test_line_event_raises_before_opcode_event(self): + exception = ValueError("BOOM!") + def trace(frame, event, arg): + if event == "line": + raise exception + frame.f_trace_opcodes = True + return trace + def f(): + pass + with self.assertRaises(ValueError) as caught: + sys.settrace(trace) + f() + self.assertIs(caught.exception, exception) + # 'Jump' tests: assigning to frame.f_lineno within a trace function # moves the execution position - it's how debuggers implement a Jump diff -Nru python3.10-3.10.7/Lib/test/test_tarfile.py python3.10-3.10.12/Lib/test/test_tarfile.py --- python3.10-3.10.7/Lib/test/test_tarfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_tarfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -5,6 +5,10 @@ from contextlib import contextmanager from random import Random import pathlib +import shutil +import re +import warnings +import stat import unittest import unittest.mock @@ -13,6 +17,7 @@ from test import support from test.support import os_helper from test.support import script_helper +from test.support import warnings_helper # Check for our compression modules. try: @@ -108,7 +113,7 @@ "regular file extraction failed") def test_fileobj_readlines(self): - self.tar.extract("ustar/regtype", TEMPDIR) + self.tar.extract("ustar/regtype", TEMPDIR, filter='data') tarinfo = self.tar.getmember("ustar/regtype") with open(os.path.join(TEMPDIR, "ustar/regtype"), "r") as fobj1: lines1 = fobj1.readlines() @@ -126,7 +131,7 @@ "fileobj.readlines() failed") def test_fileobj_iter(self): - self.tar.extract("ustar/regtype", TEMPDIR) + self.tar.extract("ustar/regtype", TEMPDIR, filter='data') tarinfo = self.tar.getmember("ustar/regtype") with open(os.path.join(TEMPDIR, "ustar/regtype"), "r") as fobj1: lines1 = fobj1.readlines() @@ -136,7 +141,8 @@ "fileobj.__iter__() failed") def test_fileobj_seek(self): - self.tar.extract("ustar/regtype", TEMPDIR) + self.tar.extract("ustar/regtype", TEMPDIR, + filter='data') with open(os.path.join(TEMPDIR, "ustar/regtype"), "rb") as fobj: data = fobj.read() @@ -225,13 +231,19 @@ self.add_dir_and_getmember('bar') self.add_dir_and_getmember('a'*101) + @unittest.skipUnless(hasattr(os, "getuid") and hasattr(os, "getgid"), + "Missing getuid or getgid implementation") def add_dir_and_getmember(self, name): + def filter(tarinfo): + tarinfo.uid = tarinfo.gid = 100 + return tarinfo + with os_helper.temp_cwd(): with tarfile.open(tmpname, 'w') as tar: tar.format = tarfile.USTAR_FORMAT try: os.mkdir(name) - tar.add(name) + tar.add(name, filter=filter) finally: os.rmdir(name) with tarfile.open(tmpname) as tar: @@ -449,7 +461,7 @@ t = tar.next() with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): - tar.extract(t, TEMPDIR) + tar.extract(t, TEMPDIR, filter='data') with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"): tar.extractfile(t).read() @@ -604,16 +616,16 @@ def test_extract_hardlink(self): # Test hardlink extraction (e.g. bug #857297). with tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") as tar: - tar.extract("ustar/regtype", TEMPDIR) + tar.extract("ustar/regtype", TEMPDIR, filter='data') self.addCleanup(os_helper.unlink, os.path.join(TEMPDIR, "ustar/regtype")) - tar.extract("ustar/lnktype", TEMPDIR) + tar.extract("ustar/lnktype", TEMPDIR, filter='data') self.addCleanup(os_helper.unlink, os.path.join(TEMPDIR, "ustar/lnktype")) with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f: data = f.read() self.assertEqual(sha256sum(data), sha256_regtype) - tar.extract("ustar/symtype", TEMPDIR) + tar.extract("ustar/symtype", TEMPDIR, filter='data') self.addCleanup(os_helper.unlink, os.path.join(TEMPDIR, "ustar/symtype")) with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f: data = f.read() @@ -627,13 +639,14 @@ os.mkdir(DIR) try: directories = [t for t in tar if t.isdir()] - tar.extractall(DIR, directories) + tar.extractall(DIR, directories, filter='fully_trusted') for tarinfo in directories: path = os.path.join(DIR, tarinfo.name) if sys.platform != "win32": # Win32 has no support for fine grained permissions. self.assertEqual(tarinfo.mode & 0o777, - os.stat(path).st_mode & 0o777) + os.stat(path).st_mode & 0o777, + tarinfo.name) def format_mtime(mtime): if isinstance(mtime, float): return "{} ({})".format(mtime, mtime.hex()) @@ -656,7 +669,7 @@ try: with tarfile.open(tarname, encoding="iso8859-1") as tar: tarinfo = tar.getmember(dirtype) - tar.extract(tarinfo, path=DIR) + tar.extract(tarinfo, path=DIR, filter='fully_trusted') extracted = os.path.join(DIR, dirtype) self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime) if sys.platform != "win32": @@ -669,7 +682,7 @@ with os_helper.temp_dir(DIR), \ tarfile.open(tarname, encoding="iso8859-1") as tar: directories = [t for t in tar if t.isdir()] - tar.extractall(DIR, directories) + tar.extractall(DIR, directories, filter='fully_trusted') for tarinfo in directories: path = DIR / tarinfo.name self.assertEqual(os.path.getmtime(path), tarinfo.mtime) @@ -680,7 +693,7 @@ with os_helper.temp_dir(DIR), \ tarfile.open(tarname, encoding="iso8859-1") as tar: tarinfo = tar.getmember(dirtype) - tar.extract(tarinfo, path=DIR) + tar.extract(tarinfo, path=DIR, filter='fully_trusted') extracted = DIR / dirtype self.assertEqual(os.path.getmtime(extracted), tarinfo.mtime) @@ -1036,7 +1049,7 @@ # an all platforms, and after that a test that will work only on # platforms/filesystems that prove to support sparse files. def _test_sparse_file(self, name): - self.tar.extract(name, TEMPDIR) + self.tar.extract(name, TEMPDIR, filter='data') filename = os.path.join(TEMPDIR, name) with open(filename, "rb") as fobj: data = fobj.read() @@ -1403,7 +1416,8 @@ with tarfile.open(temparchive, errorlevel=2) as tar: # this should not raise OSError: [Errno 17] File exists try: - tar.extractall(path=tempdir) + tar.extractall(path=tempdir, + filter='fully_trusted') except OSError: self.fail("extractall failed with symlinked files") finally: @@ -2400,7 +2414,12 @@ 'PAX_NUMBER_FIELDS', 'stn', 'nts', 'nti', 'itn', 'calc_chksums', 'copyfileobj', 'filemode', 'EmptyHeaderError', 'TruncatedHeaderError', 'EOFHeaderError', 'InvalidHeaderError', - 'SubsequentHeaderError', 'ExFileObject', 'main'} + 'SubsequentHeaderError', 'ExFileObject', 'main', + "fully_trusted_filter", "data_filter", + "tar_filter", "FilterError", "AbsoluteLinkError", + "OutsideDestinationError", "SpecialFileError", "AbsolutePathError", + "LinkOutsideDestinationError", + } support.check__all__(self, tarfile, not_exported=not_exported) def test_useful_error_message_when_modules_missing(self): @@ -2435,6 +2454,15 @@ for tardata in files: tf.add(tardata, arcname=os.path.basename(tardata)) + def make_evil_tarfile(self, tar_name): + files = [support.findfile('tokenize_tests.txt')] + self.addCleanup(os_helper.unlink, tar_name) + with tarfile.open(tar_name, 'w') as tf: + benign = tarfile.TarInfo('benign') + tf.addfile(benign, fileobj=io.BytesIO(b'')) + evil = tarfile.TarInfo('../evil') + tf.addfile(evil, fileobj=io.BytesIO(b'')) + def test_bad_use(self): rc, out, err = self.tarfilecmd_failure() self.assertEqual(out, b'') @@ -2591,6 +2619,25 @@ finally: os_helper.rmtree(tarextdir) + def test_extract_command_filter(self): + self.make_evil_tarfile(tmpname) + # Make an inner directory, so the member named '../evil' + # is still extracted into `tarextdir` + destdir = os.path.join(tarextdir, 'dest') + os.mkdir(tarextdir) + try: + with os_helper.temp_cwd(destdir): + self.tarfilecmd_failure('-e', tmpname, + '-v', + '--filter', 'data') + out = self.tarfilecmd('-e', tmpname, + '-v', + '--filter', 'fully_trusted', + PYTHONIOENCODING='utf-8') + self.assertIn(b' file is extracted.', out) + finally: + os_helper.rmtree(tarextdir) + def test_extract_command_different_directory(self): self.make_simple_tarfile(tmpname) try: @@ -2674,7 +2721,7 @@ # symbolic or hard links tarfile tries to extract these types of members # as the regular files they point to. def _test_link_extraction(self, name): - self.tar.extract(name, TEMPDIR) + self.tar.extract(name, TEMPDIR, filter='fully_trusted') with open(os.path.join(TEMPDIR, name), "rb") as f: data = f.read() self.assertEqual(sha256sum(data), sha256_regtype) @@ -2806,8 +2853,10 @@ mock_chown): with self._setup_test(mock_geteuid) as (tarfl, filename_1, _, filename_2): - tarfl.extract(filename_1, TEMPDIR, numeric_owner=True) - tarfl.extract(filename_2 , TEMPDIR, numeric_owner=True) + tarfl.extract(filename_1, TEMPDIR, numeric_owner=True, + filter='fully_trusted') + tarfl.extract(filename_2 , TEMPDIR, numeric_owner=True, + filter='fully_trusted') # convert to filesystem paths f_filename_1 = os.path.join(TEMPDIR, filename_1) @@ -2825,7 +2874,8 @@ mock_chown): with self._setup_test(mock_geteuid) as (tarfl, filename_1, dirname_1, filename_2): - tarfl.extractall(TEMPDIR, numeric_owner=True) + tarfl.extractall(TEMPDIR, numeric_owner=True, + filter='fully_trusted') # convert to filesystem paths f_filename_1 = os.path.join(TEMPDIR, filename_1) @@ -2850,7 +2900,8 @@ def test_extract_without_numeric_owner(self, mock_geteuid, mock_chmod, mock_chown): with self._setup_test(mock_geteuid) as (tarfl, filename_1, _, _): - tarfl.extract(filename_1, TEMPDIR, numeric_owner=False) + tarfl.extract(filename_1, TEMPDIR, numeric_owner=False, + filter='fully_trusted') # convert to filesystem paths f_filename_1 = os.path.join(TEMPDIR, filename_1) @@ -2864,6 +2915,893 @@ tarfl.extract, filename_1, TEMPDIR, False, True) +class ReplaceTests(ReadTest, unittest.TestCase): + def test_replace_name(self): + member = self.tar.getmember('ustar/regtype') + replaced = member.replace(name='misc/other') + self.assertEqual(replaced.name, 'misc/other') + self.assertEqual(member.name, 'ustar/regtype') + self.assertEqual(self.tar.getmember('ustar/regtype').name, + 'ustar/regtype') + + def test_replace_deep(self): + member = self.tar.getmember('pax/regtype1') + replaced = member.replace() + replaced.pax_headers['gname'] = 'not-bar' + self.assertEqual(member.pax_headers['gname'], 'bar') + self.assertEqual( + self.tar.getmember('pax/regtype1').pax_headers['gname'], 'bar') + + def test_replace_shallow(self): + member = self.tar.getmember('pax/regtype1') + replaced = member.replace(deep=False) + replaced.pax_headers['gname'] = 'not-bar' + self.assertEqual(member.pax_headers['gname'], 'not-bar') + self.assertEqual( + self.tar.getmember('pax/regtype1').pax_headers['gname'], 'not-bar') + + def test_replace_all(self): + member = self.tar.getmember('ustar/regtype') + for attr_name in ('name', 'mtime', 'mode', 'linkname', + 'uid', 'gid', 'uname', 'gname'): + with self.subTest(attr_name=attr_name): + replaced = member.replace(**{attr_name: None}) + self.assertEqual(getattr(replaced, attr_name), None) + self.assertNotEqual(getattr(member, attr_name), None) + + def test_replace_internal(self): + member = self.tar.getmember('ustar/regtype') + with self.assertRaises(TypeError): + member.replace(offset=123456789) + + +class NoneInfoExtractTests(ReadTest): + # These mainly check that all kinds of members are extracted successfully + # if some metadata is None. + # Some of the methods do additional spot checks. + + # We also test that the default filters can deal with None. + + extraction_filter = None + + @classmethod + def setUpClass(cls): + tar = tarfile.open(tarname, mode='r', encoding="iso8859-1") + cls.control_dir = pathlib.Path(TEMPDIR) / "extractall_ctrl" + tar.errorlevel = 0 + tar.extractall(cls.control_dir, filter=cls.extraction_filter) + tar.close() + cls.control_paths = set( + p.relative_to(cls.control_dir) + for p in pathlib.Path(cls.control_dir).glob('**/*')) + + @classmethod + def tearDownClass(cls): + shutil.rmtree(cls.control_dir) + + def check_files_present(self, directory): + got_paths = set( + p.relative_to(directory) + for p in pathlib.Path(directory).glob('**/*')) + self.assertEqual(self.control_paths, got_paths) + + @contextmanager + def extract_with_none(self, *attr_names): + DIR = pathlib.Path(TEMPDIR) / "extractall_none" + self.tar.errorlevel = 0 + for member in self.tar.getmembers(): + for attr_name in attr_names: + setattr(member, attr_name, None) + with os_helper.temp_dir(DIR): + self.tar.extractall(DIR, filter='fully_trusted') + self.check_files_present(DIR) + yield DIR + + def test_extractall_none_mtime(self): + # mtimes of extracted files should be later than 'now' -- the mtime + # of a previously created directory. + now = pathlib.Path(TEMPDIR).stat().st_mtime + with self.extract_with_none('mtime') as DIR: + for path in pathlib.Path(DIR).glob('**/*'): + with self.subTest(path=path): + try: + mtime = path.stat().st_mtime + except OSError: + # Some systems can't stat symlinks, ignore those + if not path.is_symlink(): + raise + else: + self.assertGreaterEqual(path.stat().st_mtime, now) + + def test_extractall_none_mode(self): + # modes of directories and regular files should match the mode + # of a "normally" created directory or regular file + dir_mode = pathlib.Path(TEMPDIR).stat().st_mode + regular_file = pathlib.Path(TEMPDIR) / 'regular_file' + regular_file.write_text('') + regular_file_mode = regular_file.stat().st_mode + with self.extract_with_none('mode') as DIR: + for path in pathlib.Path(DIR).glob('**/*'): + with self.subTest(path=path): + if path.is_dir(): + self.assertEqual(path.stat().st_mode, dir_mode) + elif path.is_file(): + self.assertEqual(path.stat().st_mode, + regular_file_mode) + + def test_extractall_none_uid(self): + with self.extract_with_none('uid'): + pass + + def test_extractall_none_gid(self): + with self.extract_with_none('gid'): + pass + + def test_extractall_none_uname(self): + with self.extract_with_none('uname'): + pass + + def test_extractall_none_gname(self): + with self.extract_with_none('gname'): + pass + + def test_extractall_none_ownership(self): + with self.extract_with_none('uid', 'gid', 'uname', 'gname'): + pass + +class NoneInfoExtractTests_Data(NoneInfoExtractTests, unittest.TestCase): + extraction_filter = 'data' + +class NoneInfoExtractTests_FullyTrusted(NoneInfoExtractTests, + unittest.TestCase): + extraction_filter = 'fully_trusted' + +class NoneInfoExtractTests_Tar(NoneInfoExtractTests, unittest.TestCase): + extraction_filter = 'tar' + +class NoneInfoExtractTests_Default(NoneInfoExtractTests, + unittest.TestCase): + extraction_filter = None + +class NoneInfoTests_Misc(unittest.TestCase): + def test_add(self): + # When addfile() encounters None metadata, it raises a ValueError + bio = io.BytesIO() + for tarformat in (tarfile.USTAR_FORMAT, tarfile.GNU_FORMAT, + tarfile.PAX_FORMAT): + with self.subTest(tarformat=tarformat): + tar = tarfile.open(fileobj=bio, mode='w', format=tarformat) + tarinfo = tar.gettarinfo(tarname) + try: + tar.addfile(tarinfo) + except Exception: + if tarformat == tarfile.USTAR_FORMAT: + # In the old, limited format, adding might fail for + # reasons like the UID being too large + pass + else: + raise + else: + for attr_name in ('mtime', 'mode', 'uid', 'gid', + 'uname', 'gname'): + with self.subTest(attr_name=attr_name): + replaced = tarinfo.replace(**{attr_name: None}) + with self.assertRaisesRegex(ValueError, + f"{attr_name}"): + tar.addfile(replaced) + + def test_list(self): + # Change some metadata to None, then compare list() output + # word-for-word. We want list() to not raise, and to only change + # printout for the affected piece of metadata. + # (n.b.: some contents of the test archive are hardcoded.) + for attr_names in ({'mtime'}, {'mode'}, {'uid'}, {'gid'}, + {'uname'}, {'gname'}, + {'uid', 'uname'}, {'gid', 'gname'}): + with (self.subTest(attr_names=attr_names), + tarfile.open(tarname, encoding="iso8859-1") as tar): + tio_prev = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio_prev): + tar.list() + for member in tar.getmembers(): + for attr_name in attr_names: + setattr(member, attr_name, None) + tio_new = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio_new): + tar.list() + for expected, got in zip(tio_prev.detach().getvalue().split(), + tio_new.detach().getvalue().split()): + if attr_names == {'mtime'} and re.match(rb'2003-01-\d\d', expected): + self.assertEqual(got, b'????-??-??') + elif attr_names == {'mtime'} and re.match(rb'\d\d:\d\d:\d\d', expected): + self.assertEqual(got, b'??:??:??') + elif attr_names == {'mode'} and re.match( + rb'.([r-][w-][x-]){3}', expected): + self.assertEqual(got, b'??????????') + elif attr_names == {'uname'} and expected.startswith( + (b'tarfile/', b'lars/', b'foo/')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_group, exp_group) + self.assertRegex(got_user, b'[0-9]+') + elif attr_names == {'gname'} and expected.endswith( + (b'/tarfile', b'/users', b'/bar')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_user, exp_user) + self.assertRegex(got_group, b'[0-9]+') + elif attr_names == {'uid'} and expected.startswith( + (b'1000/')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_group, exp_group) + self.assertEqual(got_user, b'None') + elif attr_names == {'gid'} and expected.endswith((b'/100')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_user, exp_user) + self.assertEqual(got_group, b'None') + elif attr_names == {'uid', 'uname'} and expected.startswith( + (b'tarfile/', b'lars/', b'foo/', b'1000/')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_group, exp_group) + self.assertEqual(got_user, b'None') + elif attr_names == {'gname', 'gid'} and expected.endswith( + (b'/tarfile', b'/users', b'/bar', b'/100')): + exp_user, exp_group = expected.split(b'/') + got_user, got_group = got.split(b'/') + self.assertEqual(got_user, exp_user) + self.assertEqual(got_group, b'None') + else: + # In other cases the output should be the same + self.assertEqual(expected, got) + +def _filemode_to_int(mode): + """Inverse of `stat.filemode` (for permission bits) + + Using mode strings rather than numbers makes the later tests more readable. + """ + str_mode = mode[1:] + result = ( + {'r': stat.S_IRUSR, '-': 0}[str_mode[0]] + | {'w': stat.S_IWUSR, '-': 0}[str_mode[1]] + | {'x': stat.S_IXUSR, '-': 0, + 's': stat.S_IXUSR | stat.S_ISUID, + 'S': stat.S_ISUID}[str_mode[2]] + | {'r': stat.S_IRGRP, '-': 0}[str_mode[3]] + | {'w': stat.S_IWGRP, '-': 0}[str_mode[4]] + | {'x': stat.S_IXGRP, '-': 0, + 's': stat.S_IXGRP | stat.S_ISGID, + 'S': stat.S_ISGID}[str_mode[5]] + | {'r': stat.S_IROTH, '-': 0}[str_mode[6]] + | {'w': stat.S_IWOTH, '-': 0}[str_mode[7]] + | {'x': stat.S_IXOTH, '-': 0, + 't': stat.S_IXOTH | stat.S_ISVTX, + 'T': stat.S_ISVTX}[str_mode[8]] + ) + # check we did this right + assert stat.filemode(result)[1:] == mode[1:] + + return result + +class ArchiveMaker: + """Helper to create a tar file with specific contents + + Usage: + + with ArchiveMaker() as t: + t.add('filename', ...) + + with t.open() as tar: + ... # `tar` is now a TarFile with 'filename' in it! + """ + def __init__(self): + self.bio = io.BytesIO() + + def __enter__(self): + self.tar_w = tarfile.TarFile(mode='w', fileobj=self.bio) + return self + + def __exit__(self, *exc): + self.tar_w.close() + self.contents = self.bio.getvalue() + self.bio = None + + def add(self, name, *, type=None, symlink_to=None, hardlink_to=None, + mode=None, **kwargs): + """Add a member to the test archive. Call within `with`.""" + name = str(name) + tarinfo = tarfile.TarInfo(name).replace(**kwargs) + if mode: + tarinfo.mode = _filemode_to_int(mode) + if symlink_to is not None: + type = tarfile.SYMTYPE + tarinfo.linkname = str(symlink_to) + if hardlink_to is not None: + type = tarfile.LNKTYPE + tarinfo.linkname = str(hardlink_to) + if name.endswith('/') and type is None: + type = tarfile.DIRTYPE + if type is not None: + tarinfo.type = type + if tarinfo.isreg(): + fileobj = io.BytesIO(bytes(tarinfo.size)) + else: + fileobj = None + self.tar_w.addfile(tarinfo, fileobj) + + def open(self, **kwargs): + """Open the resulting archive as TarFile. Call after `with`.""" + bio = io.BytesIO(self.contents) + return tarfile.open(fileobj=bio, **kwargs) + + +class TestExtractionFilters(unittest.TestCase): + + # A temporary directory for the extraction results. + # All files that "escape" the destination path should still end + # up in this directory. + outerdir = pathlib.Path(TEMPDIR) / 'outerdir' + + # The destination for the extraction, within `outerdir` + destdir = outerdir / 'dest' + + @contextmanager + def check_context(self, tar, filter): + """Extracts `tar` to `self.destdir` and allows checking the result + + If an error occurs, it must be checked using `expect_exception` + + Otherwise, all resulting files must be checked using `expect_file`, + except the destination directory itself and parent directories of + other files. + When checking directories, do so before their contents. + """ + with os_helper.temp_dir(self.outerdir): + try: + tar.extractall(self.destdir, filter=filter) + except Exception as exc: + self.raised_exception = exc + self.expected_paths = set() + else: + self.raised_exception = None + self.expected_paths = set(self.outerdir.glob('**/*')) + self.expected_paths.discard(self.destdir) + try: + yield + finally: + tar.close() + if self.raised_exception: + raise self.raised_exception + self.assertEqual(self.expected_paths, set()) + + def expect_file(self, name, type=None, symlink_to=None, mode=None): + """Check a single file. See check_context.""" + if self.raised_exception: + raise self.raised_exception + # use normpath() rather than resolve() so we don't follow symlinks + path = pathlib.Path(os.path.normpath(self.destdir / name)) + self.assertIn(path, self.expected_paths) + self.expected_paths.remove(path) + + # When checking mode, ignore Windows (which can only set user read and + # user write bits). Newer versions of Python use `os_helper.can_chmod()` + # instead of hardcoding Windows. + if mode is not None and sys.platform != 'win32': + got = stat.filemode(stat.S_IMODE(path.stat().st_mode)) + self.assertEqual(got, mode) + + if type is None and isinstance(name, str) and name.endswith('/'): + type = tarfile.DIRTYPE + if symlink_to is not None: + got = (self.destdir / name).readlink() + expected = pathlib.Path(symlink_to) + # The symlink might be the same (textually) as what we expect, + # but some systems change the link to an equivalent path, so + # we fall back to samefile(). + if expected != got: + self.assertTrue(got.samefile(expected)) + elif type == tarfile.REGTYPE or type is None: + self.assertTrue(path.is_file()) + elif type == tarfile.DIRTYPE: + self.assertTrue(path.is_dir()) + elif type == tarfile.FIFOTYPE: + self.assertTrue(path.is_fifo()) + else: + raise NotImplementedError(type) + for parent in path.parents: + self.expected_paths.discard(parent) + + def expect_exception(self, exc_type, message_re='.'): + with self.assertRaisesRegex(exc_type, message_re): + if self.raised_exception is not None: + raise self.raised_exception + self.raised_exception = None + + def test_benign_file(self): + with ArchiveMaker() as arc: + arc.add('benign.txt') + for filter in 'fully_trusted', 'tar', 'data': + with self.check_context(arc.open(), filter): + self.expect_file('benign.txt') + + def test_absolute(self): + # Test handling a member with an absolute path + # Inspired by 'absolute1' in https://github.com/jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add(self.outerdir / 'escaped.evil') + + with self.check_context(arc.open(), 'fully_trusted'): + self.expect_file('../escaped.evil') + + for filter in 'tar', 'data': + with self.check_context(arc.open(), filter): + if str(self.outerdir).startswith('/'): + # We strip leading slashes, as e.g. GNU tar does + # (without --absolute-filenames). + outerdir_stripped = str(self.outerdir).lstrip('/') + self.expect_file(f'{outerdir_stripped}/escaped.evil') + else: + # On this system, absolute paths don't have leading + # slashes. + # So, there's nothing to strip. We refuse to unpack + # to an absolute path, nonetheless. + self.expect_exception( + tarfile.AbsolutePathError, + """['"].*escaped.evil['"] has an absolute path""") + + def test_parent_symlink(self): + # Test interplaying symlinks + # Inspired by 'dirsymlink2a' in jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('current', symlink_to='.') + arc.add('parent', symlink_to='current/..') + arc.add('parent/evil') + + if os_helper.can_symlink(): + with self.check_context(arc.open(), 'fully_trusted'): + if self.raised_exception is not None: + # Windows will refuse to create a file that's a symlink to itself + # (and tarfile doesn't swallow that exception) + self.expect_exception(FileExistsError) + # The other cases will fail with this error too. + # Skip the rest of this test. + return + else: + self.expect_file('current', symlink_to='.') + self.expect_file('parent', symlink_to='current/..') + self.expect_file('../evil') + + with self.check_context(arc.open(), 'tar'): + self.expect_exception( + tarfile.OutsideDestinationError, + """'parent/evil' would be extracted to ['"].*evil['"], """ + + "which is outside the destination") + + with self.check_context(arc.open(), 'data'): + self.expect_exception( + tarfile.LinkOutsideDestinationError, + """'parent' would link to ['"].*outerdir['"], """ + + "which is outside the destination") + + else: + # No symlink support. The symlinks are ignored. + with self.check_context(arc.open(), 'fully_trusted'): + self.expect_file('parent/evil') + with self.check_context(arc.open(), 'tar'): + self.expect_file('parent/evil') + with self.check_context(arc.open(), 'data'): + self.expect_file('parent/evil') + + def test_parent_symlink2(self): + # Test interplaying symlinks + # Inspired by 'dirsymlink2b' in jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('current', symlink_to='.') + arc.add('current/parent', symlink_to='..') + arc.add('parent/evil') + + with self.check_context(arc.open(), 'fully_trusted'): + if os_helper.can_symlink(): + self.expect_file('current', symlink_to='.') + self.expect_file('parent', symlink_to='..') + self.expect_file('../evil') + else: + self.expect_file('current/') + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'tar'): + if os_helper.can_symlink(): + self.expect_exception( + tarfile.OutsideDestinationError, + "'parent/evil' would be extracted to " + + """['"].*evil['"], which is outside """ + + "the destination") + else: + self.expect_file('current/') + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'data'): + self.expect_exception( + tarfile.LinkOutsideDestinationError, + """'current/parent' would link to ['"].*['"], """ + + "which is outside the destination") + + def test_absolute_symlink(self): + # Test symlink to an absolute path + # Inspired by 'dirsymlink' in jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('parent', symlink_to=self.outerdir) + arc.add('parent/evil') + + with self.check_context(arc.open(), 'fully_trusted'): + if os_helper.can_symlink(): + self.expect_file('parent', symlink_to=self.outerdir) + self.expect_file('../evil') + else: + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'tar'): + if os_helper.can_symlink(): + self.expect_exception( + tarfile.OutsideDestinationError, + "'parent/evil' would be extracted to " + + """['"].*evil['"], which is outside """ + + "the destination") + else: + self.expect_file('parent/evil') + + with self.check_context(arc.open(), 'data'): + self.expect_exception( + tarfile.AbsoluteLinkError, + "'parent' is a symlink to an absolute path") + + def test_sly_relative0(self): + # Inspired by 'relative0' in jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('../moo', symlink_to='..//tmp/moo') + + try: + with self.check_context(arc.open(), filter='fully_trusted'): + if os_helper.can_symlink(): + if isinstance(self.raised_exception, FileExistsError): + # XXX TarFile happens to fail creating a parent + # directory. + # This might be a bug, but fixing it would hurt + # security. + # Note that e.g. GNU `tar` rejects '..' components, + # so you could argue this is an invalid archive and we + # just raise an bad type of exception. + self.expect_exception(FileExistsError) + else: + self.expect_file('../moo', symlink_to='..//tmp/moo') + else: + # The symlink can't be extracted and is ignored + pass + except FileExistsError: + pass + + for filter in 'tar', 'data': + with self.check_context(arc.open(), filter): + self.expect_exception( + tarfile.OutsideDestinationError, + "'../moo' would be extracted to " + + "'.*moo', which is outside " + + "the destination") + + def test_sly_relative2(self): + # Inspired by 'relative2' in jwilk/traversal-archives + with ArchiveMaker() as arc: + arc.add('tmp/') + arc.add('tmp/../../moo', symlink_to='tmp/../..//tmp/moo') + + with self.check_context(arc.open(), 'fully_trusted'): + self.expect_file('tmp', type=tarfile.DIRTYPE) + if os_helper.can_symlink(): + self.expect_file('../moo', symlink_to='tmp/../../tmp/moo') + + for filter in 'tar', 'data': + with self.check_context(arc.open(), filter): + self.expect_exception( + tarfile.OutsideDestinationError, + "'tmp/../../moo' would be extracted to " + + """['"].*moo['"], which is outside the """ + + "destination") + + def test_modes(self): + # Test how file modes are extracted + # (Note that the modes are ignored on platforms without working chmod) + with ArchiveMaker() as arc: + arc.add('all_bits', mode='?rwsrwsrwt') + arc.add('perm_bits', mode='?rwxrwxrwx') + arc.add('exec_group_other', mode='?rw-rwxrwx') + arc.add('read_group_only', mode='?---r-----') + arc.add('no_bits', mode='?---------') + arc.add('dir/', mode='?---rwsrwt') + + # On some systems, setting the sticky bit is a no-op. + # Check if that's the case. + tmp_filename = os.path.join(TEMPDIR, "tmp.file") + with open(tmp_filename, 'w'): + pass + os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX) + have_sticky_files = (os.stat(tmp_filename).st_mode & stat.S_ISVTX) + os.unlink(tmp_filename) + + os.mkdir(tmp_filename) + os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX) + have_sticky_dirs = (os.stat(tmp_filename).st_mode & stat.S_ISVTX) + os.rmdir(tmp_filename) + + with self.check_context(arc.open(), 'fully_trusted'): + if have_sticky_files: + self.expect_file('all_bits', mode='?rwsrwsrwt') + else: + self.expect_file('all_bits', mode='?rwsrwsrwx') + self.expect_file('perm_bits', mode='?rwxrwxrwx') + self.expect_file('exec_group_other', mode='?rw-rwxrwx') + self.expect_file('read_group_only', mode='?---r-----') + self.expect_file('no_bits', mode='?---------') + if have_sticky_dirs: + self.expect_file('dir/', mode='?---rwsrwt') + else: + self.expect_file('dir/', mode='?---rwsrwx') + + with self.check_context(arc.open(), 'tar'): + self.expect_file('all_bits', mode='?rwxr-xr-x') + self.expect_file('perm_bits', mode='?rwxr-xr-x') + self.expect_file('exec_group_other', mode='?rw-r-xr-x') + self.expect_file('read_group_only', mode='?---r-----') + self.expect_file('no_bits', mode='?---------') + self.expect_file('dir/', mode='?---r-xr-x') + + with self.check_context(arc.open(), 'data'): + normal_dir_mode = stat.filemode(stat.S_IMODE( + self.outerdir.stat().st_mode)) + self.expect_file('all_bits', mode='?rwxr-xr-x') + self.expect_file('perm_bits', mode='?rwxr-xr-x') + self.expect_file('exec_group_other', mode='?rw-r--r--') + self.expect_file('read_group_only', mode='?rw-r-----') + self.expect_file('no_bits', mode='?rw-------') + self.expect_file('dir/', mode=normal_dir_mode) + + def test_pipe(self): + # Test handling of a special file + with ArchiveMaker() as arc: + arc.add('foo', type=tarfile.FIFOTYPE) + + for filter in 'fully_trusted', 'tar': + with self.check_context(arc.open(), filter): + if hasattr(os, 'mkfifo'): + self.expect_file('foo', type=tarfile.FIFOTYPE) + else: + # The pipe can't be extracted and is skipped. + pass + + with self.check_context(arc.open(), 'data'): + self.expect_exception( + tarfile.SpecialFileError, + "'foo' is a special file") + + def test_special_files(self): + # Creating device files is tricky. Instead of attempting that let's + # only check the filter result. + for special_type in tarfile.FIFOTYPE, tarfile.CHRTYPE, tarfile.BLKTYPE: + tarinfo = tarfile.TarInfo('foo') + tarinfo.type = special_type + trusted = tarfile.fully_trusted_filter(tarinfo, '') + self.assertIs(trusted, tarinfo) + tar = tarfile.tar_filter(tarinfo, '') + self.assertEqual(tar.type, special_type) + with self.assertRaises(tarfile.SpecialFileError) as cm: + tarfile.data_filter(tarinfo, '') + self.assertIsInstance(cm.exception.tarinfo, tarfile.TarInfo) + self.assertEqual(cm.exception.tarinfo.name, 'foo') + + def test_fully_trusted_filter(self): + # The 'fully_trusted' filter returns the original TarInfo objects. + with tarfile.TarFile.open(tarname) as tar: + for tarinfo in tar.getmembers(): + filtered = tarfile.fully_trusted_filter(tarinfo, '') + self.assertIs(filtered, tarinfo) + + def test_tar_filter(self): + # The 'tar' filter returns TarInfo objects with the same name/type. + # (It can also fail for particularly "evil" input, but we don't have + # that in the test archive.) + with tarfile.TarFile.open(tarname) as tar: + for tarinfo in tar.getmembers(): + filtered = tarfile.tar_filter(tarinfo, '') + self.assertIs(filtered.name, tarinfo.name) + self.assertIs(filtered.type, tarinfo.type) + + def test_data_filter(self): + # The 'data' filter either raises, or returns TarInfo with the same + # name/type. + with tarfile.TarFile.open(tarname) as tar: + for tarinfo in tar.getmembers(): + try: + filtered = tarfile.data_filter(tarinfo, '') + except tarfile.FilterError: + continue + self.assertIs(filtered.name, tarinfo.name) + self.assertIs(filtered.type, tarinfo.type) + + def test_default_filter_warns_not(self): + """Ensure the default filter does not warn (like in 3.12)""" + with ArchiveMaker() as arc: + arc.add('foo') + with warnings_helper.check_no_warnings(self): + with self.check_context(arc.open(), None): + self.expect_file('foo') + + def test_change_default_filter_on_instance(self): + tar = tarfile.TarFile(tarname, 'r') + def strict_filter(tarinfo, path): + if tarinfo.name == 'ustar/regtype': + return tarinfo + else: + return None + tar.extraction_filter = strict_filter + with self.check_context(tar, None): + self.expect_file('ustar/regtype') + + def test_change_default_filter_on_class(self): + def strict_filter(tarinfo, path): + if tarinfo.name == 'ustar/regtype': + return tarinfo + else: + return None + tar = tarfile.TarFile(tarname, 'r') + with support.swap_attr(tarfile.TarFile, 'extraction_filter', + staticmethod(strict_filter)): + with self.check_context(tar, None): + self.expect_file('ustar/regtype') + + def test_change_default_filter_on_subclass(self): + class TarSubclass(tarfile.TarFile): + def extraction_filter(self, tarinfo, path): + if tarinfo.name == 'ustar/regtype': + return tarinfo + else: + return None + + tar = TarSubclass(tarname, 'r') + with self.check_context(tar, None): + self.expect_file('ustar/regtype') + + def test_change_default_filter_to_string(self): + tar = tarfile.TarFile(tarname, 'r') + tar.extraction_filter = 'data' + with self.check_context(tar, None): + self.expect_exception(TypeError) + + def test_custom_filter(self): + def custom_filter(tarinfo, path): + self.assertIs(path, self.destdir) + if tarinfo.name == 'move_this': + return tarinfo.replace(name='moved') + if tarinfo.name == 'ignore_this': + return None + return tarinfo + + with ArchiveMaker() as arc: + arc.add('move_this') + arc.add('ignore_this') + arc.add('keep') + with self.check_context(arc.open(), custom_filter): + self.expect_file('moved') + self.expect_file('keep') + + def test_bad_filter_name(self): + with ArchiveMaker() as arc: + arc.add('foo') + with self.check_context(arc.open(), 'bad filter name'): + self.expect_exception(ValueError) + + def test_stateful_filter(self): + # Stateful filters should be possible. + # (This doesn't really test tarfile. Rather, it demonstrates + # that third parties can implement a stateful filter.) + class StatefulFilter: + def __enter__(self): + self.num_files_processed = 0 + return self + + def __call__(self, tarinfo, path): + try: + tarinfo = tarfile.data_filter(tarinfo, path) + except tarfile.FilterError: + return None + self.num_files_processed += 1 + return tarinfo + + def __exit__(self, *exc_info): + self.done = True + + with ArchiveMaker() as arc: + arc.add('good') + arc.add('bad', symlink_to='/') + arc.add('good') + with StatefulFilter() as custom_filter: + with self.check_context(arc.open(), custom_filter): + self.expect_file('good') + self.assertEqual(custom_filter.num_files_processed, 2) + self.assertEqual(custom_filter.done, True) + + def test_errorlevel(self): + def extracterror_filter(tarinfo, path): + raise tarfile.ExtractError('failed with ExtractError') + def filtererror_filter(tarinfo, path): + raise tarfile.FilterError('failed with FilterError') + def oserror_filter(tarinfo, path): + raise OSError('failed with OSError') + def tarerror_filter(tarinfo, path): + raise tarfile.TarError('failed with base TarError') + def valueerror_filter(tarinfo, path): + raise ValueError('failed with ValueError') + + with ArchiveMaker() as arc: + arc.add('file') + + # If errorlevel is 0, errors affected by errorlevel are ignored + + with self.check_context(arc.open(errorlevel=0), extracterror_filter): + self.expect_file('file') + + with self.check_context(arc.open(errorlevel=0), filtererror_filter): + self.expect_file('file') + + with self.check_context(arc.open(errorlevel=0), oserror_filter): + self.expect_file('file') + + with self.check_context(arc.open(errorlevel=0), tarerror_filter): + self.expect_exception(tarfile.TarError) + + with self.check_context(arc.open(errorlevel=0), valueerror_filter): + self.expect_exception(ValueError) + + # If 1, all fatal errors are raised + + with self.check_context(arc.open(errorlevel=1), extracterror_filter): + self.expect_file('file') + + with self.check_context(arc.open(errorlevel=1), filtererror_filter): + self.expect_exception(tarfile.FilterError) + + with self.check_context(arc.open(errorlevel=1), oserror_filter): + self.expect_exception(OSError) + + with self.check_context(arc.open(errorlevel=1), tarerror_filter): + self.expect_exception(tarfile.TarError) + + with self.check_context(arc.open(errorlevel=1), valueerror_filter): + self.expect_exception(ValueError) + + # If 2, all non-fatal errors are raised as well. + + with self.check_context(arc.open(errorlevel=2), extracterror_filter): + self.expect_exception(tarfile.ExtractError) + + with self.check_context(arc.open(errorlevel=2), filtererror_filter): + self.expect_exception(tarfile.FilterError) + + with self.check_context(arc.open(errorlevel=2), oserror_filter): + self.expect_exception(OSError) + + with self.check_context(arc.open(errorlevel=2), tarerror_filter): + self.expect_exception(tarfile.TarError) + + with self.check_context(arc.open(errorlevel=2), valueerror_filter): + self.expect_exception(ValueError) + + # We only handle ExtractionError, FilterError & OSError specially. + + with self.check_context(arc.open(errorlevel='boo!'), filtererror_filter): + self.expect_exception(TypeError) # errorlevel is not int + + def setUpModule(): os_helper.unlink(TEMPDIR) os.makedirs(TEMPDIR) diff -Nru python3.10-3.10.7/Lib/test/test_threading_local.py python3.10-3.10.12/Lib/test/test_threading_local.py --- python3.10-3.10.7/Lib/test/test_threading_local.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_threading_local.py 2023-06-06 22:30:33.000000000 +0000 @@ -3,6 +3,7 @@ from doctest import DocTestSuite from test import support from test.support import threading_helper +from test.support.import_helper import import_module import weakref import gc @@ -194,6 +195,18 @@ self.assertIsNone(wr()) + def test_threading_local_clear_race(self): + # See https://github.com/python/cpython/issues/100892 + + _testcapi = import_module('_testcapi') + _testcapi.call_in_temporary_c_thread(lambda: None, False) + + for _ in range(1000): + _ = threading.local() + + _testcapi.join_temporary_c_thread() + + class ThreadLocalTest(unittest.TestCase, BaseLocalTest): _local = _thread._local diff -Nru python3.10-3.10.7/Lib/test/test_tokenize.py python3.10-3.10.12/Lib/test/test_tokenize.py --- python3.10-3.10.7/Lib/test/test_tokenize.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_tokenize.py 2023-06-06 22:30:33.000000000 +0000 @@ -10,6 +10,8 @@ from unittest import TestCase, mock from test.test_grammar import (VALID_UNDERSCORE_LITERALS, INVALID_UNDERSCORE_LITERALS) +from test.support import os_helper +from test.support.script_helper import run_test_script, make_script import os import token @@ -1654,5 +1656,19 @@ self.check_roundtrip(code) +class CTokenizerBufferTests(unittest.TestCase): + def test_newline_at_the_end_of_buffer(self): + # See issue 99581: Make sure that if we need to add a new line at the + # end of the buffer, we have enough space in the buffer, specially when + # the current line is as long as the buffer space available. + test_script = f"""\ + #coding: latin-1 + #{"a"*10000} + #{"a"*10002}""" + with os_helper.temp_dir() as temp_dir: + file_name = make_script(temp_dir, 'foo', test_script) + run_test_script(file_name) + + if __name__ == "__main__": unittest.main() diff -Nru python3.10-3.10.7/Lib/test/test_tools/test_i18n.py python3.10-3.10.12/Lib/test/test_tools/test_i18n.py --- python3.10-3.10.7/Lib/test/test_tools/test_i18n.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_tools/test_i18n.py 2023-06-06 22:30:33.000000000 +0000 @@ -155,6 +155,26 @@ ''')) self.assertFalse([msgid for msgid in msgids if 'doc' in msgid]) + def test_moduledocstring(self): + for doc in ('"""doc"""', "r'''doc'''", "R'doc'", 'u"doc"'): + with self.subTest(doc): + msgids = self.extract_docstrings_from_str(dedent('''\ + %s + ''' % doc)) + self.assertIn('doc', msgids) + + def test_moduledocstring_bytes(self): + msgids = self.extract_docstrings_from_str(dedent('''\ + b"""doc""" + ''')) + self.assertFalse([msgid for msgid in msgids if 'doc' in msgid]) + + def test_moduledocstring_fstring(self): + msgids = self.extract_docstrings_from_str(dedent('''\ + f"""doc""" + ''')) + self.assertFalse([msgid for msgid in msgids if 'doc' in msgid]) + def test_msgid(self): msgids = self.extract_docstrings_from_str( '''_("""doc""" r'str' u"ing")''') diff -Nru python3.10-3.10.7/Lib/test/test_trace.py python3.10-3.10.12/Lib/test/test_trace.py --- python3.10-3.10.7/Lib/test/test_trace.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_trace.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,4 +1,5 @@ import os +from pickle import dump import sys from test.support import captured_stdout from test.support.os_helper import (TESTFN, rmtree, unlink) @@ -407,6 +408,15 @@ self.assertIn(modname, coverage) self.assertEqual(coverage[modname], (5, 100)) + def test_coverageresults_update(self): + # Update empty CoverageResults with a non-empty infile. + infile = TESTFN + '-infile' + with open(infile, 'wb') as f: + dump(({}, {}, {'caller': 1}), f, protocol=1) + self.addCleanup(unlink, infile) + results = trace.CoverageResults({}, {}, infile, {}) + self.assertEqual(results.callers, {'caller': 1}) + ### Tests that don't mess with sys.settrace and can be traced ### themselves TODO: Skip tests that do mess with sys.settrace when ### regrtest is invoked with -T option. diff -Nru python3.10-3.10.7/Lib/test/test_typing.py python3.10-3.10.12/Lib/test/test_typing.py --- python3.10-3.10.7/Lib/test/test_typing.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_typing.py 2023-06-06 22:30:33.000000000 +0000 @@ -556,14 +556,27 @@ self.assertEqual(weakref.ref(alias)(), alias) def test_pickle(self): + global T_pickle, P_pickle # needed for pickling Callable = self.Callable - alias = Callable[[int, str], float] - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - s = pickle.dumps(alias, proto) - loaded = pickle.loads(s) - self.assertEqual(alias.__origin__, loaded.__origin__) - self.assertEqual(alias.__args__, loaded.__args__) - self.assertEqual(alias.__parameters__, loaded.__parameters__) + T_pickle = TypeVar('T_pickle') + P_pickle = ParamSpec('P_pickle') + + samples = [ + Callable[[int, str], float], + Callable[P_pickle, int], + Callable[P_pickle, T_pickle], + Callable[Concatenate[int, P_pickle], int], + ] + for alias in samples: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.subTest(alias=alias, proto=proto): + s = pickle.dumps(alias, proto) + loaded = pickle.loads(s) + self.assertEqual(alias.__origin__, loaded.__origin__) + self.assertEqual(alias.__args__, loaded.__args__) + self.assertEqual(alias.__parameters__, loaded.__parameters__) + + del T_pickle, P_pickle # cleaning up global state def test_var_substitution(self): Callable = self.Callable @@ -590,6 +603,16 @@ self.assertEqual(C5[int, str, float], Callable[[typing.List[int], tuple[str, int], float], int]) + def test_type_subst_error(self): + Callable = self.Callable + P = ParamSpec('P') + T = TypeVar('T') + + pat = "Expected a list of types, an ellipsis, ParamSpec, or Concatenate." + + with self.assertRaisesRegex(TypeError, pat): + Callable[P, T][0, int] + def test_type_erasure(self): Callable = self.Callable class C1(Callable): @@ -1142,6 +1165,94 @@ with self.assertRaises(TypeError): isinstance(C(), BadPG) + def test_protocols_isinstance_properties_and_descriptors(self): + class C: + @property + def attr(self): + return 42 + + class CustomDescriptor: + def __get__(self, obj, objtype=None): + return 42 + + class D: + attr = CustomDescriptor() + + # Check that properties set on superclasses + # are still found by the isinstance() logic + class E(C): ... + class F(D): ... + + class Empty: ... + + T = TypeVar('T') + + @runtime_checkable + class P(Protocol): + @property + def attr(self): ... + + @runtime_checkable + class P1(Protocol): + attr: int + + @runtime_checkable + class PG(Protocol[T]): + @property + def attr(self): ... + + @runtime_checkable + class PG1(Protocol[T]): + attr: T + + for protocol_class in P, P1, PG, PG1: + for klass in C, D, E, F: + with self.subTest( + klass=klass.__name__, + protocol_class=protocol_class.__name__ + ): + self.assertIsInstance(klass(), protocol_class) + + with self.subTest(klass="Empty", protocol_class=protocol_class.__name__): + self.assertNotIsInstance(Empty(), protocol_class) + + class BadP(Protocol): + @property + def attr(self): ... + + class BadP1(Protocol): + attr: int + + class BadPG(Protocol[T]): + @property + def attr(self): ... + + class BadPG1(Protocol[T]): + attr: T + + for obj in PG[T], PG[C], PG1[T], PG1[C], BadP, BadP1, BadPG, BadPG1: + for klass in C, D, E, F, Empty: + with self.subTest(klass=klass.__name__, obj=obj): + with self.assertRaises(TypeError): + isinstance(klass(), obj) + + def test_protocols_isinstance_not_fooled_by_custom_dir(self): + @runtime_checkable + class HasX(Protocol): + x: int + + class CustomDirWithX: + x = 10 + def __dir__(self): + return [] + + class CustomDirWithoutX: + def __dir__(self): + return ["x"] + + self.assertIsInstance(CustomDirWithX(), HasX) + self.assertNotIsInstance(CustomDirWithoutX(), HasX) + def test_protocols_isinstance_py36(self): class APoint: def __init__(self, x, y, label): @@ -1528,8 +1639,8 @@ def __init__(self): self.x = None - self.assertIsInstance(C(), P) - self.assertIsInstance(D(), P) + self.assertIsInstance(CI(), P) + self.assertIsInstance(DI(), P) def test_protocols_in_unions(self): class P(Protocol): @@ -1560,7 +1671,7 @@ self.assertEqual(x.bar, 'abc') self.assertEqual(x.x, 1) self.assertEqual(x.__dict__, {'foo': 42, 'bar': 'abc'}) - s = pickle.dumps(P) + s = pickle.dumps(P, proto) D = pickle.loads(s) class E: @@ -2405,11 +2516,11 @@ self.assertEqual(D.__parameters__, ()) - with self.assertRaises(Exception): + with self.assertRaises(TypeError): D[int] - with self.assertRaises(Exception): + with self.assertRaises(TypeError): D[Any] - with self.assertRaises(Exception): + with self.assertRaises(TypeError): D[T] def test_new_with_args(self): @@ -2498,6 +2609,61 @@ class Foo(obj): pass + def test_complex_subclasses(self): + T_co = TypeVar("T_co", covariant=True) + + class Base(Generic[T_co]): + ... + + T = TypeVar("T") + + # see gh-94607: this fails in that bug + class Sub(Base, Generic[T]): + ... + + def test_parameter_detection(self): + self.assertEqual(List[T].__parameters__, (T,)) + self.assertEqual(List[List[T]].__parameters__, (T,)) + class A: + __parameters__ = (T,) + # Bare classes should be skipped + for a in (List, list): + for b in (int, TypeVar, ParamSpec, types.GenericAlias, types.UnionType): + with self.subTest(generic=a, sub=b): + with self.assertRaisesRegex(TypeError, + '.* is not a generic class|' + 'no type variables left'): + a[b][str] + # Duck-typing anything that looks like it has __parameters__. + # C version of GenericAlias + self.assertEqual(list[A()].__parameters__, (T,)) + + def test_non_generic_subscript(self): + T = TypeVar('T') + class G(Generic[T]): + pass + + for s in (int, G, List, list, + TypeVar, ParamSpec, + types.GenericAlias, types.UnionType): + + for t in Tuple, tuple: + with self.subTest(tuple=t, sub=s): + self.assertEqual(t[s, T][int], t[s, int]) + self.assertEqual(t[T, s][int], t[int, s]) + a = t[s] + with self.assertRaises(TypeError): + a[int] + + for c in Callable, collections.abc.Callable: + with self.subTest(callable=c, sub=s): + self.assertEqual(c[[s], T][int], c[[s], int]) + self.assertEqual(c[[T], s][int], c[[int], s]) + a = c[[s], s] + with self.assertRaises(TypeError): + a[int] + + class ClassVarTests(BaseTestCase): def test_basics(self): @@ -4697,16 +4863,6 @@ self.assertEqual(get_type_hints(C, globals())['classvar'], ClassVar[int]) self.assertEqual(get_type_hints(C, globals())['const'], Final[int]) - def test_hash_eq(self): - self.assertEqual(len({Annotated[int, 4, 5], Annotated[int, 4, 5]}), 1) - self.assertNotEqual(Annotated[int, 4, 5], Annotated[int, 5, 4]) - self.assertNotEqual(Annotated[int, 4, 5], Annotated[str, 4, 5]) - self.assertNotEqual(Annotated[int, 4], Annotated[int, 4, 4]) - self.assertEqual( - {Annotated[int, 4, 5], Annotated[int, 4, 5], Annotated[T, 4, 5]}, - {Annotated[int, 4, 5], Annotated[T, 4, 5]} - ) - def test_cannot_subclass(self): with self.assertRaisesRegex(TypeError, "Cannot subclass .*Annotated"): class C(Annotated): @@ -5254,7 +5410,7 @@ self.assertEqual(fr.__module__, 'typing') # Forward refs are currently unpicklable. for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.assertRaises(TypeError) as exc: + with self.assertRaises(TypeError): pickle.dumps(fr, proto) self.assertEqual(SpecialAttrsTests.TypeName.__name__, 'TypeName') diff -Nru python3.10-3.10.7/Lib/test/test_unicodedata.py python3.10-3.10.12/Lib/test/test_unicodedata.py --- python3.10-3.10.7/Lib/test/test_unicodedata.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_unicodedata.py 2023-06-06 22:30:33.000000000 +0000 @@ -12,7 +12,8 @@ import unicodedata import unittest from test.support import (open_urlresource, requires_resource, script_helper, - cpython_only, check_disallow_instantiation) + cpython_only, check_disallow_instantiation, + ResourceDenied) class UnicodeMethodsTest(unittest.TestCase): @@ -95,6 +96,13 @@ result = h.hexdigest() self.assertEqual(result, self.expectedchecksum) + @requires_resource('cpu') + def test_name_inverse_lookup(self): + for i in range(sys.maxunicode + 1): + char = chr(i) + if looked_name := self.db.name(char, None): + self.assertEqual(self.db.lookup(looked_name), char) + def test_digit(self): self.assertEqual(self.db.digit('A', None), None) self.assertEqual(self.db.digit('9'), 9) @@ -338,8 +346,8 @@ except PermissionError: self.skipTest(f"Permission error when downloading {TESTDATAURL} " f"into the test data directory") - except (OSError, HTTPException): - self.fail(f"Could not retrieve {TESTDATAURL}") + except (OSError, HTTPException) as exc: + self.skipTest(f"Failed to download {TESTDATAURL}: {exc}") with testdata: self.run_normalization_tests(testdata) diff -Nru python3.10-3.10.7/Lib/test/test_unicode.py python3.10-3.10.12/Lib/test/test_unicode.py --- python3.10-3.10.7/Lib/test/test_unicode.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_unicode.py 2023-06-06 22:30:33.000000000 +0000 @@ -15,7 +15,6 @@ import unicodedata import unittest import warnings -from test.support import import_helper from test.support import warnings_helper from test import support, string_tests from test.support.script_helper import assert_python_failure @@ -221,6 +220,20 @@ self.checkequalnofix(9, 'abcdefghiabc', 'find', 'abc', 1) self.checkequalnofix(-1, 'abcdefghiabc', 'find', 'def', 4) + # test utf-8 non-ascii char + self.checkequal(0, 'тест', 'find', 'т') + self.checkequal(3, 'тест', 'find', 'т', 1) + self.checkequal(-1, 'тест', 'find', 'т', 1, 3) + self.checkequal(-1, 'тест', 'find', 'e') # english `e` + # test utf-8 non-ascii slice + self.checkequal(1, 'тест тест', 'find', 'ес') + self.checkequal(1, 'тест тест', 'find', 'ес', 1) + self.checkequal(1, 'тест тест', 'find', 'ес', 1, 3) + self.checkequal(6, 'тест тест', 'find', 'ес', 2) + self.checkequal(-1, 'тест тест', 'find', 'ес', 6, 7) + self.checkequal(-1, 'тест тест', 'find', 'ес', 7) + self.checkequal(-1, 'тест тест', 'find', 'ec') # english `ec` + self.assertRaises(TypeError, 'hello'.find) self.assertRaises(TypeError, 'hello'.find, 42) # test mixed kinds @@ -251,6 +264,19 @@ self.checkequalnofix(9, 'abcdefghiabc', 'rfind', 'abc') self.checkequalnofix(12, 'abcdefghiabc', 'rfind', '') self.checkequalnofix(12, 'abcdefghiabc', 'rfind', '') + # test utf-8 non-ascii char + self.checkequal(1, 'тест', 'rfind', 'е') + self.checkequal(1, 'тест', 'rfind', 'е', 1) + self.checkequal(-1, 'тест', 'rfind', 'е', 2) + self.checkequal(-1, 'тест', 'rfind', 'e') # english `e` + # test utf-8 non-ascii slice + self.checkequal(6, 'тест тест', 'rfind', 'ес') + self.checkequal(6, 'тест тест', 'rfind', 'ес', 1) + self.checkequal(1, 'тест тест', 'rfind', 'ес', 1, 3) + self.checkequal(6, 'тест тест', 'rfind', 'ес', 2) + self.checkequal(-1, 'тест тест', 'rfind', 'ес', 6, 7) + self.checkequal(-1, 'тест тест', 'rfind', 'ес', 7) + self.checkequal(-1, 'тест тест', 'rfind', 'ec') # english `ec` # test mixed kinds self.checkequal(0, 'a' + '\u0102' * 100, 'rfind', 'a') self.checkequal(0, 'a' + '\U00100304' * 100, 'rfind', 'a') @@ -1240,6 +1266,20 @@ self.assertRaises(ValueError, ("{" + big + "}").format) self.assertRaises(ValueError, ("{[" + big + "]}").format, [0]) + # test number formatter errors: + self.assertRaises(ValueError, '{0:x}'.format, 1j) + self.assertRaises(ValueError, '{0:x}'.format, 1.0) + self.assertRaises(ValueError, '{0:X}'.format, 1j) + self.assertRaises(ValueError, '{0:X}'.format, 1.0) + self.assertRaises(ValueError, '{0:o}'.format, 1j) + self.assertRaises(ValueError, '{0:o}'.format, 1.0) + self.assertRaises(ValueError, '{0:u}'.format, 1j) + self.assertRaises(ValueError, '{0:u}'.format, 1.0) + self.assertRaises(ValueError, '{0:i}'.format, 1j) + self.assertRaises(ValueError, '{0:i}'.format, 1.0) + self.assertRaises(ValueError, '{0:d}'.format, 1j) + self.assertRaises(ValueError, '{0:d}'.format, 1.0) + # issue 6089 self.assertRaises(ValueError, "{0[0]x}".format, [None]) self.assertRaises(ValueError, "{0[0](10)}".format, [None]) @@ -1475,11 +1515,31 @@ self.assertEqual('%X' % letter_m, '6D') self.assertEqual('%o' % letter_m, '155') self.assertEqual('%c' % letter_m, 'm') - self.assertRaisesRegex(TypeError, '%x format: an integer is required, not float', operator.mod, '%x', 3.14), - self.assertRaisesRegex(TypeError, '%X format: an integer is required, not float', operator.mod, '%X', 2.11), - self.assertRaisesRegex(TypeError, '%o format: an integer is required, not float', operator.mod, '%o', 1.79), - self.assertRaisesRegex(TypeError, '%x format: an integer is required, not PseudoFloat', operator.mod, '%x', pi), - self.assertRaises(TypeError, operator.mod, '%c', pi), + self.assertRaisesRegex(TypeError, '%x format: an integer is required, not float', operator.mod, '%x', 3.14) + self.assertRaisesRegex(TypeError, '%X format: an integer is required, not float', operator.mod, '%X', 2.11) + self.assertRaisesRegex(TypeError, '%o format: an integer is required, not float', operator.mod, '%o', 1.79) + self.assertRaisesRegex(TypeError, '%x format: an integer is required, not PseudoFloat', operator.mod, '%x', pi) + self.assertRaisesRegex(TypeError, '%x format: an integer is required, not complex', operator.mod, '%x', 3j) + self.assertRaisesRegex(TypeError, '%X format: an integer is required, not complex', operator.mod, '%X', 2j) + self.assertRaisesRegex(TypeError, '%o format: an integer is required, not complex', operator.mod, '%o', 1j) + self.assertRaisesRegex(TypeError, '%u format: a real number is required, not complex', operator.mod, '%u', 3j) + self.assertRaisesRegex(TypeError, '%i format: a real number is required, not complex', operator.mod, '%i', 2j) + self.assertRaisesRegex(TypeError, '%d format: a real number is required, not complex', operator.mod, '%d', 1j) + self.assertRaisesRegex(TypeError, '%c requires int or char', operator.mod, '%c', pi) + + class RaisingNumber: + def __int__(self): + raise RuntimeError('int') # should not be `TypeError` + def __index__(self): + raise RuntimeError('index') # should not be `TypeError` + + rn = RaisingNumber() + self.assertRaisesRegex(RuntimeError, 'int', operator.mod, '%d', rn) + self.assertRaisesRegex(RuntimeError, 'int', operator.mod, '%i', rn) + self.assertRaisesRegex(RuntimeError, 'int', operator.mod, '%u', rn) + self.assertRaisesRegex(RuntimeError, 'index', operator.mod, '%x', rn) + self.assertRaisesRegex(RuntimeError, 'index', operator.mod, '%X', rn) + self.assertRaisesRegex(RuntimeError, 'index', operator.mod, '%o', rn) def test_formatting_with_enum(self): # issue18780 @@ -2543,473 +2603,6 @@ self.assertEqual(proc.rc, 10, proc) -class CAPITest(unittest.TestCase): - - # Test PyUnicode_FromFormat() - def test_from_format(self): - import_helper.import_module('ctypes') - from ctypes import ( - c_char_p, - pythonapi, py_object, sizeof, - c_int, c_long, c_longlong, c_ssize_t, - c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) - name = "PyUnicode_FromFormat" - _PyUnicode_FromFormat = getattr(pythonapi, name) - _PyUnicode_FromFormat.argtypes = (c_char_p,) - _PyUnicode_FromFormat.restype = py_object - - def PyUnicode_FromFormat(format, *args): - cargs = tuple( - py_object(arg) if isinstance(arg, str) else arg - for arg in args) - return _PyUnicode_FromFormat(format, *cargs) - - def check_format(expected, format, *args): - text = PyUnicode_FromFormat(format, *args) - self.assertEqual(expected, text) - - # ascii format, non-ascii argument - check_format('ascii\x7f=unicode\xe9', - b'ascii\x7f=%U', 'unicode\xe9') - - # non-ascii format, ascii argument: ensure that PyUnicode_FromFormatV() - # raises an error - self.assertRaisesRegex(ValueError, - r'^PyUnicode_FromFormatV\(\) expects an ASCII-encoded format ' - 'string, got a non-ASCII byte: 0xe9$', - PyUnicode_FromFormat, b'unicode\xe9=%s', 'ascii') - - # test "%c" - check_format('\uabcd', - b'%c', c_int(0xabcd)) - check_format('\U0010ffff', - b'%c', c_int(0x10ffff)) - with self.assertRaises(OverflowError): - PyUnicode_FromFormat(b'%c', c_int(0x110000)) - # Issue #18183 - check_format('\U00010000\U00100000', - b'%c%c', c_int(0x10000), c_int(0x100000)) - - # test "%" - check_format('%', - b'%') - check_format('%', - b'%%') - check_format('%s', - b'%%s') - check_format('[%]', - b'[%%]') - check_format('%abc', - b'%%%s', b'abc') - - # truncated string - check_format('abc', - b'%.3s', b'abcdef') - check_format('abc[\ufffd', - b'%.5s', 'abc[\u20ac]'.encode('utf8')) - check_format("'\\u20acABC'", - b'%A', '\u20acABC') - check_format("'\\u20", - b'%.5A', '\u20acABCDEF') - check_format("'\u20acABC'", - b'%R', '\u20acABC') - check_format("'\u20acA", - b'%.3R', '\u20acABCDEF') - check_format('\u20acAB', - b'%.3S', '\u20acABCDEF') - check_format('\u20acAB', - b'%.3U', '\u20acABCDEF') - check_format('\u20acAB', - b'%.3V', '\u20acABCDEF', None) - check_format('abc[\ufffd', - b'%.5V', None, 'abc[\u20ac]'.encode('utf8')) - - # following tests comes from #7330 - # test width modifier and precision modifier with %S - check_format("repr= abc", - b'repr=%5S', 'abc') - check_format("repr=ab", - b'repr=%.2S', 'abc') - check_format("repr= ab", - b'repr=%5.2S', 'abc') - - # test width modifier and precision modifier with %R - check_format("repr= 'abc'", - b'repr=%8R', 'abc') - check_format("repr='ab", - b'repr=%.3R', 'abc') - check_format("repr= 'ab", - b'repr=%5.3R', 'abc') - - # test width modifier and precision modifier with %A - check_format("repr= 'abc'", - b'repr=%8A', 'abc') - check_format("repr='ab", - b'repr=%.3A', 'abc') - check_format("repr= 'ab", - b'repr=%5.3A', 'abc') - - # test width modifier and precision modifier with %s - check_format("repr= abc", - b'repr=%5s', b'abc') - check_format("repr=ab", - b'repr=%.2s', b'abc') - check_format("repr= ab", - b'repr=%5.2s', b'abc') - - # test width modifier and precision modifier with %U - check_format("repr= abc", - b'repr=%5U', 'abc') - check_format("repr=ab", - b'repr=%.2U', 'abc') - check_format("repr= ab", - b'repr=%5.2U', 'abc') - - # test width modifier and precision modifier with %V - check_format("repr= abc", - b'repr=%5V', 'abc', b'123') - check_format("repr=ab", - b'repr=%.2V', 'abc', b'123') - check_format("repr= ab", - b'repr=%5.2V', 'abc', b'123') - check_format("repr= 123", - b'repr=%5V', None, b'123') - check_format("repr=12", - b'repr=%.2V', None, b'123') - check_format("repr= 12", - b'repr=%5.2V', None, b'123') - - # test integer formats (%i, %d, %u) - check_format('010', - b'%03i', c_int(10)) - check_format('0010', - b'%0.4i', c_int(10)) - check_format('-123', - b'%i', c_int(-123)) - check_format('-123', - b'%li', c_long(-123)) - check_format('-123', - b'%lli', c_longlong(-123)) - check_format('-123', - b'%zi', c_ssize_t(-123)) - - check_format('-123', - b'%d', c_int(-123)) - check_format('-123', - b'%ld', c_long(-123)) - check_format('-123', - b'%lld', c_longlong(-123)) - check_format('-123', - b'%zd', c_ssize_t(-123)) - - check_format('123', - b'%u', c_uint(123)) - check_format('123', - b'%lu', c_ulong(123)) - check_format('123', - b'%llu', c_ulonglong(123)) - check_format('123', - b'%zu', c_size_t(123)) - - # test long output - min_longlong = -(2 ** (8 * sizeof(c_longlong) - 1)) - max_longlong = -min_longlong - 1 - check_format(str(min_longlong), - b'%lld', c_longlong(min_longlong)) - check_format(str(max_longlong), - b'%lld', c_longlong(max_longlong)) - max_ulonglong = 2 ** (8 * sizeof(c_ulonglong)) - 1 - check_format(str(max_ulonglong), - b'%llu', c_ulonglong(max_ulonglong)) - PyUnicode_FromFormat(b'%p', c_void_p(-1)) - - # test padding (width and/or precision) - check_format('123'.rjust(10, '0'), - b'%010i', c_int(123)) - check_format('123'.rjust(100), - b'%100i', c_int(123)) - check_format('123'.rjust(100, '0'), - b'%.100i', c_int(123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80i', c_int(123)) - - check_format('123'.rjust(10, '0'), - b'%010u', c_uint(123)) - check_format('123'.rjust(100), - b'%100u', c_uint(123)) - check_format('123'.rjust(100, '0'), - b'%.100u', c_uint(123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80u', c_uint(123)) - - check_format('123'.rjust(10, '0'), - b'%010x', c_int(0x123)) - check_format('123'.rjust(100), - b'%100x', c_int(0x123)) - check_format('123'.rjust(100, '0'), - b'%.100x', c_int(0x123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80x', c_int(0x123)) - - # test %A - check_format(r"%A:'abc\xe9\uabcd\U0010ffff'", - b'%%A:%A', 'abc\xe9\uabcd\U0010ffff') - - # test %V - check_format('repr=abc', - b'repr=%V', 'abc', b'xyz') - - # Test string decode from parameter of %s using utf-8. - # b'\xe4\xba\xba\xe6\xb0\x91' is utf-8 encoded byte sequence of - # '\u4eba\u6c11' - check_format('repr=\u4eba\u6c11', - b'repr=%V', None, b'\xe4\xba\xba\xe6\xb0\x91') - - #Test replace error handler. - check_format('repr=abc\ufffd', - b'repr=%V', None, b'abc\xff') - - # not supported: copy the raw format string. these tests are just here - # to check for crashes and should not be considered as specifications - check_format('%s', - b'%1%s', b'abc') - check_format('%1abc', - b'%1abc') - check_format('%+i', - b'%+i', c_int(10)) - check_format('%.%s', - b'%.%s', b'abc') - - # Issue #33817: empty strings - check_format('', - b'') - check_format('', - b'%s', b'') - - # Test PyUnicode_AsWideChar() - @support.cpython_only - def test_aswidechar(self): - from _testcapi import unicode_aswidechar - import_helper.import_module('ctypes') - from ctypes import c_wchar, sizeof - - wchar, size = unicode_aswidechar('abcdef', 2) - self.assertEqual(size, 2) - self.assertEqual(wchar, 'ab') - - wchar, size = unicode_aswidechar('abc', 3) - self.assertEqual(size, 3) - self.assertEqual(wchar, 'abc') - - wchar, size = unicode_aswidechar('abc', 4) - self.assertEqual(size, 3) - self.assertEqual(wchar, 'abc\0') - - wchar, size = unicode_aswidechar('abc', 10) - self.assertEqual(size, 3) - self.assertEqual(wchar, 'abc\0') - - wchar, size = unicode_aswidechar('abc\0def', 20) - self.assertEqual(size, 7) - self.assertEqual(wchar, 'abc\0def\0') - - nonbmp = chr(0x10ffff) - if sizeof(c_wchar) == 2: - buflen = 3 - nchar = 2 - else: # sizeof(c_wchar) == 4 - buflen = 2 - nchar = 1 - wchar, size = unicode_aswidechar(nonbmp, buflen) - self.assertEqual(size, nchar) - self.assertEqual(wchar, nonbmp + '\0') - - # Test PyUnicode_AsWideCharString() - @support.cpython_only - def test_aswidecharstring(self): - from _testcapi import unicode_aswidecharstring - import_helper.import_module('ctypes') - from ctypes import c_wchar, sizeof - - wchar, size = unicode_aswidecharstring('abc') - self.assertEqual(size, 3) - self.assertEqual(wchar, 'abc\0') - - wchar, size = unicode_aswidecharstring('abc\0def') - self.assertEqual(size, 7) - self.assertEqual(wchar, 'abc\0def\0') - - nonbmp = chr(0x10ffff) - if sizeof(c_wchar) == 2: - nchar = 2 - else: # sizeof(c_wchar) == 4 - nchar = 1 - wchar, size = unicode_aswidecharstring(nonbmp) - self.assertEqual(size, nchar) - self.assertEqual(wchar, nonbmp + '\0') - - # Test PyUnicode_AsUCS4() - @support.cpython_only - def test_asucs4(self): - from _testcapi import unicode_asucs4 - for s in ['abc', '\xa1\xa2', '\u4f60\u597d', 'a\U0001f600', - 'a\ud800b\udfffc', '\ud834\udd1e']: - l = len(s) - self.assertEqual(unicode_asucs4(s, l, True), s+'\0') - self.assertEqual(unicode_asucs4(s, l, False), s+'\uffff') - self.assertEqual(unicode_asucs4(s, l+1, True), s+'\0\uffff') - self.assertEqual(unicode_asucs4(s, l+1, False), s+'\0\uffff') - self.assertRaises(SystemError, unicode_asucs4, s, l-1, True) - self.assertRaises(SystemError, unicode_asucs4, s, l-2, False) - s = '\0'.join([s, s]) - self.assertEqual(unicode_asucs4(s, len(s), True), s+'\0') - self.assertEqual(unicode_asucs4(s, len(s), False), s+'\uffff') - - # Test PyUnicode_AsUTF8() - @support.cpython_only - def test_asutf8(self): - from _testcapi import unicode_asutf8 - - bmp = '\u0100' - bmp2 = '\uffff' - nonbmp = chr(0x10ffff) - - self.assertEqual(unicode_asutf8(bmp), b'\xc4\x80') - self.assertEqual(unicode_asutf8(bmp2), b'\xef\xbf\xbf') - self.assertEqual(unicode_asutf8(nonbmp), b'\xf4\x8f\xbf\xbf') - self.assertRaises(UnicodeEncodeError, unicode_asutf8, 'a\ud800b\udfffc') - - # Test PyUnicode_AsUTF8AndSize() - @support.cpython_only - def test_asutf8andsize(self): - from _testcapi import unicode_asutf8andsize - - bmp = '\u0100' - bmp2 = '\uffff' - nonbmp = chr(0x10ffff) - - self.assertEqual(unicode_asutf8andsize(bmp), (b'\xc4\x80', 2)) - self.assertEqual(unicode_asutf8andsize(bmp2), (b'\xef\xbf\xbf', 3)) - self.assertEqual(unicode_asutf8andsize(nonbmp), (b'\xf4\x8f\xbf\xbf', 4)) - self.assertRaises(UnicodeEncodeError, unicode_asutf8andsize, 'a\ud800b\udfffc') - - # Test PyUnicode_FindChar() - @support.cpython_only - def test_findchar(self): - from _testcapi import unicode_findchar - - for str in "\xa1", "\u8000\u8080", "\ud800\udc02", "\U0001f100\U0001f1f1": - for i, ch in enumerate(str): - self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), 1), i) - self.assertEqual(unicode_findchar(str, ord(ch), 0, len(str), -1), i) - - str = "!>_= end - self.assertEqual(unicode_findchar(str, ord('!'), 0, 0, 1), -1) - self.assertEqual(unicode_findchar(str, ord('!'), len(str), 0, 1), -1) - # negative - self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, 1), 0) - self.assertEqual(unicode_findchar(str, ord('!'), -len(str), -1, -1), 0) - - # Test PyUnicode_CopyCharacters() - @support.cpython_only - def test_copycharacters(self): - from _testcapi import unicode_copycharacters - - strings = [ - 'abcde', '\xa1\xa2\xa3\xa4\xa5', - '\u4f60\u597d\u4e16\u754c\uff01', - '\U0001f600\U0001f601\U0001f602\U0001f603\U0001f604' - ] - - for idx, from_ in enumerate(strings): - # wide -> narrow: exceed maxchar limitation - for to in strings[:idx]: - self.assertRaises( - SystemError, - unicode_copycharacters, to, 0, from_, 0, 5 - ) - # same kind - for from_start in range(5): - self.assertEqual( - unicode_copycharacters(from_, 0, from_, from_start, 5), - (from_[from_start:from_start+5].ljust(5, '\0'), - 5-from_start) - ) - for to_start in range(5): - self.assertEqual( - unicode_copycharacters(from_, to_start, from_, to_start, 5), - (from_[to_start:to_start+5].rjust(5, '\0'), - 5-to_start) - ) - # narrow -> wide - # Tests omitted since this creates invalid strings. - - s = strings[0] - self.assertRaises(IndexError, unicode_copycharacters, s, 6, s, 0, 5) - self.assertRaises(IndexError, unicode_copycharacters, s, -1, s, 0, 5) - self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, 6, 5) - self.assertRaises(IndexError, unicode_copycharacters, s, 0, s, -1, 5) - self.assertRaises(SystemError, unicode_copycharacters, s, 1, s, 0, 5) - self.assertRaises(SystemError, unicode_copycharacters, s, 0, s, 0, -1) - self.assertRaises(SystemError, unicode_copycharacters, s, 0, b'', 0, 0) - - @support.cpython_only - @support.requires_legacy_unicode_capi - def test_encode_decimal(self): - from _testcapi import unicode_encodedecimal - with warnings_helper.check_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - self.assertEqual(unicode_encodedecimal('123'), - b'123') - self.assertEqual(unicode_encodedecimal('\u0663.\u0661\u0664'), - b'3.14') - self.assertEqual(unicode_encodedecimal( - "\N{EM SPACE}3.14\N{EN SPACE}"), b' 3.14 ') - self.assertRaises(UnicodeEncodeError, - unicode_encodedecimal, "123\u20ac", "strict") - self.assertRaisesRegex( - ValueError, - "^'decimal' codec can't encode character", - unicode_encodedecimal, "123\u20ac", "replace") - - @support.cpython_only - @support.requires_legacy_unicode_capi - def test_transform_decimal(self): - from _testcapi import unicode_transformdecimaltoascii as transform_decimal - with warnings_helper.check_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - self.assertEqual(transform_decimal('123'), - '123') - self.assertEqual(transform_decimal('\u0663.\u0661\u0664'), - '3.14') - self.assertEqual(transform_decimal("\N{EM SPACE}3.14\N{EN SPACE}"), - "\N{EM SPACE}3.14\N{EN SPACE}") - self.assertEqual(transform_decimal('123\u20ac'), - '123\u20ac') - - @support.cpython_only - def test_pep393_utf8_caching_bug(self): - # Issue #25709: Problem with string concatenation and utf-8 cache - from _testcapi import getargs_s_hash - for k in 0x24, 0xa4, 0x20ac, 0x1f40d: - s = '' - for i in range(5): - # Due to CPython specific optimization the 's' string can be - # resized in-place. - s += chr(k) - # Parsing with the "s#" format code calls indirectly - # PyUnicode_AsUTF8AndSize() which creates the UTF-8 - # encoded string cached in the Unicode object. - self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1)) - # Check that the second call returns the same result - self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1)) - class StringModuleTest(unittest.TestCase): def test_formatter_parser(self): def parse(format): diff -Nru python3.10-3.10.7/Lib/test/test_unparse.py python3.10-3.10.12/Lib/test/test_unparse.py --- python3.10-3.10.7/Lib/test/test_unparse.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_unparse.py 2023-06-06 22:30:33.000000000 +0000 @@ -341,6 +341,12 @@ def test_invalid_yield_from(self): self.check_invalid(ast.YieldFrom(value=None)) + def test_import_from_level_none(self): + tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')]) + self.assertEqual(ast.unparse(tree), "from mod import x") + tree = ast.ImportFrom(module='mod', names=[ast.alias(name='x')], level=None) + self.assertEqual(ast.unparse(tree), "from mod import x") + def test_docstrings(self): docstrings = ( 'this ends with double quote"', diff -Nru python3.10-3.10.7/Lib/test/test_urllib2.py python3.10-3.10.12/Lib/test/test_urllib2.py --- python3.10-3.10.7/Lib/test/test_urllib2.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_urllib2.py 2023-06-06 22:30:33.000000000 +0000 @@ -1823,6 +1823,11 @@ expected_errmsg = '' % (err.code, err.msg) self.assertEqual(repr(err), expected_errmsg) + def test_gh_98778(self): + x = urllib.error.HTTPError("url", 405, "METHOD NOT ALLOWED", None, None) + self.assertEqual(getattr(x, "__notes__", ()), ()) + self.assertIsInstance(x.fp.read(), bytes) + def test_parse_proxy(self): parse_proxy_test_cases = [ ('proxy.example.com', diff -Nru python3.10-3.10.7/Lib/test/test_urlparse.py python3.10-3.10.12/Lib/test/test_urlparse.py --- python3.10-3.10.7/Lib/test/test_urlparse.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_urlparse.py 2023-06-06 22:30:33.000000000 +0000 @@ -649,17 +649,79 @@ self.assertEqual(p.scheme, "http") self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") + def test_urlsplit_strip_url(self): + noise = bytes(range(0, 0x20 + 1)) + base_url = "http://User:Pass@www.python.org:080/doc/?query=yes#frag" + + url = noise.decode("utf-8") + base_url + p = urllib.parse.urlsplit(url) + self.assertEqual(p.scheme, "http") + self.assertEqual(p.netloc, "User:Pass@www.python.org:080") + self.assertEqual(p.path, "/doc/") + self.assertEqual(p.query, "query=yes") + self.assertEqual(p.fragment, "frag") + self.assertEqual(p.username, "User") + self.assertEqual(p.password, "Pass") + self.assertEqual(p.hostname, "www.python.org") + self.assertEqual(p.port, 80) + self.assertEqual(p.geturl(), base_url) + + url = noise + base_url.encode("utf-8") + p = urllib.parse.urlsplit(url) + self.assertEqual(p.scheme, b"http") + self.assertEqual(p.netloc, b"User:Pass@www.python.org:080") + self.assertEqual(p.path, b"/doc/") + self.assertEqual(p.query, b"query=yes") + self.assertEqual(p.fragment, b"frag") + self.assertEqual(p.username, b"User") + self.assertEqual(p.password, b"Pass") + self.assertEqual(p.hostname, b"www.python.org") + self.assertEqual(p.port, 80) + self.assertEqual(p.geturl(), base_url.encode("utf-8")) + + # Test that trailing space is preserved as some applications rely on + # this within query strings. + query_spaces_url = "https://www.python.org:88/doc/?query= " + p = urllib.parse.urlsplit(noise.decode("utf-8") + query_spaces_url) + self.assertEqual(p.scheme, "https") + self.assertEqual(p.netloc, "www.python.org:88") + self.assertEqual(p.path, "/doc/") + self.assertEqual(p.query, "query= ") + self.assertEqual(p.port, 88) + self.assertEqual(p.geturl(), query_spaces_url) + + p = urllib.parse.urlsplit("www.pypi.org ") + # That "hostname" gets considered a "path" due to the + # trailing space and our existing logic... YUCK... + # and re-assembles via geturl aka unurlsplit into the original. + # django.core.validators.URLValidator (at least through v3.2) relies on + # this, for better or worse, to catch it in a ValidationError via its + # regular expressions. + # Here we test the basic round trip concept of such a trailing space. + self.assertEqual(urllib.parse.urlunsplit(p), "www.pypi.org ") + + # with scheme as cache-key + url = "//www.python.org/" + scheme = noise.decode("utf-8") + "https" + noise.decode("utf-8") + for _ in range(2): + p = urllib.parse.urlsplit(url, scheme=scheme) + self.assertEqual(p.scheme, "https") + self.assertEqual(p.geturl(), "https://www.python.org/") + def test_attributes_bad_port(self): """Check handling of invalid ports.""" for bytes in (False, True): for parse in (urllib.parse.urlsplit, urllib.parse.urlparse): - for port in ("foo", "1.5", "-1", "0x10"): + for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"): with self.subTest(bytes=bytes, parse=parse, port=port): netloc = "www.example.net:" + port - url = "http://" + netloc + url = "http://" + netloc + "/" if bytes: - netloc = netloc.encode("ascii") - url = url.encode("ascii") + if netloc.isascii() and port.isascii(): + netloc = netloc.encode("ascii") + url = url.encode("ascii") + else: + continue p = parse(url) self.assertEqual(p.netloc, netloc) with self.assertRaises(ValueError): @@ -1186,6 +1248,7 @@ self.assertEqual(splitnport('127.0.0.1', 55), ('127.0.0.1', 55)) self.assertEqual(splitnport('parrot:cheese'), ('parrot', None)) self.assertEqual(splitnport('parrot:cheese', 55), ('parrot', None)) + self.assertEqual(splitnport('parrot: +1_0 '), ('parrot', None)) def test_splitquery(self): # Normal cases are exercised by other tests; ensure that we also diff -Nru python3.10-3.10.7/Lib/test/test_uu.py python3.10-3.10.12/Lib/test/test_uu.py --- python3.10-3.10.7/Lib/test/test_uu.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_uu.py 2023-06-06 22:30:33.000000000 +0000 @@ -145,6 +145,34 @@ uu.encode(inp, out, filename) self.assertIn(safefilename, out.getvalue()) + def test_no_directory_traversal(self): + relative_bad = b"""\ +begin 644 ../../../../../../../../tmp/test1 +$86)C"@`` +` +end +""" + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(relative_bad)) + if os.altsep: + relative_bad_bs = relative_bad.replace(b'/', b'\\') + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(relative_bad_bs)) + + absolute_bad = b"""\ +begin 644 /tmp/test2 +$86)C"@`` +` +end +""" + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(absolute_bad)) + if os.altsep: + absolute_bad_bs = absolute_bad.replace(b'/', b'\\') + with self.assertRaisesRegex(uu.Error, 'directory'): + uu.decode(io.BytesIO(absolute_bad_bs)) + + class UUStdIOTest(unittest.TestCase): def setUp(self): diff -Nru python3.10-3.10.7/Lib/test/test_venv.py python3.10-3.10.12/Lib/test/test_venv.py --- python3.10-3.10.7/Lib/test/test_venv.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_venv.py 2023-06-06 22:30:33.000000000 +0000 @@ -159,7 +159,7 @@ if sys.platform == 'win32': expect_exe = os.path.normcase(os.path.realpath(expect_exe)) - def pip_cmd_checker(cmd): + def pip_cmd_checker(cmd, **kwargs): cmd[0] = os.path.normcase(cmd[0]) self.assertEqual( cmd, @@ -175,7 +175,7 @@ ) fake_context = builder.ensure_directories(fake_env_dir) - with patch('venv.subprocess.check_call', pip_cmd_checker): + with patch('venv.subprocess.check_output', pip_cmd_checker): builder.upgrade_dependencies(fake_context) @requireVenvCreate @@ -547,8 +547,8 @@ try: yield except subprocess.CalledProcessError as exc: - out = exc.output.decode(errors="replace") - err = exc.stderr.decode(errors="replace") + out = (exc.output or b'').decode(errors="replace") + err = (exc.stderr or b'').decode(errors="replace") self.fail( f"{exc}\n\n" f"**Subprocess Output**\n{out}\n\n" diff -Nru python3.10-3.10.7/Lib/test/test_weakref.py python3.10-3.10.12/Lib/test/test_weakref.py --- python3.10-3.10.7/Lib/test/test_weakref.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_weakref.py 2023-06-06 22:30:33.000000000 +0000 @@ -595,7 +595,7 @@ # deallocation of c2. del c2 - def test_callback_in_cycle_1(self): + def test_callback_in_cycle(self): import gc class J(object): @@ -635,40 +635,11 @@ del I, J, II gc.collect() - def test_callback_in_cycle_2(self): + def test_callback_reachable_one_way(self): import gc - # This is just like test_callback_in_cycle_1, except that II is an - # old-style class. The symptom is different then: an instance of an - # old-style class looks in its own __dict__ first. 'J' happens to - # get cleared from I.__dict__ before 'wr', and 'J' was never in II's - # __dict__, so the attribute isn't found. The difference is that - # the old-style II doesn't have a NULL __mro__ (it doesn't have any - # __mro__), so no segfault occurs. Instead it got: - # test_callback_in_cycle_2 (__main__.ReferencesTestCase) ... - # Exception exceptions.AttributeError: - # "II instance has no attribute 'J'" in > ignored - - class J(object): - pass - - class II: - def acallback(self, ignore): - self.J - - I = II() - I.J = J - I.wr = weakref.ref(J, I.acallback) - - del I, J, II - gc.collect() - - def test_callback_in_cycle_3(self): - import gc - - # This one broke the first patch that fixed the last two. In this - # case, the objects reachable from the callback aren't also reachable + # This one broke the first patch that fixed the previous test. In this case, + # the objects reachable from the callback aren't also reachable # from the object (c1) *triggering* the callback: you can get to # c1 from c2, but not vice-versa. The result was that c2's __dict__ # got tp_clear'ed by the time the c2.cb callback got invoked. @@ -688,10 +659,10 @@ del c1, c2 gc.collect() - def test_callback_in_cycle_4(self): + def test_callback_different_classes(self): import gc - # Like test_callback_in_cycle_3, except c2 and c1 have different + # Like test_callback_reachable_one_way, except c2 and c1 have different # classes. c2's class (C) isn't reachable from c1 then, so protecting # objects reachable from the dying object (c1) isn't enough to stop # c2's class (C) from getting tp_clear'ed before c2.cb is invoked. diff -Nru python3.10-3.10.7/Lib/test/test_winreg.py python3.10-3.10.12/Lib/test/test_winreg.py --- python3.10-3.10.7/Lib/test/test_winreg.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_winreg.py 2023-06-06 22:30:33.000000000 +0000 @@ -113,7 +113,6 @@ "does not close the actual key!") except OSError: pass - def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey): # Check we can get default value for this key. val = QueryValue(root_key, test_key_name) @@ -340,6 +339,23 @@ finally: DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_setvalueex_negative_one_check(self): + # Test for Issue #43984, check -1 was not set by SetValueEx. + # Py2Reg, which gets called by SetValueEx, wasn't checking return + # value by PyLong_AsUnsignedLong, thus setting -1 as value in the registry. + # The implementation now checks PyLong_AsUnsignedLong return value to assure + # the value set was not -1. + try: + with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: + with self.assertRaises(OverflowError): + SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1) + SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1) + self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword") + self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword") + + finally: + DeleteKey(HKEY_CURRENT_USER, test_key_name) + def test_queryvalueex_return_value(self): # Test for Issue #16759, return unsigned int from QueryValueEx. # Reg2Py, which gets called by QueryValueEx, was returning a value diff -Nru python3.10-3.10.7/Lib/test/test_xml_etree.py python3.10-3.10.12/Lib/test/test_xml_etree.py --- python3.10-3.10.7/Lib/test/test_xml_etree.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_xml_etree.py 2023-06-06 22:30:33.000000000 +0000 @@ -203,25 +203,6 @@ def test_interface(self): # Test element tree interface. - def check_string(string): - len(string) - for char in string: - self.assertEqual(len(char), 1, - msg="expected one-character string, got %r" % char) - new_string = string + "" - new_string = string + " " - string[:0] - - def check_mapping(mapping): - len(mapping) - keys = mapping.keys() - items = mapping.items() - for key in keys: - item = mapping[key] - mapping["key"] = "value" - self.assertEqual(mapping["key"], "value", - msg="expected value string, got %r" % mapping["key"]) - def check_element(element): self.assertTrue(ET.iselement(element), msg="not an element") direlem = dir(element) @@ -231,12 +212,12 @@ self.assertIn(attr, direlem, msg='no %s visible by dir' % attr) - check_string(element.tag) - check_mapping(element.attrib) + self.assertIsInstance(element.tag, str) + self.assertIsInstance(element.attrib, dict) if element.text is not None: - check_string(element.text) + self.assertIsInstance(element.text, str) if element.tail is not None: - check_string(element.tail) + self.assertIsInstance(element.tail, str) for elem in element: check_element(elem) diff -Nru python3.10-3.10.7/Lib/test/test_zipfile.py python3.10-3.10.12/Lib/test/test_zipfile.py --- python3.10-3.10.7/Lib/test/test_zipfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/test/test_zipfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -10,6 +10,7 @@ import struct import subprocess import sys +from test.support.script_helper import assert_python_ok import time import unittest import unittest.mock as mock @@ -2933,7 +2934,69 @@ a, b, g = root.iterdir() with a.open(encoding="utf-8") as strm: data = strm.read() - assert data == "content of a" + self.assertEqual(data, "content of a") + with a.open('r', "utf-8") as strm: # not a kw, no gh-101144 TypeError + data = strm.read() + self.assertEqual(data, "content of a") + + def test_open_encoding_utf16(self): + in_memory_file = io.BytesIO() + zf = zipfile.ZipFile(in_memory_file, "w") + zf.writestr("path/16.txt", "This was utf-16".encode("utf-16")) + zf.filename = "test_open_utf16.zip" + root = zipfile.Path(zf) + (path,) = root.iterdir() + u16 = path.joinpath("16.txt") + with u16.open('r', "utf-16") as strm: + data = strm.read() + self.assertEqual(data, "This was utf-16") + with u16.open(encoding="utf-16") as strm: + data = strm.read() + self.assertEqual(data, "This was utf-16") + + def test_open_encoding_errors(self): + in_memory_file = io.BytesIO() + zf = zipfile.ZipFile(in_memory_file, "w") + zf.writestr("path/bad-utf8.bin", b"invalid utf-8: \xff\xff.") + zf.filename = "test_read_text_encoding_errors.zip" + root = zipfile.Path(zf) + (path,) = root.iterdir() + u16 = path.joinpath("bad-utf8.bin") + + # encoding= as a positional argument for gh-101144. + data = u16.read_text("utf-8", errors="ignore") + self.assertEqual(data, "invalid utf-8: .") + with u16.open("r", "utf-8", errors="surrogateescape") as f: + self.assertEqual(f.read(), "invalid utf-8: \udcff\udcff.") + + # encoding= both positional and keyword is an error; gh-101144. + with self.assertRaisesRegex(TypeError, "encoding"): + data = u16.read_text("utf-8", encoding="utf-8") + + # both keyword arguments work. + with u16.open("r", encoding="utf-8", errors="strict") as f: + # error during decoding with wrong codec. + with self.assertRaises(UnicodeDecodeError): + f.read() + + def test_encoding_warnings(self): + """EncodingWarning must blame the read_text and open calls.""" + code = '''\ +import io, zipfile +with zipfile.ZipFile(io.BytesIO(), "w") as zf: + zf.filename = '' + zf.writestr("path/file.txt", b"Spanish Inquisition") + root = zipfile.Path(zf) + (path,) = root.iterdir() + file_path = path.joinpath("file.txt") + unused = file_path.read_text() # should warn + file_path.open("r").close() # should warn +''' + proc = assert_python_ok('-X', 'warn_default_encoding', '-c', code) + warnings = proc.err.splitlines() + self.assertEqual(len(warnings), 2, proc.err) + self.assertRegex(warnings[0], rb"^:8: EncodingWarning:") + self.assertRegex(warnings[1], rb"^:9: EncodingWarning:") def test_open_write(self): """ @@ -2975,6 +3038,7 @@ root = zipfile.Path(alpharep) a, b, g = root.iterdir() assert a.read_text(encoding="utf-8") == "content of a" + a.read_text("utf-8") # No positional arg TypeError per gh-101144. assert a.read_bytes() == b"content of a" @pass_alpharep @@ -3145,6 +3209,79 @@ file = cls(alpharep).joinpath('some dir').parent assert isinstance(file, cls) + @pass_alpharep + def test_extract_orig_with_implied_dirs(self, alpharep): + """ + A zip file wrapped in a Path should extract even with implied dirs. + """ + source_path = self.zipfile_ondisk(alpharep) + zf = zipfile.ZipFile(source_path) + # wrap the zipfile for its side effect + zipfile.Path(zf) + zf.extractall(source_path.parent) + + +class StripExtraTests(unittest.TestCase): + # Note: all of the "z" characters are technically invalid, but up + # to 3 bytes at the end of the extra will be passed through as they + # are too short to encode a valid extra. + + ZIP64_EXTRA = 1 + + def test_no_data(self): + s = struct.Struct(" 5 and name[-6] == "_" and name[-5:].lower() == "proxy": + value = os.environ[name] + proxy_name = name[:-6].lower() + environment.append((name, value, proxy_name)) + if value: + proxies[proxy_name] = value # CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY # (non-all-lowercase) as it may be set from the web server by a "Proxy:" # header from the client # If "proxy" is lowercase, it will still be used thanks to the next block if 'REQUEST_METHOD' in os.environ: proxies.pop('http', None) - for name, value in os.environ.items(): + for name, value, proxy_name in environment: + # not case-folded, checking here for lower-case env vars only if name[-6:] == '_proxy': - name = name.lower() if value: - proxies[name[:-6]] = value + proxies[proxy_name] = value else: - proxies.pop(name[:-6], None) + proxies.pop(proxy_name, None) return proxies def proxy_bypass_environment(host, proxies=None): diff -Nru python3.10-3.10.7/Lib/uuid.py python3.10-3.10.12/Lib/uuid.py --- python3.10-3.10.7/Lib/uuid.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/uuid.py 2023-06-06 22:30:33.000000000 +0000 @@ -370,7 +370,12 @@ # for are actually localized, but in theory some system could do so.) env = dict(os.environ) env['LC_ALL'] = 'C' - proc = subprocess.Popen((executable,) + args, + # Empty strings will be quoted by popen so we should just ommit it + if args != ('',): + command = (executable, *args) + else: + command = (executable,) + proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, env=env) @@ -510,7 +515,7 @@ mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1) if mac: return mac - return None + return None def _ip_getnode(): """Get the hardware address on Unix by running ip.""" diff -Nru python3.10-3.10.7/Lib/uu.py python3.10-3.10.12/Lib/uu.py --- python3.10-3.10.7/Lib/uu.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/uu.py 2023-06-06 22:30:33.000000000 +0000 @@ -130,7 +130,14 @@ # If the filename isn't ASCII, what's up with that?!? out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii") if os.path.exists(out_file): - raise Error('Cannot overwrite existing file: %s' % out_file) + raise Error(f'Cannot overwrite existing file: {out_file}') + if (out_file.startswith(os.sep) or + f'..{os.sep}' in out_file or ( + os.altsep and + (out_file.startswith(os.altsep) or + f'..{os.altsep}' in out_file)) + ): + raise Error(f'Refusing to write to {out_file} due to directory traversal') if mode is None: mode = int(hdrfields[1], 8) # diff -Nru python3.10-3.10.7/Lib/venv/__init__.py python3.10-3.10.12/Lib/venv/__init__.py --- python3.10-3.10.7/Lib/venv/__init__.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/venv/__init__.py 2023-06-06 22:30:33.000000000 +0000 @@ -115,6 +115,11 @@ context.prompt = '(%s) ' % prompt create_if_needed(env_dir) executable = sys._base_executable + if not executable: # see gh-96861 + raise ValueError('Unable to determine path to the running ' + 'Python interpreter. Provide an explicit path or ' + 'check that your PATH environment variable is ' + 'correctly set.') dirname, exename = os.path.split(os.path.abspath(executable)) context.executable = executable context.python_dir = dirname @@ -303,14 +308,25 @@ shutil.copyfile(src, dst) break + def _call_new_python(self, context, *py_args, **kwargs): + """Executes the newly created Python using safe-ish options""" + # gh-98251: We do not want to just use '-I' because that masks + # legitimate user preferences (such as not writing bytecode). All we + # really need is to ensure that the path variables do not overrule + # normal venv handling. + args = [context.env_exec_cmd, *py_args] + kwargs['env'] = env = os.environ.copy() + env['VIRTUAL_ENV'] = context.env_dir + env.pop('PYTHONHOME', None) + env.pop('PYTHONPATH', None) + kwargs['cwd'] = context.env_dir + kwargs['executable'] = context.env_exec_cmd + subprocess.check_output(args, **kwargs) + def _setup_pip(self, context): """Installs or upgrades pip in a virtual environment""" - # We run ensurepip in isolated mode to avoid side effects from - # environment vars, the current directory and anything else - # intended for the global Python environment - cmd = [context.env_exec_cmd, '-Im', 'ensurepip', '--upgrade', - '--default-pip'] - subprocess.check_output(cmd, stderr=subprocess.STDOUT) + self._call_new_python(context, '-m', 'ensurepip', '--upgrade', + '--default-pip', stderr=subprocess.STDOUT) def setup_scripts(self, context): """ @@ -409,9 +425,8 @@ logger.debug( f'Upgrading {CORE_VENV_DEPS} packages in {context.bin_path}' ) - cmd = [context.env_exec_cmd, '-m', 'pip', 'install', '--upgrade'] - cmd.extend(CORE_VENV_DEPS) - subprocess.check_call(cmd) + self._call_new_python(context, '-m', 'pip', 'install', '--upgrade', + *CORE_VENV_DEPS) def create(env_dir, system_site_packages=False, clear=False, diff -Nru python3.10-3.10.7/Lib/venv/scripts/posix/activate.fish python3.10-3.10.12/Lib/venv/scripts/posix/activate.fish --- python3.10-3.10.7/Lib/venv/scripts/posix/activate.fish 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/venv/scripts/posix/activate.fish 2023-06-06 22:30:33.000000000 +0000 @@ -13,10 +13,13 @@ end if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - functions -e fish_prompt set -e _OLD_FISH_PROMPT_OVERRIDE - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end end set -e VIRTUAL_ENV diff -Nru python3.10-3.10.7/Lib/wsgiref/validate.py python3.10-3.10.12/Lib/wsgiref/validate.py --- python3.10-3.10.7/Lib/wsgiref/validate.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/wsgiref/validate.py 2023-06-06 22:30:33.000000000 +0000 @@ -1,6 +1,6 @@ # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php -# Also licenced under the Apache License, 2.0: http://opensource.org/licenses/apache2.0.php +# Licensed under the MIT license: https://opensource.org/licenses/mit-license.php +# Also licenced under the Apache License, 2.0: https://opensource.org/licenses/apache2.0.php # Licensed to PSF under a Contributor Agreement """ Middleware to check for obedience to the WSGI specification. diff -Nru python3.10-3.10.7/Lib/zipfile.py python3.10-3.10.12/Lib/zipfile.py --- python3.10-3.10.7/Lib/zipfile.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/zipfile.py 2023-06-06 22:30:33.000000000 +0000 @@ -185,6 +185,8 @@ i = j if not modified: return extra + if start != len(extra): + buffer.append(extra[start:]) return b''.join(buffer) def _check_zipfile(fp): @@ -2197,6 +2199,17 @@ dir_match = name not in names and dirname in names return dirname if dir_match else name + def getinfo(self, name): + """ + Supplement getinfo for implied dirs. + """ + try: + return super().getinfo(name) + except KeyError: + if not name.endswith('/') or name not in self._name_set(): + raise + return ZipInfo(filename=name) + @classmethod def make(cls, source): """ @@ -2236,6 +2249,11 @@ return self.__lookup +def _extract_text_encoding(encoding=None, *args, **kwargs): + # stacklevel=3 so that the caller of the caller see any warning. + return io.text_encoding(encoding, 3), args, kwargs + + class Path: """ A pathlib-compatible interface for zip files. @@ -2345,9 +2363,9 @@ if args or kwargs: raise ValueError("encoding args invalid for binary operation") return stream - else: - kwargs["encoding"] = io.text_encoding(kwargs.get("encoding")) - return io.TextIOWrapper(stream, *args, **kwargs) + # Text mode: + encoding, args, kwargs = _extract_text_encoding(*args, **kwargs) + return io.TextIOWrapper(stream, encoding, *args, **kwargs) @property def name(self): @@ -2358,8 +2376,8 @@ return pathlib.Path(self.root.filename).joinpath(self.at) def read_text(self, *args, **kwargs): - kwargs["encoding"] = io.text_encoding(kwargs.get("encoding")) - with self.open('r', *args, **kwargs) as strm: + encoding, args, kwargs = _extract_text_encoding(*args, **kwargs) + with self.open('r', encoding, *args, **kwargs) as strm: return strm.read() def read_bytes(self): diff -Nru python3.10-3.10.7/Lib/zipimport.py python3.10-3.10.12/Lib/zipimport.py --- python3.10-3.10.7/Lib/zipimport.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/zipimport.py 2023-06-06 22:30:33.000000000 +0000 @@ -406,114 +406,121 @@ raise ZipImportError(f"can't open Zip file: {archive!r}", path=archive) with fp: + # GH-87235: On macOS all file descriptors for /dev/fd/N share the same + # file offset, reset the file offset after scanning the zipfile diretory + # to not cause problems when some runs 'python3 /dev/fd/9 9 header_offset: - raise ZipImportError(f'bad local header offset: {archive!r}', path=archive) - file_offset += arc_offset - - try: - name = fp.read(name_size) + fp.seek(-END_CENTRAL_DIR_SIZE, 2) + header_position = fp.tell() + buffer = fp.read(END_CENTRAL_DIR_SIZE) except OSError: raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) - if len(name) != name_size: + if len(buffer) != END_CENTRAL_DIR_SIZE: raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) - # On Windows, calling fseek to skip over the fields we don't use is - # slower than reading the data because fseek flushes stdio's - # internal buffers. See issue #8745. + if buffer[:4] != STRING_END_ARCHIVE: + # Bad: End of Central Dir signature + # Check if there's a comment. + try: + fp.seek(0, 2) + file_size = fp.tell() + except OSError: + raise ZipImportError(f"can't read Zip file: {archive!r}", + path=archive) + max_comment_start = max(file_size - MAX_COMMENT_LEN - + END_CENTRAL_DIR_SIZE, 0) + try: + fp.seek(max_comment_start) + data = fp.read() + except OSError: + raise ZipImportError(f"can't read Zip file: {archive!r}", + path=archive) + pos = data.rfind(STRING_END_ARCHIVE) + if pos < 0: + raise ZipImportError(f'not a Zip file: {archive!r}', + path=archive) + buffer = data[pos:pos+END_CENTRAL_DIR_SIZE] + if len(buffer) != END_CENTRAL_DIR_SIZE: + raise ZipImportError(f"corrupt Zip file: {archive!r}", + path=archive) + header_position = file_size - len(data) + pos + + header_size = _unpack_uint32(buffer[12:16]) + header_offset = _unpack_uint32(buffer[16:20]) + if header_position < header_size: + raise ZipImportError(f'bad central directory size: {archive!r}', path=archive) + if header_position < header_offset: + raise ZipImportError(f'bad central directory offset: {archive!r}', path=archive) + header_position -= header_size + arc_offset = header_position - header_offset + if arc_offset < 0: + raise ZipImportError(f'bad central directory size or offset: {archive!r}', path=archive) + + files = {} + # Start of Central Directory + count = 0 try: - if len(fp.read(header_size - name_size)) != header_size - name_size: - raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + fp.seek(header_position) except OSError: raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + while True: + buffer = fp.read(46) + if len(buffer) < 4: + raise EOFError('EOF read where not expected') + # Start of file header + if buffer[:4] != b'PK\x01\x02': + break # Bad: Central Dir File Header + if len(buffer) != 46: + raise EOFError('EOF read where not expected') + flags = _unpack_uint16(buffer[8:10]) + compress = _unpack_uint16(buffer[10:12]) + time = _unpack_uint16(buffer[12:14]) + date = _unpack_uint16(buffer[14:16]) + crc = _unpack_uint32(buffer[16:20]) + data_size = _unpack_uint32(buffer[20:24]) + file_size = _unpack_uint32(buffer[24:28]) + name_size = _unpack_uint16(buffer[28:30]) + extra_size = _unpack_uint16(buffer[30:32]) + comment_size = _unpack_uint16(buffer[32:34]) + file_offset = _unpack_uint32(buffer[42:46]) + header_size = name_size + extra_size + comment_size + if file_offset > header_offset: + raise ZipImportError(f'bad local header offset: {archive!r}', path=archive) + file_offset += arc_offset - if flags & 0x800: - # UTF-8 file names extension - name = name.decode() - else: - # Historical ZIP filename encoding try: - name = name.decode('ascii') - except UnicodeDecodeError: - name = name.decode('latin1').translate(cp437_table) - - name = name.replace('/', path_sep) - path = _bootstrap_external._path_join(archive, name) - t = (path, compress, data_size, file_size, file_offset, time, date, crc) - files[name] = t - count += 1 + name = fp.read(name_size) + except OSError: + raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + if len(name) != name_size: + raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + # On Windows, calling fseek to skip over the fields we don't use is + # slower than reading the data because fseek flushes stdio's + # internal buffers. See issue #8745. + try: + if len(fp.read(header_size - name_size)) != header_size - name_size: + raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + except OSError: + raise ZipImportError(f"can't read Zip file: {archive!r}", path=archive) + + if flags & 0x800: + # UTF-8 file names extension + name = name.decode() + else: + # Historical ZIP filename encoding + try: + name = name.decode('ascii') + except UnicodeDecodeError: + name = name.decode('latin1').translate(cp437_table) + + name = name.replace('/', path_sep) + path = _bootstrap_external._path_join(archive, name) + t = (path, compress, data_size, file_size, file_offset, time, date, crc) + files[name] = t + count += 1 + finally: + fp.seek(start_offset) _bootstrap._verbose_message('zipimport: found {} names in {!r}', count, archive) return files diff -Nru python3.10-3.10.7/Lib/zoneinfo/_zoneinfo.py python3.10-3.10.12/Lib/zoneinfo/_zoneinfo.py --- python3.10-3.10.7/Lib/zoneinfo/_zoneinfo.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Lib/zoneinfo/_zoneinfo.py 2023-06-06 22:30:33.000000000 +0000 @@ -302,7 +302,7 @@ # difference between utcoffset() and the "standard" offset, but # the "base offset" and "DST offset" are not encoded in the file; # we can infer what they are from the isdst flag, but it is not - # sufficient to to just look at the last standard offset, because + # sufficient to just look at the last standard offset, because # occasionally countries will shift both DST offset and base offset. typecnt = len(isdsts) diff -Nru python3.10-3.10.7/LICENSE python3.10-3.10.12/LICENSE --- python3.10-3.10.7/LICENSE 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/LICENSE 2023-06-06 22:30:33.000000000 +0000 @@ -2,12 +2,12 @@ ========================== Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others. In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software. @@ -19,7 +19,7 @@ created specifically to own Python-related Intellectual Property. Zope Corporation was a sponsoring member of the PSF. -All Python releases are Open Source (see http://www.opensource.org for +All Python releases are Open Source (see https://opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases. @@ -84,7 +84,7 @@ distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Python Software Foundation; +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. diff -Nru python3.10-3.10.7/Mac/BuildScript/build-installer.py python3.10-3.10.12/Mac/BuildScript/build-installer.py --- python3.10-3.10.7/Mac/BuildScript/build-installer.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/BuildScript/build-installer.py 2023-06-06 22:30:33.000000000 +0000 @@ -246,9 +246,9 @@ result.extend([ dict( - name="OpenSSL 1.1.1q", - url="https://www.openssl.org/source/openssl-1.1.1q.tar.gz", - checksum='d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca', + name="OpenSSL 1.1.1u", + url="https://www.openssl.org/source/openssl-1.1.1u.tar.gz", + checksum='e2f8d84b523eecd06c7be7626830370300fbcc15386bf5142d72758f6963ebc6', buildrecipe=build_universal_openssl, configure=None, install=None, @@ -358,9 +358,9 @@ ), ), dict( - name="SQLite 3.37.2", - url="https://sqlite.org/2022/sqlite-autoconf-3370200.tar.gz", - checksum='683cc5312ee74e71079c14d24b7a6d27', + name="SQLite 3.40.1", + url="https://sqlite.org/2022/sqlite-autoconf-3400100.tar.gz", + checksum="42175b1a1d23529cb133bbd2b5900afd", extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff -Nru python3.10-3.10.7/Mac/BuildScript/resources/License.rtf python3.10-3.10.12/Mac/BuildScript/resources/License.rtf --- python3.10-3.10.7/Mac/BuildScript/resources/License.rtf 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/BuildScript/resources/License.rtf 2023-06-06 22:30:33.000000000 +0000 @@ -12,13 +12,13 @@ HISTORY OF THE SOFTWARE\ \f1\b0 \ulnone \ -Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others.\ +Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others.\ \ -In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software.\ +In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software.\ \ -In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.org). In 2001, the Python Software Foundation (PSF, see https://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF.\ +In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see https://www.zope.dev). In 2001, the Python Software Foundation (PSF, see https://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF.\ \ -All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases.\ +All Python releases are Open Source (see https://opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases.\ \ \f2\b Release Derived Year Owner GPL-\ diff -Nru python3.10-3.10.7/Mac/BuildScript/resources/Welcome.rtf python3.10-3.10.12/Mac/BuildScript/resources/Welcome.rtf --- python3.10-3.10.7/Mac/BuildScript/resources/Welcome.rtf 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/BuildScript/resources/Welcome.rtf 2023-06-06 22:30:33.000000000 +0000 @@ -1,9 +1,9 @@ -{\rtf1\ansi\ansicpg1252\cocoartf2580 +{\rtf1\ansi\ansicpg1252\cocoartf2708 \cocoascreenfonts1\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fmodern\fcharset0 CourierNewPSMT; } {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} -\paperw11900\paperh16840\margl1440\margr1440\vieww12200\viewh10880\viewkind0 +\margl1440\margr1440\vieww12200\viewh10880\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 \f0\fs24 \cf0 This package will install @@ -23,4 +23,27 @@ At the end of this install, click on \f2 Install Certificates \f0 to install a set of current SSL root certificates.\ +\ + +\f1\b macOS 13 Ventura users +\f0\b0 : Due to an issue with the macOS +\f1\b Installer +\f0\b0 app, installation of some third-party packages including this Python package may fail with a vague +\f1\b "The installer encountered an error" +\f0\b0 message if the +\f1\b Installer +\f0\b0 app does not have permission to access the folder containing the downloaded installer file, typically in the +\f1\b Downloads +\f0\b0 folder. Go to +\f1\b System Settings +\f0\b0 -> +\f1\b Privacy & Security +\f0\b0 -> +\f1\b Files and Folders +\f0\b0 , then click the mark in front of +\f1\b Installer +\f0\b0 to expand, and enable +\f1\b Downloads Folder +\f0\b0 by moving the toggle to the right. See {\field{\*\fldinst{HYPERLINK "https://github.com/python/cpython/issues/103207"}}{\fldrslt https://github.com/python/cpython/issues/103207}} for up-to-date information on this issue.\ +\ } \ No newline at end of file diff -Nru python3.10-3.10.7/Mac/IDLE/IDLE.app/Contents/Info.plist python3.10-3.10.12/Mac/IDLE/IDLE.app/Contents/Info.plist --- python3.10-3.10.7/Mac/IDLE/IDLE.app/Contents/Info.plist 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/IDLE/IDLE.app/Contents/Info.plist 2023-06-06 22:30:33.000000000 +0000 @@ -37,7 +37,7 @@ CFBundleExecutable IDLE CFBundleGetInfoString - %version%, © 2001-2022 Python Software Foundation + %version%, © 2001-2023 Python Software Foundation CFBundleIconFile IDLE.icns CFBundleIdentifier diff -Nru python3.10-3.10.7/Mac/PythonLauncher/Info.plist.in python3.10-3.10.12/Mac/PythonLauncher/Info.plist.in --- python3.10-3.10.7/Mac/PythonLauncher/Info.plist.in 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/PythonLauncher/Info.plist.in 2023-06-06 22:30:33.000000000 +0000 @@ -40,9 +40,9 @@ CFBundleExecutable Python Launcher NSHumanReadableCopyright - Copyright © 2001-2022 Python Software Foundation + Copyright © 2001-2023 Python Software Foundation CFBundleGetInfoString - %VERSION%, © 2001-2022 Python Software Foundation + %VERSION%, © 2001-2023 Python Software Foundation CFBundleIconFile PythonLauncher.icns CFBundleIdentifier diff -Nru python3.10-3.10.7/Mac/README.rst python3.10-3.10.12/Mac/README.rst --- python3.10-3.10.7/Mac/README.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/README.rst 2023-06-06 22:30:33.000000000 +0000 @@ -10,6 +10,19 @@ This document provides a quick overview of some macOS specific features in the Python distribution. +Compilers for building on macOS +=============================== + +The core developers primarily test builds on macOS with Apple's compiler tools, +either Xcode or the Command Line Tools. For these we only support building with +a compiler that includes an SDK that targets the OS on the build machine, that is +the version of Xcode that shipped with the OS version or one newer. + +For example, for macOS 12 we support Xcode 13 and Xcode 14 (or the corresponding +Command Line Tools). + +Building with other compilers, such as GCC, likely works, but is not actively supported. + macOS specific arguments to configure ===================================== @@ -334,9 +347,9 @@ configure: WARNING: libintl.h: section "Present But Cannot Be Compiled" configure: WARNING: libintl.h: proceeding with the preprocessor's result configure: WARNING: libintl.h: in the future, the compiler will take precedence - configure: WARNING: ## --------------------------------------- ## - configure: WARNING: ## Report this to https://bugs.python.org/ ## - configure: WARNING: ## --------------------------------------- ## + configure: WARNING: ## -------------------------------------------------------- ## + configure: WARNING: ## Report this to https://github.com/python/cpython/issues/ ## + configure: WARNING: ## -------------------------------------------------------- ## This almost always means you are trying to build a universal binary for Python and have libraries in ``/usr/local`` that don't contain the required diff -Nru python3.10-3.10.7/Mac/Resources/app/Info.plist.in python3.10-3.10.12/Mac/Resources/app/Info.plist.in --- python3.10-3.10.7/Mac/Resources/app/Info.plist.in 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/Resources/app/Info.plist.in 2023-06-06 22:30:33.000000000 +0000 @@ -20,7 +20,7 @@ CFBundleExecutable Python CFBundleGetInfoString - %version%, (c) 2001-2020 Python Software Foundation. + %version%, (c) 2001-2023 Python Software Foundation. CFBundleHelpBookFolder Documentation @@ -37,7 +37,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - %version%, (c) 2001-2022 Python Software Foundation. + %version%, (c) 2001-2023 Python Software Foundation. CFBundleName Python CFBundlePackageType @@ -55,7 +55,7 @@ NSAppleScriptEnabled NSHumanReadableCopyright - (c) 2001-2020 Python Software Foundation. + (c) 2001-2023 Python Software Foundation. NSHighResolutionCapable diff -Nru python3.10-3.10.7/Mac/Resources/framework/Info.plist.in python3.10-3.10.12/Mac/Resources/framework/Info.plist.in --- python3.10-3.10.7/Mac/Resources/framework/Info.plist.in 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Mac/Resources/framework/Info.plist.in 2023-06-06 22:30:33.000000000 +0000 @@ -17,9 +17,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - %VERSION%, (c) 2001-2021 Python Software Foundation. + %VERSION%, (c) 2001-2023 Python Software Foundation. CFBundleLongVersionString - %VERSION%, (c) 2001-2021 Python Software Foundation. + %VERSION%, (c) 2001-2023 Python Software Foundation. CFBundleSignature ???? CFBundleVersion diff -Nru python3.10-3.10.7/Makefile.pre.in python3.10-3.10.12/Makefile.pre.in --- python3.10-3.10.7/Makefile.pre.in 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Makefile.pre.in 2023-06-06 22:30:33.000000000 +0000 @@ -1521,6 +1521,7 @@ test/test_warnings test/test_warnings/data \ test/test_zoneinfo test/test_zoneinfo/data \ test/tracedmodules \ + test/typinganndata \ test/xmltestdata test/xmltestdata/c14n-20 \ test/ziptestdata \ tkinter/test tkinter/test/test_tkinter \ @@ -1897,8 +1898,7 @@ -rm -f gb-18030-2000.xml docclean: - -rm -rf Doc/build - -rm -rf Doc/tools/sphinx Doc/tools/pygments Doc/tools/docutils + $(MAKE) -C $(srcdir)/Doc clean # like the 'clean' target but retain the profile guided optimization (PGO) # data. The PGO data is only valid if source code remains unchanged. @@ -1942,7 +1942,7 @@ # Make things extra clean, before making a distribution: # remove all generated files, even Makefile[.pre] # Keep configure and Python-ast.[ch], it's possible they can't be generated -distclean: clobber +distclean: clobber docclean for file in $(srcdir)/Lib/test/data/* ; do \ if test "$$file" != "$(srcdir)/Lib/test/data/README"; then rm "$$file"; fi; \ done diff -Nru python3.10-3.10.7/Misc/ACKS python3.10-3.10.12/Misc/ACKS --- python3.10-3.10.7/Misc/ACKS 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Misc/ACKS 2023-06-06 22:30:33.000000000 +0000 @@ -627,6 +627,7 @@ Yonatan Goldschmidt Mark Gollahon Mikhail Golubev +Marta Gómez Macías Guilherme Gonçalves Tiago Gonçalves Chris Gonnerman @@ -912,6 +913,7 @@ Mads Kiilerich Jason Killen Derek D. Kim +Gihwan Kim Jan Kim Taek Joo Kim Sam Kimbrel @@ -1208,6 +1210,7 @@ Bastien Montagne Skip Montanaro Peter Moody +HyunKyun Moon Alan D. Moore Nicolai Moore Paul Moore @@ -1284,6 +1287,7 @@ Milan Oberkirch Pascal Oberndoerfer Géry Ogam +Seonkyo Ok Jeffrey Ollie Adam Olsen Bryan Olson @@ -1357,6 +1361,7 @@ Mathieu Perreault Mark Perrego Trevor Perrin +Yonatan Perry Gabriel de Perthuis Tim Peters Benjamin Peterson @@ -1428,6 +1433,7 @@ Jeffrey Rackauckas Jérôme Radix Burton Radons +Kirill (python273) R. Abhilash Raj Shorya Raj Dhushyanth Ramasamy @@ -1864,6 +1870,7 @@ Norman Vine Pauli Virtanen Frank Visser +Long Vo Johannes Vogel Michael Vogt Radu Voicilas @@ -1966,6 +1973,7 @@ Darren Worrall Thomas Wouters Daniel Wozniak +Simon Wrede Marcin Niemira Wei Wu Heiko Wundram diff -Nru python3.10-3.10.7/Misc/HISTORY python3.10-3.10.12/Misc/HISTORY --- python3.10-3.10.7/Misc/HISTORY 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Misc/HISTORY 2023-06-06 22:30:33.000000000 +0000 @@ -19610,7 +19610,7 @@ the Open Source Initiative's entry for the Python Software Foundation License:: - http://www.opensource.org/licenses/PythonSoftFoundation.php + https://opensource.org/licenses/PythonSoftFoundation.php says "Python 2.1.1" all over it, wondering whether it applies only to Python 2.1.1. diff -Nru python3.10-3.10.7/Misc/NEWS python3.10-3.10.12/Misc/NEWS --- python3.10-3.10.7/Misc/NEWS 2022-09-05 13:12:31.000000000 +0000 +++ python3.10-3.10.12/Misc/NEWS 2023-06-06 22:43:10.000000000 +0000 @@ -2,6 +2,841 @@ Python News +++++++++++ +What's New in Python 3.10.12 final? +=================================== + +*Release date: 2023-06-06* + +Security +-------- + +- gh-issue-103142: The version of OpenSSL used in our binary builds has been + upgraded to 1.1.1u to address several CVEs. + +- gh-issue-99889: Fixed a security in flaw in :func:`uu.decode` that could + allow for directory traversal based on the input if no ``out_file`` was + specified. + +- gh-issue-104049: Do not expose the local on-disk location in directory + indexes produced by :class:`http.client.SimpleHTTPRequestHandler`. + +- gh-issue-102153: :func:`urllib.parse.urlsplit` now strips leading C0 + control and space characters following the specification for URLs defined + by WHATWG in response to CVE-2023-24329. Patch by Illia Volochii. + +Library +------- + +- gh-issue-103935: Use :func:`io.open_code` for files to be executed instead + of raw :func:`open` + +- gh-issue-102953: The extraction methods in :mod:`tarfile`, and + :func:`shutil.unpack_archive`, have a new a *filter* argument that allows + limiting tar features than may be surprising or dangerous, such as + creating files outside the destination directory. See + :ref:`tarfile-extraction-filter` for details. + +Documentation +------------- + +- gh-issue-89412: Add missing documentation for the ``end_lineno`` and + ``end_offset`` attributes of the :class:`traceback.TracebackException` + class. + +Build +----- + +- gh-issue-103262: Fixes Windows installer build to work with latest + compilers. + + +What's New in Python 3.10.11 final? +=================================== + +*Release date: 2023-04-04* + +Security +-------- + +- gh-issue-101727: Updated the OpenSSL version used in Windows and macOS + binary release builds to 1.1.1t to address CVE-2023-0286, CVE-2022-4303, + and CVE-2022-4303 per `the OpenSSL 2023-02-07 security advisory + `_. + +- gh-issue-101283: :class:`subprocess.Popen` now uses a safer approach to + find ``cmd.exe`` when launching with ``shell=True``. Patch by Eryk Sun, + based on a patch by Oleg Iarygin. + +Core and Builtins +----------------- + +- gh-issue-102416: Do not memoize incorrectly automatically generated loop + rules in the parser. Patch by Pablo Galindo. + +- gh-issue-102356: Fix a bug that caused a crash when deallocating deeply + nested filter objects. Patch by Marta Gómez Macías. + +- gh-issue-102397: Fix segfault from race condition in signal handling + during garbage collection. Patch by Kumar Aditya. + +- gh-issue-102126: Fix deadlock at shutdown when clearing thread states if + any finalizer tries to acquire the runtime head lock. Patch by Kumar + Aditya. + +- gh-issue-102027: Fix SSE2 and SSE3 detection in ``_blake2`` internal + module. Patch by Max Bachmann. + +- gh-issue-101967: Fix possible segfault in + ``positional_only_passed_as_keyword`` function, when new list created. + +- gh-issue-101765: Fix SystemError / segmentation fault in iter + ``__reduce__`` when internal access of ``builtins.__dict__`` keys mutates + the iter object. + +Library +------- + +- gh-issue-102947: Improve traceback when :func:`dataclasses.fields` is + called on a non-dataclass. Patch by Alex Waygood + +- gh-issue-101979: Fix a bug where parentheses in the ``metavar`` argument + to :meth:`argparse.ArgumentParser.add_argument` were dropped. Patch by + Yeojin Kim. + +- gh-issue-102179: Fix :func:`os.dup2` error message for negative fds. + +- gh-issue-101961: For the binary mode, :func:`fileinput.hookcompressed` + doesn't set the ``encoding`` value even if the value is ``None``. Patch by + Gihwan Kim. + +- gh-issue-101936: The default value of ``fp`` becomes :class:`io.BytesIO` + if :exc:`~urllib.error.HTTPError` is initialized without a designated + ``fp`` parameter. Patch by Long Vo. + +- gh-issue-101566: In zipfile, apply fix for extractall on the underlying + zipfile after being wrapped in ``Path``. + +- gh-issue-101997: Upgrade pip wheel bundled with ensurepip (pip 23.0.1) + +- gh-issue-101892: Callable iterators no longer raise :class:`SystemError` + when the callable object exhausts the iterator but forgets to either + return a sentinel value or raise :class:`StopIteration`. + +- gh-issue-97786: Fix potential undefined behaviour in corner cases of + floating-point-to-time conversions. + +- gh-issue-101517: Fixed bug where :mod:`bdb` looks up the source line with + :mod:`linecache` with a ``lineno=None``, which causes it to fail with an + unhandled exception. + +- gh-issue-101673: Fix a :mod:`pdb` bug where ``ll`` clears the changes to + local variables. + +- gh-issue-96931: Fix incorrect results from + :meth:`ssl.SSLSocket.shared_ciphers` + +- gh-issue-88233: Correctly preserve "extra" fields in ``zipfile`` + regardless of their ordering relative to a zip64 "extra." + +- gh-issue-95495: When built against OpenSSL 3.0, the :mod:`ssl` module had + a bug where it reported unauthenticated EOFs (i.e. without close_notify) + as a clean TLS-level EOF. It now raises :exc:`~ssl.SSLEOFError`, matching + the behavior in previous versions of OpenSSL. The + :attr:`~ssl.SSLContext.options` attribute on :class:`~ssl.SSLContext` also + no longer includes :data:`~ssl.OP_IGNORE_UNEXPECTED_EOF` by default. This + option may be set to specify the previous OpenSSL 3.0 behavior. + +- gh-issue-94440: Fix a :mod:`concurrent.futures.process` bug where + ``ProcessPoolExecutor`` shutdown could hang after a future has been + quickly submitted and canceled. + +Documentation +------------- + +- gh-issue-103112: Add docstring to :meth:`http.client.HTTPResponse.read` to + fix ``pydoc`` output. + +- gh-issue-85417: Update :mod:`cmath` documentation to clarify behaviour on + branch cuts. + +- gh-issue-97725: Fix :meth:`asyncio.Task.print_stack` description for + ``file=None``. Patch by Oleg Iarygin. + +Tests +----- + +- gh-issue-102980: Improve test coverage on :mod:`pdb`. + +- gh-issue-102537: Adjust the error handling strategy in + ``test_zoneinfo.TzPathTest.python_tzpath_context``. Patch by Paul Ganssle. + +- gh-issue-101377: Improved test_locale_calendar_formatweekday of calendar. + +Build +----- + +- gh-issue-102711: Fix ``-Wstrict-prototypes`` compiler warnings. + +Windows +------- + +- gh-issue-101759: Update Windows installer to SQLite 3.40.1. + +- gh-issue-101614: Correctly handle extensions built against debug binaries + that reference ``python3_d.dll``. + +macOS +----- + +- gh-issue-103207: Add instructions to the macOS installer welcome display + on how to workaround the macOS 13 Ventura “The installer encountered an + error” failure. + +- gh-issue-101759: Update macOS installer to SQLite 3.40.1. + +- gh-issue-87235: On macOS ``python3 /dev/fd/9 9` in :func:`os.ismount()`. + +- bpo-44817: Ignore WinError 53 (ERROR_BAD_NETPATH), 65 + (ERROR_NETWORK_ACCESS_DENIED) and 161 (ERROR_BAD_PATHNAME) when using + ntpath.realpath(). + +- bpo-40447: Accept :class:`os.PathLike` (such as :class:`pathlib.Path`) in + the ``stripdir`` arguments of :meth:`compileall.compile_file` and + :meth:`compileall.compile_dir`. + +- bpo-36880: Fix a reference counting issue when a :mod:`ctypes` callback + with return type :class:`~ctypes.py_object` returns ``None``, which could + cause crashes. + +Documentation +------------- + +- gh-issue-100616: Document existing ``attr`` parameter to + :func:`curses.window.vline` function in :mod:`curses`. + +- gh-issue-100472: Remove claim in documentation that the ``stripdir``, + ``prependdir`` and ``limit_sl_dest`` parameters of + :func:`compileall.compile_dir` and :func:`compileall.compile_file` could + be :class:`bytes`. + +Tests +----- + +- gh-issue-101334: ``test_tarfile`` has been updated to pass when run as a + high UID. + +- gh-issue-96002: Add functional test for Argument Clinic. + +Build +----- + +- gh-issue-101522: Allow overriding Windows dependencies versions and paths + using MSBuild properties. + +Windows +------- + +- gh-issue-82052: Fixed an issue where writing more than 32K of Unicode + output to the console screen in one go can result in mojibake. + +- gh-issue-100180: Update Windows installer to OpenSSL 1.1.1s + +- bpo-43984: :meth:`winreg.SetValueEx` now leaves the target value untouched + in the case of conversion errors. Previously, ``-1`` would be written in + case of such errors. + +macOS +----- + +- gh-issue-100180: Update macOS installer to OpenSSL 1.1.1s + +C API +----- + +- gh-issue-99240: In argument parsing, after deallocating newly allocated + memory, reset its pointer to NULL. + + +What's New in Python 3.10.9 final? +================================== + +*Release date: 2022-12-06* + +Security +-------- + +- gh-issue-100001: ``python -m http.server`` no longer allows terminal + control characters sent within a garbage request to be printed to the + stderr server log. + + This is done by changing the :mod:`http.server` + :class:`BaseHTTPRequestHandler` ``.log_message`` method to replace control + characters with a ``\xHH`` hex escape before printing. + +- gh-issue-87604: Avoid publishing list of active per-interpreter audit + hooks via the :mod:`gc` module + +- gh-issue-98433: The IDNA codec decoder used on DNS hostnames by + :mod:`socket` or :mod:`asyncio` related name resolution functions no + longer involves a quadratic algorithm. This prevents a potential CPU + denial of service if an out-of-spec excessive length hostname involving + bidirectional characters were decoded. Some protocols such as + :mod:`urllib` http ``3xx`` redirects potentially allow for an attacker to + supply such a name. + +- gh-issue-98739: Update bundled libexpat to 2.5.0 + +- gh-issue-98517: Port XKCP's fix for the buffer overflows in SHA-3 + (CVE-2022-37454). + +- gh-issue-97514: On Linux the :mod:`multiprocessing` module returns to + using filesystem backed unix domain sockets for communication with the + *forkserver* process instead of the Linux abstract socket namespace. Only + code that chooses to use the :ref:`"forkserver" start method + ` is affected. + + Abstract sockets have no permissions and could allow any user on the + system in the same `network namespace + `_ (often + the whole system) to inject code into the multiprocessing *forkserver* + process. This was a potential privilege escalation. Filesystem based + socket permissions restrict this to the *forkserver* process user as was + the default in Python 3.8 and earlier. + + This prevents Linux `CVE-2022-42919 + `_. + +Core and Builtins +----------------- + +- gh-issue-99578: Fix a reference bug in :func:`_imp.create_builtin()` after + the creation of the first sub-interpreter for modules ``builtins`` and + ``sys``. Patch by Victor Stinner. + +- gh-issue-99581: Fixed a bug that was causing a buffer overflow if the + tokenizer copies a line missing the newline caracter from a file that is + as long as the available tokenizer buffer. Patch by Pablo galindo + +- gh-issue-96055: Update :mod:`faulthandler` to emit an error message with + the proper unexpected signal number. Patch by Dong-hee Na. + +- gh-issue-98852: Fix subscription of :class:`types.GenericAlias` instances + containing bare generic types: for example ``tuple[A, T][int]``, where + ``A`` is a generic type, and ``T`` is a type variable. + +- gh-issue-98415: Fix detection of MAC addresses for :mod:`uuid` on certain + OSs. Patch by Chaim Sanders + +- gh-issue-92119: Print exception class name instead of its string + representation when raising errors from :mod:`ctypes` calls. + +- gh-issue-93696: Allow :mod:`pdb` to locate source for frozen modules in + the standard library. + +- bpo-31718: Raise :exc:`ValueError` instead of :exc:`SystemError` when + methods of uninitialized :class:`io.IncrementalNewlineDecoder` objects are + called. Patch by Oren Milman. + +- bpo-38031: Fix a possible assertion failure in :class:`io.FileIO` when the + opener returns an invalid file descriptor. + +Library +------- + +- gh-issue-100001: Also \ escape \s in the http.server + BaseHTTPRequestHandler.log_message so that it is technically possible to + parse the line and reconstruct what the original data was. Without this a + \xHH is ambiguious as to if it is a hex replacement we put in or the + characters r"\x" came through in the original request line. + +- gh-issue-93453: :func:`asyncio.get_event_loop` now only emits a + deprecation warning when a new event loop was created implicitly. It no + longer emits a deprecation warning if the current event loop was set. + +- gh-issue-51524: Fix bug when calling trace.CoverageResults with valid + infile. + +- gh-issue-99645: Fix a bug in handling class cleanups in + :class:`unittest.TestCase`. Now ``addClassCleanup()`` uses separate lists + for different ``TestCase`` subclasses, and ``doClassCleanups()`` only + cleans up the particular class. + +- gh-issue-97001: Release the GIL when calling termios APIs to avoid + blocking threads. + +- gh-issue-99341: Fix :func:`ast.increment_lineno` to also cover + :class:`ast.TypeIgnore` when changing line numbers. + +- gh-issue-74044: Fixed bug where :func:`inspect.signature` reported + incorrect arguments for decorated methods. + +- gh-issue-99275: Fix ``SystemError`` in :mod:`ctypes` when exception was + not set during ``__initsubclass__``. + +- gh-issue-99155: Fix :class:`statistics.NormalDist` pickle with ``0`` and + ``1`` protocols. + +- gh-issue-99134: Update the bundled copy of pip to version 22.3.1. + +- gh-issue-99130: Apply bugfixes from `importlib_metadata 4.11.4 + `_, + namely: In ``PathDistribution._name_from_stem``, avoid including parts of + the extension in the result. In ``PathDistribution._normalized_name``, + ensure names loaded from the stem of the filename are also normalized, + ensuring duplicate entry points by packages varying only by non-normalized + name are hidden. + +- gh-issue-83004: Clean up refleak on failed module initialisation in + :mod:`_zoneinfo` + +- gh-issue-83004: Clean up refleaks on failed module initialisation in in + :mod:`_pickle` + +- gh-issue-83004: Clean up refleak on failed module initialisation in + :mod:`_io`. + +- gh-issue-98897: Fix memory leak in :func:`math.dist` when both points + don't have the same dimension. Patch by Kumar Aditya. + +- gh-issue-98793: Fix argument typechecks in :func:`!_overlapped.WSAConnect` + and :func:`!_overlapped.Overlapped.WSASendTo` functions. + +- gh-issue-98740: Fix internal error in the :mod:`re` module which in very + rare circumstances prevented compilation of a regular expression + containing a :ref:`conditional expression ` + without the "else" branch. + +- gh-issue-98703: Fix :meth:`asyncio.StreamWriter.drain` to call + ``protocol.connection_lost`` callback only once on Windows. + +- gh-issue-98624: Add a mutex to unittest.mock.NonCallableMock to protect + concurrent access to mock attributes. + +- gh-issue-89237: Fix hang on Windows in ``subprocess.wait_closed()`` in + :mod:`asyncio` with :class:`~asyncio.ProactorEventLoop`. Patch by Kumar + Aditya. + +- gh-issue-98458: Fix infinite loop in unittest when a self-referencing + chained exception is raised + +- gh-issue-97928: :meth:`tkinter.Text.count` raises now an exception for + options starting with "-" instead of silently ignoring them. + +- gh-issue-97966: On ``uname_result``, restored expectation that ``_fields`` + and ``_asdict`` would include all six properties including ``processor``. + +- gh-issue-98331: Update the bundled copies of pip and setuptools to + versions 22.3 and 65.5.0 respectively. + +- gh-issue-96035: Fix bug in :func:`urllib.parse.urlparse` that causes + certain port numbers containing whitespace, underscores, plus and minus + signs, or non-ASCII digits to be incorrectly accepted. + +- gh-issue-98251: Allow :mod:`venv` to pass along :envvar:`PYTHON*` + variables to ``ensurepip`` and ``pip`` when they do not impact path + resolution + +- gh-issue-98178: On macOS, fix a crash in :func:`syslog.syslog` in + multi-threaded applications. On macOS, the libc ``syslog()`` function is + not thread-safe, so :func:`syslog.syslog` no longer releases the GIL to + call it. Patch by Victor Stinner. + +- gh-issue-96151: Allow ``BUILTINS`` to be a valid field name for frozen + dataclasses. + +- gh-issue-98086: Make sure ``patch.dict()`` can be applied on async + functions. + +- gh-issue-88863: To avoid apparent memory leaks when + :func:`asyncio.open_connection` raises, break reference cycles generated + by local exception and future instances (which has exception instance as + its member var). Patch by Dong Uk, Kang. + +- gh-issue-93858: Prevent error when activating venv in nested fish + instances. + +- bpo-46364: Restrict use of sockets instead of pipes for stdin of + subprocesses created by :mod:`asyncio` to AIX platform only. + +- bpo-38523: :func:`shutil.copytree` now applies the + *ignore_dangling_symlinks* argument recursively. + +- bpo-36267: Fix IndexError in :class:`argparse.ArgumentParser` when a + ``store_true`` action is given an explicit argument. + +Documentation +------------- + +- gh-issue-92892: Document that calling variadic functions with ctypes + requires special care on macOS/arm64 (and possibly other platforms). + +Tests +----- + +- gh-issue-99892: Skip test_normalization() of test_unicodedata if it fails + to download NormalizationTest.txt file from pythontest.net. Patch by + Victor Stinner. + +- bpo-34272: Some C API tests were moved into the new Lib/test/test_capi/ + directory. + +Build +----- + +- gh-issue-99086: Fix ``-Wimplicit-int``, ``-Wstrict-prototypes``, and + ``-Wimplicit-function-declaration`` compiler warnings in + :program:`configure` checks. + +- gh-issue-99086: Fix ``-Wimplicit-int`` compiler warning in + :program:`configure` check for ``PTHREAD_SCOPE_SYSTEM``. + +- gh-issue-97731: Specify the full path to the source location for ``make + docclean`` (needed for cross-builds). + +- gh-issue-98671: Fix ``NO_MISALIGNED_ACCESSES`` being not defined for the + SHA3 extension when ``HAVE_ALIGNED_REQUIRED`` is set. Allowing builds on + hardware that unaligned memory accesses are not allowed. + +Windows +------- + +- gh-issue-99345: Use faster initialization functions to detect install + location for Windows Store package + +- gh-issue-98689: Update Windows builds to zlib v1.2.13. v1.2.12 has + CVE-2022-37434, but the vulnerable ``inflateGetHeader`` API is not used by + Python. + +- gh-issue-94328: Update Windows installer to use SQLite 3.39.4. + +- bpo-40882: Fix a memory leak in + :class:`multiprocessing.shared_memory.SharedMemory` on Windows. + +macOS +----- + +- gh-issue-94328: Update macOS installer to SQLite 3.39.4. + +IDLE +---- + +- gh-issue-97527: Fix a bug in the previous bugfix that caused IDLE to not + start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python + 3.10.2288.0 installed without the Lib/test package. 3.11.0 was never + affected. + +Tools/Demos +----------- + +- gh-issue-95731: Fix handling of module docstrings in + :file:`Tools/i18n/pygettext.py`. + + +What's New in Python 3.10.8 final? +================================== + +*Release date: 2022-10-11* + +Security +-------- + +- gh-issue-97616: Fix multiplying a list by an integer (``list *= int``): + detect the integer overflow when the new allocated length is close to the + maximum size. Issue reported by Jordan Limor. Patch by Victor Stinner. + +- gh-issue-97612: Fix a shell code injection vulnerability in the + ``get-remote-certificate.py`` example script. The script no longer uses a + shell to run ``openssl`` commands. Issue reported and initial fix by Caleb + Shortt. Patch by Victor Stinner. + +- gh-issue-68966: The deprecated mailcap module now refuses to inject unsafe + text (filenames, MIME types, parameters) into shell commands. Instead of + using such text, it will warn and act as if a match was not found (or for + test commands, as if the test failed). + +Core and Builtins +----------------- + +- gh-issue-96078: :func:`os.sched_yield` now release the GIL while calling + sched_yield(2). Patch by Dong-hee Na. + +- gh-issue-97943: Bugfix: :func:`PyFunction_GetAnnotations` should return a + borrowed reference. It was returning a new reference. + +- gh-issue-97591: Fixed a missing incref/decref pair in + `Exception.__setstate__()`. Patch by Ofey Chan. + +- gh-issue-96848: Fix command line parsing: reject :option:`-X + int_max_str_digits <-X>` option with no value (invalid) when the + :envvar:`PYTHONINTMAXSTRDIGITS` environment variable is set to a valid + limit. Patch by Victor Stinner. + +- gh-issue-95921: Fix overly-broad source position information for chained + comparisons used as branching conditions. + +- gh-issue-96821: Fix undefined behaviour in ``_testcapimodule.c``. + +- gh-issue-95778: When :exc:`ValueError` is raised if an integer is larger + than the limit, mention the :func:`sys.set_int_max_str_digits` function in + the error message. Patch by Victor Stinner. + +- gh-issue-96387: At Python exit, sometimes a thread holding the GIL can + wait forever for a thread (usually a daemon thread) which requested to + drop the GIL, whereas the thread already exited. To fix the race + condition, the thread which requested the GIL drop now resets its request + before exiting. Issue discovered and analyzed by Mingliang ZHAO. Patch by + Victor Stinner. + +- gh-issue-96864: Fix a possible assertion failure, fatal error, or + :exc:`SystemError` if a line tracing event raises an exception while + opcode tracing is enabled. + +- gh-issue-96678: Fix undefined behaviour in C code of null pointer + arithmetic. + +- gh-issue-96641: Do not expose ``KeyWrapper`` in :mod:`_functools`. + +- gh-issue-96611: When loading a file with invalid UTF-8 inside a multi-line + string, a correct SyntaxError is emitted. + +- gh-issue-95196: Disable incorrect pickling of the C implemented + classmethod descriptors. + +- gh-issue-96352: Fix :exc:`AttributeError` missing ``name`` and ``obj`` + attributes in :meth:`object.__getattribute__`. Patch by Philip Georgi. + +- bpo-42316: Document some places where an assignment expression needs + parentheses. + +Library +------- + +- gh-issue-87730: Wrap network errors consistently in urllib FTP support, so + the test suite doesn't fail when a network is available but the public + internet is not reachable. + +- gh-issue-97825: Fixes :exc:`AttributeError` when + :meth:`subprocess.check_output` is used with argument ``input=None`` and + either of the arguments *encoding* or *errors* are used. + +- gh-issue-96827: Avoid spurious tracebacks from :mod:`asyncio` when default + executor cleanup is delayed until after the event loop is closed (e.g. as + the result of a keyboard interrupt). + +- gh-issue-97592: Avoid a crash in the C version of + :meth:`asyncio.Future.remove_done_callback` when an evil argument is + passed. + +- gh-issue-97639: Remove ``tokenize.NL`` check from :mod:`tabnanny`. + +- gh-issue-97545: Make Semaphore run faster. + +- gh-issue-73588: Fix generation of the default name of + :class:`tkinter.Checkbutton`. Previously, checkbuttons in different parent + widgets could have the same short name and share the same state if + arguments "name" and "variable" are not specified. Now they are globally + unique. + +- gh-issue-97005: Update bundled libexpat to 2.4.9 + +- gh-issue-85760: Fix race condition in :mod:`asyncio` where + :meth:`~asyncio.SubprocessProtocol.process_exited` called before the + :meth:`~asyncio.SubprocessProtocol.pipe_data_received` leading to + inconsistent output. Patch by Kumar Aditya. + +- gh-issue-96819: Fixed check in :mod:`multiprocessing.resource_tracker` + that guarantees that the length of a write to a pipe is not greater than + ``PIPE_BUF``. + +- gh-issue-96741: Corrected type annotation for dataclass attribute + ``pstats.FunctionProfile.ncalls`` to be ``str``. + +- gh-issue-96652: Fix the faulthandler implementation of + ``faulthandler.register(signal, chain=True)`` if the ``sigaction()`` + function is not available: don't call the previous signal handler if it's + NULL. Patch by Victor Stinner. + +- gh-issue-96073: In :mod:`inspect`, fix overeager replacement of + "``typing.``" in formatting annotations. + +- gh-issue-90467: Fix :class:`asyncio.streams.StreamReaderProtocol` to keep + a strong reference to the created task, so that it's not garbage collected + +- gh-issue-96052: Fix handling compiler warnings (SyntaxWarning and + DeprecationWarning) in :func:`codeop.compile_command` when checking for + incomplete input. Previously it emitted warnings and raised a SyntaxError. + Now it always returns ``None`` for incomplete input without emitting any + warnings. + +- gh-issue-91212: Fixed flickering of the turtle window when the tracer is + turned off. Patch by Shin-myoung-serp. + +- gh-issue-74116: Allow :meth:`asyncio.StreamWriter.drain` to be awaited + concurrently by multiple tasks. Patch by Kumar Aditya. + +- gh-issue-90155: Fix broken :class:`asyncio.Semaphore` when acquire is + cancelled. + +- gh-issue-92986: Fix :func:`ast.unparse` when ``ImportFrom.level`` is None + +- gh-issue-91539: Improve performance of + ``urllib.request.getproxies_environment`` when there are many environment + variables + +Documentation +------------- + +- gh-issue-97741: Fix ``!`` in c domain ref target syntax via a ``conf.py`` + patch, so it works as intended to disable ref target resolution. + +- gh-issue-95588: Clarified the conflicting advice given in the :mod:`ast` + documentation about :func:`ast.literal_eval` being "safe" for use on + untrusted input while at the same time warning that it can crash the + process. The latter statement is true and is deemed unfixable without a + large amount of work unsuitable for a bugfix. So we keep the warning and + no longer claim that ``literal_eval`` is safe. + +- gh-issue-93031: Update tutorial introduction output to use 3.10+ + SyntaxError invalid range. + +Build +----- + +- gh-issue-96729: Ensure that Windows releases built with + ``Tools\msi\buildrelease.bat`` are upgradable to and from official Python + releases. + +Windows +------- + +- gh-issue-97728: Fix possible crashes caused by the use of uninitialized + variables when pass invalid arguments in :func:`os.system` on Windows and + in Windows-specific modules (like ``winreg``). + +- gh-issue-90989: Clarify some text in the Windows installer. + +- gh-issue-96577: Fixes a potential buffer overrun in :mod:`msilib`. + +macOS +----- + +- gh-issue-97897: The macOS 13 SDK includes support for the ``mkfifoat`` and + ``mknodat`` system calls. Using the ``dir_fd`` option with either + :func:`os.mkfifo` or :func:`os.mknod` could result in a segfault if + cpython is built with the macOS 13 SDK but run on an earlier version of + macOS. Prevent this by adding runtime support for detection of these + system calls ("weaklinking") as is done for other newer syscalls on macOS. + + What's New in Python 3.10.7 final? ================================== @@ -7148,7 +7983,7 @@ ends in the internal subinterpreters module. - bpo-37986: Improve performance of :c:func:`PyLong_FromDouble` for values - that fit into :c:type:`long`. + that fit into :c:expr:`long`. Library ------- @@ -9048,8 +9883,7 @@ creates new event loop only if called from the main thread. - bpo-38918: Add an entry for ``__module__`` in the "function" & "method" - sections of the `inspect docs types and members table - `_ + sections of the :mod:`inspect` docs' :ref:`inspect-types` table. - bpo-3530: In the :mod:`ast` module documentation, fix a misleading ``NodeTransformer`` example and add advice on when to use the @@ -9997,7 +10831,7 @@ AsyncMock. - bpo-38265: Update the *length* parameter of :func:`os.pread` to accept - :c:type:`Py_ssize_t` instead of :c:type:`int`. + :c:type:`Py_ssize_t` instead of :c:expr:`int`. - bpo-38112: :mod:`compileall` has a higher default recursion limit and new command-line arguments for path manipulation, symlinks handling, and @@ -12700,9 +13534,9 @@ - bpo-36763: Fix memory leak in :c:func:`Py_SetStandardStreamEncoding`: release memory if the function is called twice. -- bpo-36641: :c:macro:`PyDoc_VAR(name)` and - :c:macro:`PyDoc_STRVAR(name,str)` now create ``static const char name[]`` - instead of ``static char name[]``. Patch by Inada Naoki. +- bpo-36641: :c:expr:`PyDoc_VAR(name)` and :c:expr:`PyDoc_STRVAR(name,str)` + now create ``static const char name[]`` instead of ``static char name[]``. + Patch by Inada Naoki. - bpo-36389: Change the value of ``CLEANBYTE``, ``DEADDYTE`` and ``FORBIDDENBYTE`` internal constants used by debug hooks on Python memory @@ -30903,7 +31737,7 @@ Initial patch by Phil Elson. - bpo-21932: os.read() now uses a :c:func:`Py_ssize_t` type instead of - :c:type:`int` for the size to support reading more than 2 GB at once. On + :c:expr:`int` for the size to support reading more than 2 GB at once. On Windows, the size is truncated to INT_MAX. As any call to os.read(), the OS may read less bytes than the number of requested bytes. diff -Nru python3.10-3.10.7/Misc/python.man python3.10-3.10.12/Misc/python.man --- python3.10-3.10.7/Misc/python.man 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Misc/python.man 2023-06-06 22:30:33.000000000 +0000 @@ -318,6 +318,10 @@ -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None' + -X int_max_str_digits=number: limit the size of int<->str conversions. + This helps avoid denial of service attacks when parsing untrusted data. + The default is sys.int_info.default_max_str_digits. 0 disables. + .TP .B \-x Skip the first line of the source. This is intended for a DOS @@ -487,6 +491,11 @@ The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. +.IP PYTHONINTMAXSTRDIGITS +Limit the maximum digit characters in an int value +when converting from a string and when converting an int back to a str. +A value of 0 disables the limit. Conversions to or from bases 2, 4, 8, +16, and 32 are never limited. .IP PYTHONMALLOC Set the Python memory allocators and/or install debug hooks. The available memory allocators are diff -Nru python3.10-3.10.7/Modules/_asynciomodule.c python3.10-3.10.12/Modules/_asynciomodule.c --- python3.10-3.10.7/Modules/_asynciomodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_asynciomodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -332,13 +332,6 @@ return loop; } - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "There is no current event loop", - stacklevel)) - { - return NULL; - } - policy = PyObject_CallNoArgs(asyncio_get_event_loop_policy); if (policy == NULL) { return NULL; @@ -1042,7 +1035,11 @@ return NULL; } - for (i = 0; i < PyList_GET_SIZE(self->fut_callbacks); i++) { + // Beware: PyObject_RichCompareBool below may change fut_callbacks. + // See GH-97592. + for (i = 0; + self->fut_callbacks != NULL && i < PyList_GET_SIZE(self->fut_callbacks); + i++) { int ret; PyObject *item = PyList_GET_ITEM(self->fut_callbacks, i); Py_INCREF(item); @@ -1061,7 +1058,8 @@ } } - if (j == 0) { + // Note: fut_callbacks may have been cleared. + if (j == 0 || self->fut_callbacks == NULL) { Py_CLEAR(self->fut_callbacks); Py_DECREF(newlist); return PyLong_FromSsize_t(len + cleared_callback0); @@ -3087,6 +3085,11 @@ return get_event_loop(1); } +// This internal method is going away in Python 3.12, left here only for +// backwards compatibility with 3.10.0 - 3.10.8 and 3.11.0. +// Similarly, this method's Python equivalent in asyncio.events is going +// away as well. +// See GH-99949 for more details. /*[clinic input] _asyncio._get_event_loop stacklevel: int = 3 diff -Nru python3.10-3.10.7/Modules/audioop.c python3.10-3.10.12/Modules/audioop.c --- python3.10-3.10.7/Modules/audioop.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/audioop.c 2023-06-06 22:30:33.000000000 +0000 @@ -1,3 +1,33 @@ +/* The audioop module uses the code base in g777.c file of the Sox project. + * Source: https://web.archive.org/web/19970716121258/http://www.spies.com/Sox/Archive/soxgamma.tar.gz + * Programming the AdLib/Sound Blaster + * FM Music Chips + * Version 2.0 (24 Feb 1992) + * + * Copyright (c) 1991, 1992 by Jeffrey S. Lee + * + * jlee@smylex.uucp + * + * + * + * Warranty and Copyright Policy + * + * This document is provided on an "as-is" basis, and its author makes + * no warranty or representation, express or implied, with respect to + * its quality performance or fitness for a particular purpose. In no + * event will the author of this document be liable for direct, indirect, + * special, incidental, or consequential damages arising out of the use + * or inability to use the information contained within. Use of this + * document is at your own risk. + * + * This file may be used and copied freely so long as the applicable + * copyright notices are retained, and no modifications are made to the + * text of the document. No money shall be charged for its distribution + * beyond reasonable shipping, handling and duplication costs, nor shall + * proprietary changes be made to this document so that it cannot be + * distributed freely. This document may not be included in published + * material or commercial packages without the written consent of its + * author. */ /* audioopmodule - Module to detect peak values in arrays */ @@ -28,20 +58,6 @@ } -/* Code shamelessly stolen from sox, 12.17.7, g711.c -** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */ - -/* From g711.c: - * - * December 30, 1994: - * Functions linear2alaw, linear2ulaw have been updated to correctly - * convert unquantized 16 bit values. - * Tables for direct u- to A-law and A- to u-law conversions have been - * corrected. - * Borge Lindberg, Center for PersonKommunikation, Aalborg University. - * bli@cpk.auc.dk - * - */ #define BIAS 0x84 /* define the add-in bias for 16 bit samples */ #define CLIP 32635 #define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */ diff -Nru python3.10-3.10.7/Modules/_blake2/impl/blake2-config.h python3.10-3.10.12/Modules/_blake2/impl/blake2-config.h --- python3.10-3.10.7/Modules/_blake2/impl/blake2-config.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_blake2/impl/blake2-config.h 2023-06-06 22:30:33.000000000 +0000 @@ -53,7 +53,7 @@ #endif #endif -#ifdef HAVE_SSE41 +#ifdef HAVE_SSE4_1 #ifndef HAVE_SSSE3 #define HAVE_SSSE3 #endif diff -Nru python3.10-3.10.7/Modules/clinic/cmathmodule.c.h python3.10-3.10.12/Modules/clinic/cmathmodule.c.h --- python3.10-3.10.7/Modules/clinic/cmathmodule.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/clinic/cmathmodule.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -638,7 +638,7 @@ "\n" "log(z[, base]) -> the logarithm of z to the given base.\n" "\n" -"If the base not specified, returns the natural logarithm (base e) of z."); +"If the base is not specified, returns the natural logarithm (base e) of z."); #define CMATH_LOG_METHODDEF \ {"log", (PyCFunction)(void(*)(void))cmath_log, METH_FASTCALL, cmath_log__doc__}, @@ -953,4 +953,4 @@ exit: return return_value; } -/*[clinic end generated code: output=353347db2e808e0d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=717d3d9f0640e893 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Modules/clinic/overlapped.c.h python3.10-3.10.12/Modules/clinic/overlapped.c.h --- python3.10-3.10.7/Modules/clinic/overlapped.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/clinic/overlapped.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -220,7 +220,7 @@ PyObject *EventAttributes; BOOL ManualReset; BOOL InitialState; - const Py_UNICODE *Name; + const Py_UNICODE *Name = NULL; if (!_PyArg_ParseStack(args, nargs, "OiiO&:CreateEvent", &EventAttributes, &ManualReset, &InitialState, _PyUnicode_WideCharString_Opt_Converter, &Name)) { @@ -786,7 +786,7 @@ _overlapped_Overlapped_ConnectPipe(OverlappedObject *self, PyObject *arg) { PyObject *return_value = NULL; - const Py_UNICODE *Address; + const Py_UNICODE *Address = NULL; if (!PyUnicode_Check(arg)) { _PyArg_BadArgument("ConnectPipe", "argument", "str", arg); @@ -831,8 +831,8 @@ HANDLE ConnectSocket; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O:WSAConnect", - &ConnectSocket, &AddressObj)) { + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"O!:WSAConnect", + &ConnectSocket, &PyTuple_Type, &AddressObj)) { goto exit; } return_value = _overlapped_WSAConnect_impl(module, ConnectSocket, AddressObj); @@ -864,8 +864,8 @@ DWORD flags; PyObject *AddressObj; - if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"OkO:WSASendTo", - &handle, &bufobj, &flags, &AddressObj)) { + if (!_PyArg_ParseStack(args, nargs, ""F_HANDLE"OkO!:WSASendTo", + &handle, &bufobj, &flags, &PyTuple_Type, &AddressObj)) { goto exit; } return_value = _overlapped_Overlapped_WSASendTo_impl(self, handle, bufobj, flags, AddressObj); @@ -905,4 +905,4 @@ exit: return return_value; } -/*[clinic end generated code: output=ee2ec2f93c8d334b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e685b61b3da0524d input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Modules/clinic/posixmodule.c.h python3.10-3.10.12/Modules/clinic/posixmodule.c.h --- python3.10-3.10.7/Modules/clinic/posixmodule.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/clinic/posixmodule.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -1328,7 +1328,8 @@ "dir_fd may not be implemented on your platform.\n" " If it is unavailable, using it will raise a NotImplementedError.\n" "\n" -"The mode argument is ignored on Windows."); +"The mode argument is ignored on Windows. Where it is used, the current umask\n" +"value is first masked out."); #define OS_MKDIR_METHODDEF \ {"mkdir", (PyCFunction)(void(*)(void))os_mkdir, METH_FASTCALL|METH_KEYWORDS, os_mkdir__doc__}, @@ -1717,7 +1718,7 @@ static const char * const _keywords[] = {"command", NULL}; static _PyArg_Parser _parser = {NULL, _keywords, "system", 0}; PyObject *argsbuf[1]; - const Py_UNICODE *command; + const Py_UNICODE *command = NULL; long _return_value; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); @@ -9291,4 +9292,4 @@ #ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF #define OS_WAITSTATUS_TO_EXITCODE_METHODDEF #endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */ -/*[clinic end generated code: output=73be33fa0000a6d1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f8cdbd04ea0e3502 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Modules/clinic/_testclinic.c.h python3.10-3.10.12/Modules/clinic/_testclinic.c.h --- python3.10-3.10.7/Modules/clinic/_testclinic.c.h 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Modules/clinic/_testclinic.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,1987 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(test_empty_function__doc__, +"test_empty_function($module, /)\n" +"--\n" +"\n"); + +#define TEST_EMPTY_FUNCTION_METHODDEF \ + {"test_empty_function", (PyCFunction)test_empty_function, METH_NOARGS, test_empty_function__doc__}, + +static PyObject * +test_empty_function_impl(PyObject *module); + +static PyObject * +test_empty_function(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return test_empty_function_impl(module); +} + +PyDoc_STRVAR(objects_converter__doc__, +"objects_converter($module, a, b=, /)\n" +"--\n" +"\n"); + +#define OBJECTS_CONVERTER_METHODDEF \ + {"objects_converter", (PyCFunction)(void(*)(void))objects_converter, METH_FASTCALL, objects_converter__doc__}, + +static PyObject * +objects_converter_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +objects_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *a; + PyObject *b = NULL; + + if (!_PyArg_CheckPositional("objects_converter", nargs, 1, 2)) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional; + } + b = args[1]; +skip_optional: + return_value = objects_converter_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(bytes_object_converter__doc__, +"bytes_object_converter($module, a, /)\n" +"--\n" +"\n"); + +#define BYTES_OBJECT_CONVERTER_METHODDEF \ + {"bytes_object_converter", (PyCFunction)bytes_object_converter, METH_O, bytes_object_converter__doc__}, + +static PyObject * +bytes_object_converter_impl(PyObject *module, PyBytesObject *a); + +static PyObject * +bytes_object_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyBytesObject *a; + + if (!PyBytes_Check(arg)) { + _PyArg_BadArgument("bytes_object_converter", "argument", "bytes", arg); + goto exit; + } + a = (PyBytesObject *)arg; + return_value = bytes_object_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(byte_array_object_converter__doc__, +"byte_array_object_converter($module, a, /)\n" +"--\n" +"\n"); + +#define BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF \ + {"byte_array_object_converter", (PyCFunction)byte_array_object_converter, METH_O, byte_array_object_converter__doc__}, + +static PyObject * +byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a); + +static PyObject * +byte_array_object_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyByteArrayObject *a; + + if (!PyByteArray_Check(arg)) { + _PyArg_BadArgument("byte_array_object_converter", "argument", "bytearray", arg); + goto exit; + } + a = (PyByteArrayObject *)arg; + return_value = byte_array_object_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicode_converter__doc__, +"unicode_converter($module, a, /)\n" +"--\n" +"\n"); + +#define UNICODE_CONVERTER_METHODDEF \ + {"unicode_converter", (PyCFunction)unicode_converter, METH_O, unicode_converter__doc__}, + +static PyObject * +unicode_converter_impl(PyObject *module, PyObject *a); + +static PyObject * +unicode_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *a; + + if (!PyUnicode_Check(arg)) { + _PyArg_BadArgument("unicode_converter", "argument", "str", arg); + goto exit; + } + if (PyUnicode_READY(arg) == -1) { + goto exit; + } + a = arg; + return_value = unicode_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(bool_converter__doc__, +"bool_converter($module, a=True, b=True, c=True, /)\n" +"--\n" +"\n"); + +#define BOOL_CONVERTER_METHODDEF \ + {"bool_converter", (PyCFunction)(void(*)(void))bool_converter, METH_FASTCALL, bool_converter__doc__}, + +static PyObject * +bool_converter_impl(PyObject *module, int a, int b, int c); + +static PyObject * +bool_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int a = 1; + int b = 1; + int c = 1; + + if (!_PyArg_CheckPositional("bool_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyObject_IsTrue(args[0]); + if (a < 0) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + b = PyObject_IsTrue(args[1]); + if (b < 0) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = _PyLong_AsInt(args[2]); + if (c == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = bool_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(char_converter__doc__, +"char_converter($module, a=b\'A\', b=b\'\\x07\', c=b\'\\x08\', d=b\'\\t\', e=b\'\\n\',\n" +" f=b\'\\x0b\', g=b\'\\x0c\', h=b\'\\r\', i=b\'\"\', j=b\"\'\", k=b\'?\',\n" +" l=b\'\\\\\', m=b\'\\x00\', n=b\'\\xff\', /)\n" +"--\n" +"\n"); + +#define CHAR_CONVERTER_METHODDEF \ + {"char_converter", (PyCFunction)(void(*)(void))char_converter, METH_FASTCALL, char_converter__doc__}, + +static PyObject * +char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, + char f, char g, char h, char i, char j, char k, char l, + char m, char n); + +static PyObject * +char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char a = 'A'; + char b = '\x07'; + char c = '\x08'; + char d = '\t'; + char e = '\n'; + char f = '\x0b'; + char g = '\x0c'; + char h = '\r'; + char i = '"'; + char j = '\''; + char k = '?'; + char l = '\\'; + char m = '\x00'; + char n = '\xff'; + + if (!_PyArg_CheckPositional("char_converter", nargs, 0, 14)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyBytes_Check(args[0]) && PyBytes_GET_SIZE(args[0]) == 1) { + a = PyBytes_AS_STRING(args[0])[0]; + } + else if (PyByteArray_Check(args[0]) && PyByteArray_GET_SIZE(args[0]) == 1) { + a = PyByteArray_AS_STRING(args[0])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 1", "a byte string of length 1", args[0]); + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { + b = PyBytes_AS_STRING(args[1])[0]; + } + else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { + b = PyByteArray_AS_STRING(args[1])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 2", "a byte string of length 1", args[1]); + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (PyBytes_Check(args[2]) && PyBytes_GET_SIZE(args[2]) == 1) { + c = PyBytes_AS_STRING(args[2])[0]; + } + else if (PyByteArray_Check(args[2]) && PyByteArray_GET_SIZE(args[2]) == 1) { + c = PyByteArray_AS_STRING(args[2])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 3", "a byte string of length 1", args[2]); + goto exit; + } + if (nargs < 4) { + goto skip_optional; + } + if (PyBytes_Check(args[3]) && PyBytes_GET_SIZE(args[3]) == 1) { + d = PyBytes_AS_STRING(args[3])[0]; + } + else if (PyByteArray_Check(args[3]) && PyByteArray_GET_SIZE(args[3]) == 1) { + d = PyByteArray_AS_STRING(args[3])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 4", "a byte string of length 1", args[3]); + goto exit; + } + if (nargs < 5) { + goto skip_optional; + } + if (PyBytes_Check(args[4]) && PyBytes_GET_SIZE(args[4]) == 1) { + e = PyBytes_AS_STRING(args[4])[0]; + } + else if (PyByteArray_Check(args[4]) && PyByteArray_GET_SIZE(args[4]) == 1) { + e = PyByteArray_AS_STRING(args[4])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 5", "a byte string of length 1", args[4]); + goto exit; + } + if (nargs < 6) { + goto skip_optional; + } + if (PyBytes_Check(args[5]) && PyBytes_GET_SIZE(args[5]) == 1) { + f = PyBytes_AS_STRING(args[5])[0]; + } + else if (PyByteArray_Check(args[5]) && PyByteArray_GET_SIZE(args[5]) == 1) { + f = PyByteArray_AS_STRING(args[5])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 6", "a byte string of length 1", args[5]); + goto exit; + } + if (nargs < 7) { + goto skip_optional; + } + if (PyBytes_Check(args[6]) && PyBytes_GET_SIZE(args[6]) == 1) { + g = PyBytes_AS_STRING(args[6])[0]; + } + else if (PyByteArray_Check(args[6]) && PyByteArray_GET_SIZE(args[6]) == 1) { + g = PyByteArray_AS_STRING(args[6])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 7", "a byte string of length 1", args[6]); + goto exit; + } + if (nargs < 8) { + goto skip_optional; + } + if (PyBytes_Check(args[7]) && PyBytes_GET_SIZE(args[7]) == 1) { + h = PyBytes_AS_STRING(args[7])[0]; + } + else if (PyByteArray_Check(args[7]) && PyByteArray_GET_SIZE(args[7]) == 1) { + h = PyByteArray_AS_STRING(args[7])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 8", "a byte string of length 1", args[7]); + goto exit; + } + if (nargs < 9) { + goto skip_optional; + } + if (PyBytes_Check(args[8]) && PyBytes_GET_SIZE(args[8]) == 1) { + i = PyBytes_AS_STRING(args[8])[0]; + } + else if (PyByteArray_Check(args[8]) && PyByteArray_GET_SIZE(args[8]) == 1) { + i = PyByteArray_AS_STRING(args[8])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 9", "a byte string of length 1", args[8]); + goto exit; + } + if (nargs < 10) { + goto skip_optional; + } + if (PyBytes_Check(args[9]) && PyBytes_GET_SIZE(args[9]) == 1) { + j = PyBytes_AS_STRING(args[9])[0]; + } + else if (PyByteArray_Check(args[9]) && PyByteArray_GET_SIZE(args[9]) == 1) { + j = PyByteArray_AS_STRING(args[9])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 10", "a byte string of length 1", args[9]); + goto exit; + } + if (nargs < 11) { + goto skip_optional; + } + if (PyBytes_Check(args[10]) && PyBytes_GET_SIZE(args[10]) == 1) { + k = PyBytes_AS_STRING(args[10])[0]; + } + else if (PyByteArray_Check(args[10]) && PyByteArray_GET_SIZE(args[10]) == 1) { + k = PyByteArray_AS_STRING(args[10])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 11", "a byte string of length 1", args[10]); + goto exit; + } + if (nargs < 12) { + goto skip_optional; + } + if (PyBytes_Check(args[11]) && PyBytes_GET_SIZE(args[11]) == 1) { + l = PyBytes_AS_STRING(args[11])[0]; + } + else if (PyByteArray_Check(args[11]) && PyByteArray_GET_SIZE(args[11]) == 1) { + l = PyByteArray_AS_STRING(args[11])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 12", "a byte string of length 1", args[11]); + goto exit; + } + if (nargs < 13) { + goto skip_optional; + } + if (PyBytes_Check(args[12]) && PyBytes_GET_SIZE(args[12]) == 1) { + m = PyBytes_AS_STRING(args[12])[0]; + } + else if (PyByteArray_Check(args[12]) && PyByteArray_GET_SIZE(args[12]) == 1) { + m = PyByteArray_AS_STRING(args[12])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 13", "a byte string of length 1", args[12]); + goto exit; + } + if (nargs < 14) { + goto skip_optional; + } + if (PyBytes_Check(args[13]) && PyBytes_GET_SIZE(args[13]) == 1) { + n = PyBytes_AS_STRING(args[13])[0]; + } + else if (PyByteArray_Check(args[13]) && PyByteArray_GET_SIZE(args[13]) == 1) { + n = PyByteArray_AS_STRING(args[13])[0]; + } + else { + _PyArg_BadArgument("char_converter", "argument 14", "a byte string of length 1", args[13]); + goto exit; + } +skip_optional: + return_value = char_converter_impl(module, a, b, c, d, e, f, g, h, i, j, k, l, m, n); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_char_converter__doc__, +"unsigned_char_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_CHAR_CONVERTER_METHODDEF \ + {"unsigned_char_converter", (PyCFunction)(void(*)(void))unsigned_char_converter, METH_FASTCALL, unsigned_char_converter__doc__}, + +static PyObject * +unsigned_char_converter_impl(PyObject *module, unsigned char a, + unsigned char b, unsigned char c); + +static PyObject * +unsigned_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned char a = 12; + unsigned char b = 34; + unsigned char c = 56; + + if (!_PyArg_CheckPositional("unsigned_char_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + goto exit; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + goto exit; + } + else { + a = (unsigned char) ival; + } + } + if (nargs < 2) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + goto exit; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + goto exit; + } + else { + b = (unsigned char) ival; + } + } + if (nargs < 3) { + goto skip_optional; + } + { + unsigned long ival = PyLong_AsUnsignedLongMask(args[2]); + if (ival == (unsigned long)-1 && PyErr_Occurred()) { + goto exit; + } + else { + c = (unsigned char) ival; + } + } +skip_optional: + return_value = unsigned_char_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(short_converter__doc__, +"short_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define SHORT_CONVERTER_METHODDEF \ + {"short_converter", (PyCFunction)(void(*)(void))short_converter, METH_FASTCALL, short_converter__doc__}, + +static PyObject * +short_converter_impl(PyObject *module, short a); + +static PyObject * +short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short a = 12; + + if (!_PyArg_CheckPositional("short_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + a = (short) ival; + } + } +skip_optional: + return_value = short_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_short_converter__doc__, +"unsigned_short_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_SHORT_CONVERTER_METHODDEF \ + {"unsigned_short_converter", (PyCFunction)(void(*)(void))unsigned_short_converter, METH_FASTCALL, unsigned_short_converter__doc__}, + +static PyObject * +unsigned_short_converter_impl(PyObject *module, unsigned short a, + unsigned short b, unsigned short c); + +static PyObject * +unsigned_short_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned short a = 12; + unsigned short b = 34; + unsigned short c = 56; + + if (!_PyArg_CheckPositional("unsigned_short_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedShort_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedShort_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = (unsigned short)PyLong_AsUnsignedLongMask(args[2]); + if (c == (unsigned short)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = unsigned_short_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(int_converter__doc__, +"int_converter($module, a=12, b=34, c=45, /)\n" +"--\n" +"\n"); + +#define INT_CONVERTER_METHODDEF \ + {"int_converter", (PyCFunction)(void(*)(void))int_converter, METH_FASTCALL, int_converter__doc__}, + +static PyObject * +int_converter_impl(PyObject *module, int a, int b, int c); + +static PyObject * +int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int a = 12; + int b = 34; + int c = 45; + + if (!_PyArg_CheckPositional("int_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = _PyLong_AsInt(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + b = _PyLong_AsInt(args[1]); + if (b == -1 && PyErr_Occurred()) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyUnicode_Check(args[2])) { + _PyArg_BadArgument("int_converter", "argument 3", "a unicode character", args[2]); + goto exit; + } + if (PyUnicode_READY(args[2])) { + goto exit; + } + if (PyUnicode_GET_LENGTH(args[2]) != 1) { + _PyArg_BadArgument("int_converter", "argument 3", "a unicode character", args[2]); + goto exit; + } + c = PyUnicode_READ_CHAR(args[2], 0); +skip_optional: + return_value = int_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_int_converter__doc__, +"unsigned_int_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_INT_CONVERTER_METHODDEF \ + {"unsigned_int_converter", (PyCFunction)(void(*)(void))unsigned_int_converter, METH_FASTCALL, unsigned_int_converter__doc__}, + +static PyObject * +unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, + unsigned int c); + +static PyObject * +unsigned_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned int a = 12; + unsigned int b = 34; + unsigned int c = 56; + + if (!_PyArg_CheckPositional("unsigned_int_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedInt_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedInt_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + c = (unsigned int)PyLong_AsUnsignedLongMask(args[2]); + if (c == (unsigned int)-1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = unsigned_int_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(long_converter__doc__, +"long_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define LONG_CONVERTER_METHODDEF \ + {"long_converter", (PyCFunction)(void(*)(void))long_converter, METH_FASTCALL, long_converter__doc__}, + +static PyObject * +long_converter_impl(PyObject *module, long a); + +static PyObject * +long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + long a = 12; + + if (!_PyArg_CheckPositional("long_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyLong_AsLong(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = long_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_long_converter__doc__, +"unsigned_long_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_LONG_CONVERTER_METHODDEF \ + {"unsigned_long_converter", (PyCFunction)(void(*)(void))unsigned_long_converter, METH_FASTCALL, unsigned_long_converter__doc__}, + +static PyObject * +unsigned_long_converter_impl(PyObject *module, unsigned long a, + unsigned long b, unsigned long c); + +static PyObject * +unsigned_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned long a = 12; + unsigned long b = 34; + unsigned long c = 56; + + if (!_PyArg_CheckPositional("unsigned_long_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedLong_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyLong_Check(args[2])) { + _PyArg_BadArgument("unsigned_long_converter", "argument 3", "int", args[2]); + goto exit; + } + c = PyLong_AsUnsignedLongMask(args[2]); +skip_optional: + return_value = unsigned_long_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(long_long_converter__doc__, +"long_long_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define LONG_LONG_CONVERTER_METHODDEF \ + {"long_long_converter", (PyCFunction)(void(*)(void))long_long_converter, METH_FASTCALL, long_long_converter__doc__}, + +static PyObject * +long_long_converter_impl(PyObject *module, long long a); + +static PyObject * +long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + long long a = 12; + + if (!_PyArg_CheckPositional("long_long_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + a = PyLong_AsLongLong(args[0]); + if (a == -1 && PyErr_Occurred()) { + goto exit; + } +skip_optional: + return_value = long_long_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(unsigned_long_long_converter__doc__, +"unsigned_long_long_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define UNSIGNED_LONG_LONG_CONVERTER_METHODDEF \ + {"unsigned_long_long_converter", (PyCFunction)(void(*)(void))unsigned_long_long_converter, METH_FASTCALL, unsigned_long_long_converter__doc__}, + +static PyObject * +unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, + unsigned long long b, unsigned long long c); + +static PyObject * +unsigned_long_long_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + unsigned long long a = 12; + unsigned long long b = 34; + unsigned long long c = 56; + + if (!_PyArg_CheckPositional("unsigned_long_long_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_UnsignedLongLong_Converter(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyLong_UnsignedLongLong_Converter(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!PyLong_Check(args[2])) { + _PyArg_BadArgument("unsigned_long_long_converter", "argument 3", "int", args[2]); + goto exit; + } + c = PyLong_AsUnsignedLongLongMask(args[2]); +skip_optional: + return_value = unsigned_long_long_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_ssize_t_converter__doc__, +"py_ssize_t_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define PY_SSIZE_T_CONVERTER_METHODDEF \ + {"py_ssize_t_converter", (PyCFunction)(void(*)(void))py_ssize_t_converter, METH_FASTCALL, py_ssize_t_converter__doc__}, + +static PyObject * +py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c); + +static PyObject * +py_ssize_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t a = 12; + Py_ssize_t b = 34; + Py_ssize_t c = 56; + + if (!_PyArg_CheckPositional("py_ssize_t_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[0]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + a = ival; + } + if (nargs < 2) { + goto skip_optional; + } + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + b = ival; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_Py_convert_optional_to_ssize_t(args[2], &c)) { + goto exit; + } +skip_optional: + return_value = py_ssize_t_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(slice_index_converter__doc__, +"slice_index_converter($module, a=12, b=34, c=56, /)\n" +"--\n" +"\n"); + +#define SLICE_INDEX_CONVERTER_METHODDEF \ + {"slice_index_converter", (PyCFunction)(void(*)(void))slice_index_converter, METH_FASTCALL, slice_index_converter__doc__}, + +static PyObject * +slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c); + +static PyObject * +slice_index_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_ssize_t a = 12; + Py_ssize_t b = 34; + Py_ssize_t c = 56; + + if (!_PyArg_CheckPositional("slice_index_converter", nargs, 0, 3)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[0], &a)) { + goto exit; + } + if (nargs < 2) { + goto skip_optional; + } + if (!_PyEval_SliceIndexNotNone(args[1], &b)) { + goto exit; + } + if (nargs < 3) { + goto skip_optional; + } + if (!_PyEval_SliceIndex(args[2], &c)) { + goto exit; + } +skip_optional: + return_value = slice_index_converter_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(size_t_converter__doc__, +"size_t_converter($module, a=12, /)\n" +"--\n" +"\n"); + +#define SIZE_T_CONVERTER_METHODDEF \ + {"size_t_converter", (PyCFunction)(void(*)(void))size_t_converter, METH_FASTCALL, size_t_converter__doc__}, + +static PyObject * +size_t_converter_impl(PyObject *module, size_t a); + +static PyObject * +size_t_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + size_t a = 12; + + if (!_PyArg_CheckPositional("size_t_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (!_PyLong_Size_t_Converter(args[0], &a)) { + goto exit; + } +skip_optional: + return_value = size_t_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(float_converter__doc__, +"float_converter($module, a=12.5, /)\n" +"--\n" +"\n"); + +#define FLOAT_CONVERTER_METHODDEF \ + {"float_converter", (PyCFunction)(void(*)(void))float_converter, METH_FASTCALL, float_converter__doc__}, + +static PyObject * +float_converter_impl(PyObject *module, float a); + +static PyObject * +float_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + float a = 12.5; + + if (!_PyArg_CheckPositional("float_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyFloat_CheckExact(args[0])) { + a = (float) (PyFloat_AS_DOUBLE(args[0])); + } + else + { + a = (float) PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional: + return_value = float_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(double_converter__doc__, +"double_converter($module, a=12.5, /)\n" +"--\n" +"\n"); + +#define DOUBLE_CONVERTER_METHODDEF \ + {"double_converter", (PyCFunction)(void(*)(void))double_converter, METH_FASTCALL, double_converter__doc__}, + +static PyObject * +double_converter_impl(PyObject *module, double a); + +static PyObject * +double_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + double a = 12.5; + + if (!_PyArg_CheckPositional("double_converter", nargs, 0, 1)) { + goto exit; + } + if (nargs < 1) { + goto skip_optional; + } + if (PyFloat_CheckExact(args[0])) { + a = PyFloat_AS_DOUBLE(args[0]); + } + else + { + a = PyFloat_AsDouble(args[0]); + if (a == -1.0 && PyErr_Occurred()) { + goto exit; + } + } +skip_optional: + return_value = double_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_complex_converter__doc__, +"py_complex_converter($module, a, /)\n" +"--\n" +"\n"); + +#define PY_COMPLEX_CONVERTER_METHODDEF \ + {"py_complex_converter", (PyCFunction)py_complex_converter, METH_O, py_complex_converter__doc__}, + +static PyObject * +py_complex_converter_impl(PyObject *module, Py_complex a); + +static PyObject * +py_complex_converter(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_complex a; + + a = PyComplex_AsCComplex(arg); + if (PyErr_Occurred()) { + goto exit; + } + return_value = py_complex_converter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(str_converter__doc__, +"str_converter($module, a=\'a\', b=\'b\', c=\'c\', /)\n" +"--\n" +"\n"); + +#define STR_CONVERTER_METHODDEF \ + {"str_converter", (PyCFunction)(void(*)(void))str_converter, METH_FASTCALL, str_converter__doc__}, + +static PyObject * +str_converter_impl(PyObject *module, const char *a, const char *b, + const char *c, Py_ssize_clean_t c_length); + +static PyObject * +str_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *a = "a"; + const char *b = "b"; + const char *c = "c"; + Py_ssize_clean_t c_length; + + if (!_PyArg_ParseStack(args, nargs, "|sys#:str_converter", + &a, &b, &c, &c_length)) { + goto exit; + } + return_value = str_converter_impl(module, a, b, c, c_length); + +exit: + return return_value; +} + +PyDoc_STRVAR(str_converter_encoding__doc__, +"str_converter_encoding($module, a, b, c, /)\n" +"--\n" +"\n"); + +#define STR_CONVERTER_ENCODING_METHODDEF \ + {"str_converter_encoding", (PyCFunction)(void(*)(void))str_converter_encoding, METH_FASTCALL, str_converter_encoding__doc__}, + +static PyObject * +str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, + Py_ssize_clean_t c_length); + +static PyObject * +str_converter_encoding(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char *a = NULL; + char *b = NULL; + char *c = NULL; + Py_ssize_clean_t c_length; + + if (!_PyArg_ParseStack(args, nargs, "esetet#:str_converter_encoding", + "idna", &a, "idna", &b, "idna", &c, &c_length)) { + goto exit; + } + return_value = str_converter_encoding_impl(module, a, b, c, c_length); + /* Post parse cleanup for a */ + PyMem_FREE(a); + /* Post parse cleanup for b */ + PyMem_FREE(b); + /* Post parse cleanup for c */ + PyMem_FREE(c); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_buffer_converter__doc__, +"py_buffer_converter($module, a, b, /)\n" +"--\n" +"\n"); + +#define PY_BUFFER_CONVERTER_METHODDEF \ + {"py_buffer_converter", (PyCFunction)(void(*)(void))py_buffer_converter, METH_FASTCALL, py_buffer_converter__doc__}, + +static PyObject * +py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b); + +static PyObject * +py_buffer_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_buffer a = {NULL, NULL}; + Py_buffer b = {NULL, NULL}; + + if (!_PyArg_ParseStack(args, nargs, "z*w*:py_buffer_converter", + &a, &b)) { + goto exit; + } + return_value = py_buffer_converter_impl(module, &a, &b); + +exit: + /* Cleanup for a */ + if (a.obj) { + PyBuffer_Release(&a); + } + /* Cleanup for b */ + if (b.obj) { + PyBuffer_Release(&b); + } + + return return_value; +} + +PyDoc_STRVAR(keywords__doc__, +"keywords($module, /, a, b)\n" +"--\n" +"\n"); + +#define KEYWORDS_METHODDEF \ + {"keywords", (PyCFunction)(void(*)(void))keywords, METH_FASTCALL|METH_KEYWORDS, keywords__doc__}, + +static PyObject * +keywords_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +keywords(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keywords", 0}; + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = keywords_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_kwonly__doc__, +"keywords_kwonly($module, /, a, *, b)\n" +"--\n" +"\n"); + +#define KEYWORDS_KWONLY_METHODDEF \ + {"keywords_kwonly", (PyCFunction)(void(*)(void))keywords_kwonly, METH_FASTCALL|METH_KEYWORDS, keywords_kwonly__doc__}, + +static PyObject * +keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +keywords_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "b", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keywords_kwonly", 0}; + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = keywords_kwonly_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_opt__doc__, +"keywords_opt($module, /, a, b=None, c=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_OPT_METHODDEF \ + {"keywords_opt", (PyCFunction)(void(*)(void))keywords_opt, METH_FASTCALL|METH_KEYWORDS, keywords_opt__doc__}, + +static PyObject * +keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c); + +static PyObject * +keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keywords_opt", 0}; + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + c = args[2]; +skip_optional_pos: + return_value = keywords_opt_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_opt_kwonly__doc__, +"keywords_opt_kwonly($module, /, a, b=None, *, c=None, d=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_OPT_KWONLY_METHODDEF \ + {"keywords_opt_kwonly", (PyCFunction)(void(*)(void))keywords_opt_kwonly, METH_FASTCALL|METH_KEYWORDS, keywords_opt_kwonly__doc__}, + +static PyObject * +keywords_opt_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +keywords_opt_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keywords_opt_kwonly", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = keywords_opt_kwonly_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(keywords_kwonly_opt__doc__, +"keywords_kwonly_opt($module, /, a, *, b=None, c=None)\n" +"--\n" +"\n"); + +#define KEYWORDS_KWONLY_OPT_METHODDEF \ + {"keywords_kwonly_opt", (PyCFunction)(void(*)(void))keywords_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, keywords_kwonly_opt__doc__}, + +static PyObject * +keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +static PyObject * +keywords_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", "b", "c", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keywords_kwonly_opt", 0}; + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + b = args[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + c = args[2]; +skip_optional_kwonly: + return_value = keywords_kwonly_opt_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords__doc__, +"posonly_keywords($module, a, /, b)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_METHODDEF \ + {"posonly_keywords", (PyCFunction)(void(*)(void))posonly_keywords, METH_FASTCALL|METH_KEYWORDS, posonly_keywords__doc__}, + +static PyObject * +posonly_keywords_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +posonly_keywords(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_keywords", 0}; + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = posonly_keywords_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_kwonly__doc__, +"posonly_kwonly($module, a, /, *, b)\n" +"--\n" +"\n"); + +#define POSONLY_KWONLY_METHODDEF \ + {"posonly_kwonly", (PyCFunction)(void(*)(void))posonly_kwonly, METH_FASTCALL|METH_KEYWORDS, posonly_kwonly__doc__}, + +static PyObject * +posonly_kwonly_impl(PyObject *module, PyObject *a, PyObject *b); + +static PyObject * +posonly_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_kwonly", 0}; + PyObject *argsbuf[2]; + PyObject *a; + PyObject *b; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + return_value = posonly_kwonly_impl(module, a, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_kwonly__doc__, +"posonly_keywords_kwonly($module, a, /, b, *, c)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_KWONLY_METHODDEF \ + {"posonly_keywords_kwonly", (PyCFunction)(void(*)(void))posonly_keywords_kwonly, METH_FASTCALL|METH_KEYWORDS, posonly_keywords_kwonly__doc__}, + +static PyObject * +posonly_keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c); + +static PyObject * +posonly_keywords_kwonly(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", "c", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_keywords_kwonly", 0}; + PyObject *argsbuf[3]; + PyObject *a; + PyObject *b; + PyObject *c; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + return_value = posonly_keywords_kwonly_impl(module, a, b, c); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_opt__doc__, +"posonly_keywords_opt($module, a, /, b, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_OPT_METHODDEF \ + {"posonly_keywords_opt", (PyCFunction)(void(*)(void))posonly_keywords_opt, METH_FASTCALL|METH_KEYWORDS, posonly_keywords_opt__doc__}, + +static PyObject * +posonly_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_keywords_opt", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + d = args[3]; +skip_optional_pos: + return_value = posonly_keywords_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_keywords_opt__doc__, +"posonly_opt_keywords_opt($module, a, b=None, /, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KEYWORDS_OPT_METHODDEF \ + {"posonly_opt_keywords_opt", (PyCFunction)(void(*)(void))posonly_opt_keywords_opt, METH_FASTCALL|METH_KEYWORDS, posonly_opt_keywords_opt__doc__}, + +static PyObject * +posonly_opt_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_opt_keywords_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_opt_keywords_opt", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 4, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + d = args[3]; +skip_optional_pos: + return_value = posonly_opt_keywords_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_kwonly_opt__doc__, +"posonly_kwonly_opt($module, a, /, *, b, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_KWONLY_OPT_METHODDEF \ + {"posonly_kwonly_opt", (PyCFunction)(void(*)(void))posonly_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, posonly_kwonly_opt__doc__}, + +static PyObject * +posonly_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_kwonly_opt", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_kwonly_opt__doc__, +"posonly_opt_kwonly_opt($module, a, b=None, /, *, c=None, d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_opt_kwonly_opt", (PyCFunction)(void(*)(void))posonly_opt_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, posonly_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d); + +static PyObject * +posonly_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_opt_kwonly_opt", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_opt_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_kwonly_opt__doc__, +"posonly_keywords_kwonly_opt($module, a, /, b, *, c, d=None, e=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_KWONLY_OPT_METHODDEF \ + {"posonly_keywords_kwonly_opt", (PyCFunction)(void(*)(void))posonly_keywords_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, posonly_keywords_kwonly_opt__doc__}, + +static PyObject * +posonly_keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e); + +static PyObject * +posonly_keywords_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_keywords_kwonly_opt", 0}; + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3; + PyObject *a; + PyObject *b; + PyObject *c; + PyObject *d = Py_None; + PyObject *e = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + c = args[2]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + d = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + e = args[4]; +skip_optional_kwonly: + return_value = posonly_keywords_kwonly_opt_impl(module, a, b, c, d, e); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_keywords_opt_kwonly_opt__doc__, +"posonly_keywords_opt_kwonly_opt($module, a, /, b, c=None, *, d=None,\n" +" e=None)\n" +"--\n" +"\n"); + +#define POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_keywords_opt_kwonly_opt", (PyCFunction)(void(*)(void))posonly_keywords_opt_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, posonly_keywords_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d, + PyObject *e); + +static PyObject * +posonly_keywords_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "b", "c", "d", "e", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_keywords_opt_kwonly_opt", 0}; + PyObject *argsbuf[5]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *a; + PyObject *b; + PyObject *c = Py_None; + PyObject *d = Py_None; + PyObject *e = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + b = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[3]) { + d = args[3]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + e = args[4]; +skip_optional_kwonly: + return_value = posonly_keywords_opt_kwonly_opt_impl(module, a, b, c, d, e); + +exit: + return return_value; +} + +PyDoc_STRVAR(posonly_opt_keywords_opt_kwonly_opt__doc__, +"posonly_opt_keywords_opt_kwonly_opt($module, a, b=None, /, c=None, *,\n" +" d=None)\n" +"--\n" +"\n"); + +#define POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF \ + {"posonly_opt_keywords_opt_kwonly_opt", (PyCFunction)(void(*)(void))posonly_opt_keywords_opt_kwonly_opt, METH_FASTCALL|METH_KEYWORDS, posonly_opt_keywords_opt_kwonly_opt__doc__}, + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d); + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"", "", "c", "d", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "posonly_opt_keywords_opt_kwonly_opt", 0}; + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *a; + PyObject *b = Py_None; + PyObject *c = Py_None; + PyObject *d = Py_None; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + if (nargs < 2) { + goto skip_optional_posonly; + } + noptargs--; + b = args[1]; +skip_optional_posonly: + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + c = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + d = args[3]; +skip_optional_kwonly: + return_value = posonly_opt_keywords_opt_kwonly_opt_impl(module, a, b, c, d); + +exit: + return return_value; +} + +PyDoc_STRVAR(keyword_only_parameter__doc__, +"keyword_only_parameter($module, /, *, a)\n" +"--\n" +"\n"); + +#define KEYWORD_ONLY_PARAMETER_METHODDEF \ + {"keyword_only_parameter", (PyCFunction)(void(*)(void))keyword_only_parameter, METH_FASTCALL|METH_KEYWORDS, keyword_only_parameter__doc__}, + +static PyObject * +keyword_only_parameter_impl(PyObject *module, PyObject *a); + +static PyObject * +keyword_only_parameter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"a", NULL}; + static _PyArg_Parser _parser = {NULL, _keywords, "keyword_only_parameter", 0}; + PyObject *argsbuf[1]; + PyObject *a; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 1, argsbuf); + if (!args) { + goto exit; + } + a = args[0]; + return_value = keyword_only_parameter_impl(module, a); + +exit: + return return_value; +} + +PyDoc_STRVAR(gh_99240_double_free__doc__, +"gh_99240_double_free($module, a, b, /)\n" +"--\n" +"\n" +"Proof-of-concept of GH-99240 double-free bug."); + +#define GH_99240_DOUBLE_FREE_METHODDEF \ + {"gh_99240_double_free", (PyCFunction)(void(*)(void))gh_99240_double_free, METH_FASTCALL, gh_99240_double_free__doc__}, + +static PyObject * +gh_99240_double_free_impl(PyObject *module, char *a, char *b); + +static PyObject * +gh_99240_double_free(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + char *a = NULL; + char *b = NULL; + + if (!_PyArg_ParseStack(args, nargs, "eses:gh_99240_double_free", + "idna", &a, "idna", &b)) { + goto exit; + } + return_value = gh_99240_double_free_impl(module, a, b); + /* Post parse cleanup for a */ + PyMem_FREE(a); + /* Post parse cleanup for b */ + PyMem_FREE(b); + +exit: + return return_value; +} +/*[clinic end generated code: output=ecc55cbeac4adae6 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Modules/clinic/_winapi.c.h python3.10-3.10.12/Modules/clinic/_winapi.c.h --- python3.10-3.10.7/Modules/clinic/_winapi.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/clinic/_winapi.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -192,7 +192,7 @@ DWORD protect; DWORD max_size_high; DWORD max_size_low; - LPCWSTR name; + LPCWSTR name = NULL; HANDLE _return_value; if (!_PyArg_ParseStack(args, nargs, "" F_HANDLE "" F_POINTER "kkkO&:CreateFileMapping", @@ -233,8 +233,8 @@ _winapi_CreateJunction(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - LPCWSTR src_path; - LPCWSTR dst_path; + LPCWSTR src_path = NULL; + LPCWSTR dst_path = NULL; if (!_PyArg_CheckPositional("CreateJunction", nargs, 2, 2)) { goto exit; @@ -394,14 +394,14 @@ _winapi_CreateProcess(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const Py_UNICODE *application_name; + const Py_UNICODE *application_name = NULL; PyObject *command_line; PyObject *proc_attrs; PyObject *thread_attrs; BOOL inherit_handles; DWORD creation_flags; PyObject *env_mapping; - const Py_UNICODE *current_directory; + const Py_UNICODE *current_directory = NULL; PyObject *startup_info; if (!_PyArg_ParseStack(args, nargs, "O&OOOikOO&O:CreateProcess", @@ -731,6 +731,32 @@ return return_value; } +PyDoc_STRVAR(_winapi_UnmapViewOfFile__doc__, +"UnmapViewOfFile($module, address, /)\n" +"--\n" +"\n"); + +#define _WINAPI_UNMAPVIEWOFFILE_METHODDEF \ + {"UnmapViewOfFile", (PyCFunction)_winapi_UnmapViewOfFile, METH_O, _winapi_UnmapViewOfFile__doc__}, + +static PyObject * +_winapi_UnmapViewOfFile_impl(PyObject *module, LPCVOID address); + +static PyObject * +_winapi_UnmapViewOfFile(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + LPCVOID address; + + if (!PyArg_Parse(arg, "" F_POINTER ":UnmapViewOfFile", &address)) { + goto exit; + } + return_value = _winapi_UnmapViewOfFile_impl(module, address); + +exit: + return return_value; +} + PyDoc_STRVAR(_winapi_OpenFileMapping__doc__, "OpenFileMapping($module, desired_access, inherit_handle, name, /)\n" "--\n" @@ -749,7 +775,7 @@ PyObject *return_value = NULL; DWORD desired_access; BOOL inherit_handle; - LPCWSTR name; + LPCWSTR name = NULL; HANDLE _return_value; if (!_PyArg_ParseStack(args, nargs, "kiO&:OpenFileMapping", @@ -1216,4 +1242,4 @@ exit: return return_value; } -/*[clinic end generated code: output=8e13179bf25bdea5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=acabf8f2b5cc44a1 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Modules/cmathmodule.c python3.10-3.10.12/Modules/cmathmodule.c --- python3.10-3.10.7/Modules/cmathmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/cmathmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -950,12 +950,12 @@ log(z[, base]) -> the logarithm of z to the given base. -If the base not specified, returns the natural logarithm (base e) of z. +If the base is not specified, returns the natural logarithm (base e) of z. [clinic start generated code]*/ static PyObject * cmath_log_impl(PyObject *module, Py_complex x, PyObject *y_obj) -/*[clinic end generated code: output=4effdb7d258e0d94 input=230ed3a71ecd000a]*/ +/*[clinic end generated code: output=4effdb7d258e0d94 input=e1f81d4fcfd26497]*/ { Py_complex y; diff -Nru python3.10-3.10.7/Modules/_csv.c python3.10-3.10.12/Modules/_csv.c --- python3.10-3.10.7/Modules/_csv.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_csv.c 2023-06-06 22:30:33.000000000 +0000 @@ -698,7 +698,7 @@ self->state = ESCAPED_CHAR; } else if (c == ' ' && dialect->skipinitialspace) - /* ignore space at start of field */ + /* ignore spaces at start of field */ ; else if (c == dialect->delimiter) { /* save empty field */ @@ -1603,9 +1603,9 @@ " quoting character. It defaults to '\"'.\n" " * delimiter - specifies a one-character string to use as the\n" " field separator. It defaults to ','.\n" -" * skipinitialspace - specifies how to interpret whitespace which\n" -" immediately follows a delimiter. It defaults to False, which\n" -" means that whitespace immediately following a delimiter is part\n" +" * skipinitialspace - specifies how to interpret spaces which\n" +" immediately follow a delimiter. It defaults to False, which\n" +" means that spaces immediately following a delimiter is part\n" " of the following field.\n" " * lineterminator - specifies the character sequence which should\n" " terminate rows.\n" diff -Nru python3.10-3.10.7/Modules/_ctypes/callbacks.c python3.10-3.10.12/Modules/_ctypes/callbacks.c --- python3.10-3.10.7/Modules/_ctypes/callbacks.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ctypes/callbacks.c 2023-06-06 22:30:33.000000000 +0000 @@ -282,15 +282,14 @@ "of ctypes callback function", callable); } - else if (keep == Py_None) { - /* Nothing to keep */ - Py_DECREF(keep); - } else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { - if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning, - "memory leak in callback function.", - 1)) - { + if (keep == Py_None) { + /* Nothing to keep */ + Py_DECREF(keep); + } + else if (PyErr_WarnEx(PyExc_RuntimeWarning, + "memory leak in callback function.", + 1) == -1) { _PyErr_WriteUnraisableMsg("on converting result " "of ctypes callback function", callable); diff -Nru python3.10-3.10.7/Modules/_ctypes/callproc.c python3.10-3.10.12/Modules/_ctypes/callproc.c --- python3.10-3.10.7/Modules/_ctypes/callproc.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ctypes/callproc.c 2023-06-06 22:30:33.000000000 +0000 @@ -1014,7 +1014,10 @@ PyErr_Fetch(&tp, &v, &tb); PyErr_NormalizeException(&tp, &v, &tb); - cls_str = PyObject_Str(tp); + if (PyType_Check(tp)) + cls_str = PyUnicode_FromString(_PyType_Name((PyTypeObject *)tp)); + else + cls_str = PyObject_Str(tp); if (cls_str) { PyUnicode_AppendAndDel(&s, cls_str); PyUnicode_AppendAndDel(&s, PyUnicode_FromString(": ")); diff -Nru python3.10-3.10.7/Modules/_ctypes/_ctypes.c python3.10-3.10.12/Modules/_ctypes/_ctypes.c --- python3.10-3.10.7/Modules/_ctypes/_ctypes.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ctypes/_ctypes.c 2023-06-06 22:30:33.000000000 +0000 @@ -406,6 +406,7 @@ typedef struct { PyObject_HEAD void *ptr; + PyObject *keep; // If set, a reference to the original CDataObject. } StructParamObject; @@ -413,6 +414,7 @@ StructParam_dealloc(PyObject *myself) { StructParamObject *self = (StructParamObject *)myself; + Py_XDECREF(self->keep); PyMem_Free(self->ptr); Py_TYPE(self)->tp_free(myself); } @@ -460,6 +462,7 @@ StructParamObject *struct_param = (StructParamObject *)obj; struct_param->ptr = ptr; + struct_param->keep = Py_NewRef(self); } else { ptr = self->b_ptr; obj = (PyObject *)self; @@ -2795,11 +2798,33 @@ { NULL }, }; -static int PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) +/* Find the innermost type of an array type, returning a borrowed reference */ +static PyObject * +PyCData_item_type(PyObject *type) +{ + if (PyCArrayTypeObject_Check(type)) { + StgDictObject *stg_dict; + PyObject *elem_type; + + /* asserts used here as these are all guaranteed by construction */ + stg_dict = PyType_stgdict(type); + assert(stg_dict); + elem_type = stg_dict->proto; + assert(elem_type); + return PyCData_item_type(elem_type); + } + else { + return type; + } +} + +static int +PyCData_NewGetBuffer(PyObject *myself, Py_buffer *view, int flags) { CDataObject *self = (CDataObject *)myself; StgDictObject *dict = PyObject_stgdict(myself); - Py_ssize_t i; + PyObject *item_type = PyCData_item_type((PyObject*)Py_TYPE(myself)); + StgDictObject *item_dict = PyType_stgdict(item_type); if (view == NULL) return 0; @@ -2812,12 +2837,7 @@ view->format = dict->format ? dict->format : "B"; view->ndim = dict->ndim; view->shape = dict->shape; - view->itemsize = self->b_size; - if (view->itemsize) { - for (i = 0; i < view->ndim; ++i) { - view->itemsize /= dict->shape[i]; - } - } + view->itemsize = item_dict->size; view->strides = NULL; view->suboffsets = NULL; view->internal = NULL; diff -Nru python3.10-3.10.7/Modules/_ctypes/_ctypes_test.c python3.10-3.10.12/Modules/_ctypes/_ctypes_test.c --- python3.10-3.10.7/Modules/_ctypes/_ctypes_test.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ctypes/_ctypes_test.c 2023-06-06 22:30:33.000000000 +0000 @@ -1032,6 +1032,12 @@ #endif +EXPORT(int) +_testfunc_pylist_append(PyObject *list, PyObject *item) +{ + return PyList_Append(list, item); +} + static struct PyModuleDef_Slot _ctypes_test_slots[] = { {0, NULL} }; diff -Nru python3.10-3.10.7/Modules/_ctypes/stgdict.c python3.10-3.10.12/Modules/_ctypes/stgdict.c --- python3.10-3.10.7/Modules/_ctypes/stgdict.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ctypes/stgdict.c 2023-06-06 22:30:33.000000000 +0000 @@ -420,8 +420,11 @@ } stgdict = PyType_stgdict(type); - if (!stgdict) + if (!stgdict) { + PyErr_SetString(PyExc_TypeError, + "ctypes state is not initialized"); return -1; + } /* If this structure/union is already marked final we cannot assign _fields_ anymore. */ diff -Nru python3.10-3.10.7/Modules/expat/COPYING python3.10-3.10.12/Modules/expat/COPYING --- python3.10-3.10.7/Modules/expat/COPYING 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/COPYING 2023-06-06 22:30:33.000000000 +0000 @@ -1,5 +1,5 @@ Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper -Copyright (c) 2001-2019 Expat maintainers +Copyright (c) 2001-2022 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff -Nru python3.10-3.10.7/Modules/expat/expat.h python3.10-3.10.12/Modules/expat/expat.h --- python3.10-3.10.7/Modules/expat/expat.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/expat.h 2023-06-06 22:30:33.000000000 +0000 @@ -1054,8 +1054,8 @@ See http://semver.org. */ #define XML_MAJOR_VERSION 2 -#define XML_MINOR_VERSION 4 -#define XML_MICRO_VERSION 7 +#define XML_MINOR_VERSION 5 +#define XML_MICRO_VERSION 0 #ifdef __cplusplus } diff -Nru python3.10-3.10.7/Modules/expat/internal.h python3.10-3.10.12/Modules/expat/internal.h --- python3.10-3.10.7/Modules/expat/internal.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/internal.h 2023-06-06 22:30:33.000000000 +0000 @@ -28,7 +28,7 @@ Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2003 Greg Stein - Copyright (c) 2016-2021 Sebastian Pipping + Copyright (c) 2016-2022 Sebastian Pipping Copyright (c) 2018 Yury Gribov Copyright (c) 2019 David Loffredo Licensed under the MIT license: @@ -107,7 +107,9 @@ #include // ULONG_MAX -#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO) +#if defined(_WIN32) \ + && (! defined(__USE_MINGW_ANSI_STDIO) \ + || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0)) # define EXPAT_FMT_ULL(midpart) "%" midpart "I64u" # if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d" diff -Nru python3.10-3.10.7/Modules/expat/siphash.h python3.10-3.10.12/Modules/expat/siphash.h --- python3.10-3.10.7/Modules/expat/siphash.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/siphash.h 2023-06-06 22:30:33.000000000 +0000 @@ -106,7 +106,7 @@ * if this code is included and compiled as C++; related GCC warning is: * warning: use of C++11 long long integer constant [-Wlong-long] */ -#define _SIP_ULL(high, low) (((uint64_t)high << 32) | low) +#define _SIP_ULL(high, low) ((((uint64_t)high) << 32) | (low)) #define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) diff -Nru python3.10-3.10.7/Modules/expat/xmlparse.c python3.10-3.10.12/Modules/expat/xmlparse.c --- python3.10-3.10.7/Modules/expat/xmlparse.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/xmlparse.c 2023-06-06 22:30:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* fcb1a62fefa945567301146eb98e3ad3413e823a41c4378e84e8b6b6f308d824 (2.4.7+) +/* 5ab094ffadd6edfc94c3eee53af44a86951f9f1f0933ada3114bbce2bfb02c99 (2.5.0+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -19,7 +19,7 @@ Copyright (c) 2016 Gustavo Grieco Copyright (c) 2016 Pascal Cuoq Copyright (c) 2016 Ed Schouten - Copyright (c) 2017-2018 Rhodri James + Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Václav Slavík Copyright (c) 2017 Viktor Szakats Copyright (c) 2017 Chanho Park @@ -35,6 +35,7 @@ Copyright (c) 2021 Dong-hee Na Copyright (c) 2022 Samanta Navarro Copyright (c) 2022 Jeffrey Walton + Copyright (c) 2022 Jann Horn Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -1068,6 +1069,14 @@ parserInit(parser, encodingName); if (encodingName && ! parser->m_protocolEncodingName) { + if (dtd) { + // We need to stop the upcoming call to XML_ParserFree from happily + // destroying parser->m_dtd because the DTD is shared with the parent + // parser and the only guard that keeps XML_ParserFree from destroying + // parser->m_dtd is parser->m_isParamEntity but it will be set to + // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all). + parser->m_dtd = NULL; + } XML_ParserFree(parser); return NULL; } @@ -3011,9 +3020,6 @@ int len; const char *rawName; TAG *tag = parser->m_tagStack; - parser->m_tagStack = tag->parent; - tag->parent = parser->m_freeTagList; - parser->m_freeTagList = tag; rawName = s + enc->minBytesPerChar * 2; len = XmlNameLength(enc, rawName); if (len != tag->rawNameLength @@ -3021,6 +3027,9 @@ *eventPP = rawName; return XML_ERROR_TAG_MISMATCH; } + parser->m_tagStack = tag->parent; + tag->parent = parser->m_freeTagList; + parser->m_freeTagList = tag; --parser->m_tagLevel; if (parser->m_endElementHandler) { const XML_Char *localPart; @@ -4271,7 +4280,7 @@ const XML_Char *storedEncName = NULL; const ENCODING *newEncoding = NULL; const char *version = NULL; - const char *versionend; + const char *versionend = NULL; const XML_Char *storedversion = NULL; int standalone = -1; @@ -4975,10 +4984,10 @@ parser->m_handlerArg, parser->m_declElementType->name, parser->m_declAttributeId->name, parser->m_declAttributeType, 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); - poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } } + poolClear(&parser->m_tempPool); break; case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: case XML_ROLE_FIXED_ATTRIBUTE_VALUE: @@ -5386,7 +5395,7 @@ * * If 'standalone' is false, the DTD must have no * parameter entities or we wouldn't have passed the outer - * 'if' statement. That measn the only entity in the hash + * 'if' statement. That means the only entity in the hash * table is the external subset name "#" which cannot be * given as a parameter entity name in XML syntax, so the * lookup must have returned NULL and we don't even reach @@ -5798,19 +5807,27 @@ if (result != XML_ERROR_NONE) return result; - else if (textEnd != next - && parser->m_parsingStatus.parsing == XML_SUSPENDED) { + + if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { entity->processed = (int)(next - (const char *)entity->textPtr); return result; - } else { + } + #ifdef XML_DTD - entityTrackingOnClose(parser, entity, __LINE__); + entityTrackingOnClose(parser, entity, __LINE__); #endif - entity->open = XML_FALSE; - parser->m_openInternalEntities = openEntity->next; - /* put openEntity back in list of free instances */ - openEntity->next = parser->m_freeInternalEntities; - parser->m_freeInternalEntities = openEntity; + entity->open = XML_FALSE; + parser->m_openInternalEntities = openEntity->next; + /* put openEntity back in list of free instances */ + openEntity->next = parser->m_freeInternalEntities; + parser->m_freeInternalEntities = openEntity; + + // If there are more open entities we want to stop right here and have the + // upcoming call to XML_ResumeParser continue with entity content, or it would + // be ignored altogether. + if (parser->m_openInternalEntities != NULL + && parser->m_parsingStatus.parsing == XML_SUSPENDED) { + return XML_ERROR_NONE; } #ifdef XML_DTD @@ -5826,10 +5843,15 @@ { parser->m_processor = contentProcessor; /* see externalEntityContentProcessor vs contentProcessor */ - return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, - s, end, nextPtr, - (XML_Bool)! parser->m_parsingStatus.finalBuffer, - XML_ACCOUNT_DIRECT); + result = doContent(parser, parser->m_parentParser ? 1 : 0, + parser->m_encoding, s, end, nextPtr, + (XML_Bool)! parser->m_parsingStatus.finalBuffer, + XML_ACCOUNT_DIRECT); + if (result == XML_ERROR_NONE) { + if (! storeRawNames(parser)) + return XML_ERROR_NO_MEMORY; + } + return result; } } diff -Nru python3.10-3.10.7/Modules/expat/xmltok.c python3.10-3.10.12/Modules/expat/xmltok.c --- python3.10-3.10.7/Modules/expat/xmltok.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/xmltok.c 2023-06-06 22:30:33.000000000 +0000 @@ -21,6 +21,7 @@ Copyright (c) 2017 José Gutiérrez de la Concha Copyright (c) 2019 David Loffredo Copyright (c) 2021 Dong-hee Na + Copyright (c) 2022 Martin Ettl Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -296,7 +297,7 @@ } #else /* c is an ASCII character */ -# define CHAR_MATCHES(enc, p, c) (*(p) == c) +# define CHAR_MATCHES(enc, p, c) (*(p) == (c)) #endif #define PREFIX(ident) normal_##ident @@ -740,7 +741,7 @@ ((p)[1] == 0 ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ : unicode_byte_type((p)[1], (p)[0])) #define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1) -#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == c) +#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c)) #define LITTLE2_IS_NAME_CHAR_MINBPC(p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \ @@ -875,7 +876,7 @@ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ : unicode_byte_type((p)[0], (p)[1])) #define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1) -#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == c) +#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c)) #define BIG2_IS_NAME_CHAR_MINBPC(p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) #define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \ diff -Nru python3.10-3.10.7/Modules/expat/xmltok_impl.c python3.10-3.10.12/Modules/expat/xmltok_impl.c --- python3.10-3.10.7/Modules/expat/xmltok_impl.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/xmltok_impl.c 2023-06-06 22:30:33.000000000 +0000 @@ -16,6 +16,7 @@ Copyright (c) 2018 Anton Maklakov Copyright (c) 2019 David Loffredo Copyright (c) 2020 Boris Kolpackov + Copyright (c) 2022 Martin Ettl Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -96,7 +97,7 @@ # define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD##n: \ - if (end - ptr < n) \ + if ((end) - (ptr) < (n)) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ @@ -124,7 +125,8 @@ # define PREFIX(ident) ident # endif -# define HAS_CHARS(enc, ptr, end, count) (end - ptr >= count * MINBPC(enc)) +# define HAS_CHARS(enc, ptr, end, count) \ + ((end) - (ptr) >= ((count)*MINBPC(enc))) # define HAS_CHAR(enc, ptr, end) HAS_CHARS(enc, ptr, end, 1) diff -Nru python3.10-3.10.7/Modules/expat/xmltok_impl.h python3.10-3.10.12/Modules/expat/xmltok_impl.h --- python3.10-3.10.7/Modules/expat/xmltok_impl.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/expat/xmltok_impl.h 2023-06-06 22:30:33.000000000 +0000 @@ -45,7 +45,7 @@ BT_LF, /* line feed = "\n" */ BT_GT, /* greater than = ">" */ BT_QUOT, /* quotation character = "\"" */ - BT_APOS, /* aposthrophe = "'" */ + BT_APOS, /* apostrophe = "'" */ BT_EQUALS, /* equal sign = "=" */ BT_QUEST, /* question mark = "?" */ BT_EXCL, /* exclamation mark = "!" */ diff -Nru python3.10-3.10.7/Modules/faulthandler.c python3.10-3.10.12/Modules/faulthandler.c --- python3.10-3.10.7/Modules/faulthandler.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/faulthandler.c 2023-06-06 22:30:33.000000000 +0000 @@ -349,14 +349,17 @@ size_t i; fault_handler_t *handler = NULL; int save_errno = errno; + int found = 0; if (!fatal_error.enabled) return; for (i=0; i < faulthandler_nsignals; i++) { handler = &faulthandler_handlers[i]; - if (handler->signum == signum) + if (handler->signum == signum) { + found = 1; break; + } } if (handler == NULL) { /* faulthandler_nsignals == 0 (unlikely) */ @@ -366,9 +369,18 @@ /* restore the previous handler */ faulthandler_disable_fatal_handler(handler); - PUTS(fd, "Fatal Python error: "); - PUTS(fd, handler->name); - PUTS(fd, "\n\n"); + if (found) { + PUTS(fd, "Fatal Python error: "); + PUTS(fd, handler->name); + PUTS(fd, "\n\n"); + } + else { + char unknown_signum[23] = {0,}; + snprintf(unknown_signum, 23, "%d", signum); + PUTS(fd, "Fatal Python error from unexpected signum: "); + PUTS(fd, unknown_signum); + PUTS(fd, "\n\n"); + } faulthandler_dump_traceback(fd, fatal_error.all_threads, fatal_error.interp); @@ -877,7 +889,7 @@ errno = save_errno; } #else - if (user->chain) { + if (user->chain && user->previous != NULL) { errno = save_errno; /* call the previous signal handler */ user->previous(signum); diff -Nru python3.10-3.10.7/Modules/_functoolsmodule.c python3.10-3.10.12/Modules/_functoolsmodule.c --- python3.10-3.10.7/Modules/_functoolsmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_functoolsmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -1470,9 +1470,8 @@ if (state->keyobject_type == NULL) { return -1; } - if (PyModule_AddType(module, state->keyobject_type) < 0) { - return -1; - } + // keyobject_type is used only internally. + // So we don't expose it in module namespace. state->lru_list_elem_type = (PyTypeObject *)PyType_FromModuleAndSpec( module, &lru_list_elem_type_spec, NULL); diff -Nru python3.10-3.10.7/Modules/_io/fileio.c python3.10-3.10.12/Modules/_io/fileio.c --- python3.10-3.10.7/Modules/_io/fileio.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_io/fileio.c 2023-06-06 22:30:33.000000000 +0000 @@ -494,8 +494,12 @@ ret = -1; if (!fd_is_own) self->fd = -1; - if (self->fd >= 0) + if (self->fd >= 0) { + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); internal_close(self); + _PyErr_ChainExceptions(exc, val, tb); + } done: #ifdef MS_WINDOWS diff -Nru python3.10-3.10.7/Modules/_io/_iomodule.c python3.10-3.10.12/Modules/_io/_iomodule.c --- python3.10-3.10.7/Modules/_io/_iomodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_io/_iomodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -718,10 +718,10 @@ goto fail; /* BlockingIOError, for compatibility */ - Py_INCREF(PyExc_BlockingIOError); - if (PyModule_AddObject(m, "BlockingIOError", - (PyObject *) PyExc_BlockingIOError) < 0) + if (PyModule_AddObjectRef(m, "BlockingIOError", + (PyObject *) PyExc_BlockingIOError) < 0) { goto fail; + } /* Concrete base types of the IO ABCs. (the ABCs themselves are declared through inheritance in io.py) diff -Nru python3.10-3.10.7/Modules/_io/textio.c python3.10-3.10.12/Modules/_io/textio.c --- python3.10-3.10.7/Modules/_io/textio.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_io/textio.c 2023-06-06 22:30:33.000000000 +0000 @@ -251,19 +251,16 @@ PyObject *errors) /*[clinic end generated code: output=fbd04d443e764ec2 input=89db6b19c6b126bf]*/ { - self->decoder = decoder; - Py_INCREF(decoder); if (errors == NULL) { - self->errors = _PyUnicode_FromId(&PyId_strict); - if (self->errors == NULL) + errors = _PyUnicode_FromId(&PyId_strict); + if (errors == NULL) { return -1; + } } - else { - self->errors = errors; - } - Py_INCREF(self->errors); + Py_XSETREF(self->errors, Py_NewRef(errors)); + Py_XSETREF(self->decoder, Py_NewRef(decoder)); self->translate = translate ? 1 : 0; self->seennl = 0; self->pendingcr = 0; @@ -298,6 +295,13 @@ return 0; } +#define CHECK_INITIALIZED_DECODER(self) \ + if (self->errors == NULL) { \ + PyErr_SetString(PyExc_ValueError, \ + "IncrementalNewlineDecoder.__init__() not called"); \ + return NULL; \ + } + #define SEEN_CR 1 #define SEEN_LF 2 #define SEEN_CRLF 4 @@ -311,11 +315,7 @@ Py_ssize_t output_len; nldecoder_object *self = (nldecoder_object *) myself; - if (self->decoder == NULL) { - PyErr_SetString(PyExc_ValueError, - "IncrementalNewlineDecoder.__init__ not called"); - return NULL; - } + CHECK_INITIALIZED_DECODER(self); /* decode input (with the eventual \r from a previous pass) */ if (self->decoder != Py_None) { @@ -529,6 +529,8 @@ PyObject *buffer; unsigned long long flag; + CHECK_INITIALIZED_DECODER(self); + if (self->decoder != Py_None) { PyObject *state = PyObject_CallMethodNoArgs(self->decoder, _PyIO_str_getstate); @@ -573,6 +575,8 @@ PyObject *buffer; unsigned long long flag; + CHECK_INITIALIZED_DECODER(self); + if (!PyTuple_Check(state)) { PyErr_SetString(PyExc_TypeError, "state argument must be a tuple"); return NULL; @@ -601,6 +605,8 @@ _io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self) /*[clinic end generated code: output=32fa40c7462aa8ff input=728678ddaea776df]*/ { + CHECK_INITIALIZED_DECODER(self); + self->seennl = 0; self->pendingcr = 0; if (self->decoder != Py_None) @@ -612,6 +618,8 @@ static PyObject * incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context) { + CHECK_INITIALIZED_DECODER(self); + switch (self->seennl) { case SEEN_CR: return PyUnicode_FromString("\r"); diff -Nru python3.10-3.10.7/Modules/_io/winconsoleio.c python3.10-3.10.12/Modules/_io/winconsoleio.c --- python3.10-3.10.7/Modules/_io/winconsoleio.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_io/winconsoleio.c 2023-06-06 22:30:33.000000000 +0000 @@ -956,7 +956,7 @@ { BOOL res = TRUE; wchar_t *wbuf; - DWORD len, wlen, n = 0; + DWORD len, wlen, orig_len, n = 0; HANDLE handle; if (self->fd == -1) @@ -986,6 +986,21 @@ have to reduce and recalculate. */ while (wlen > 32766 / sizeof(wchar_t)) { len /= 2; + orig_len = len; + /* Reduce the length until we hit the final byte of a UTF-8 sequence + * (top bit is unset). Fix for github issue 82052. + */ + while (len > 0 && (((char *)b->buf)[len-1] & 0x80) != 0) + --len; + /* If we hit a length of 0, something has gone wrong. This shouldn't + * be possible, as valid UTF-8 can have at most 3 non-final bytes + * before a final one, and our buffer is way longer than that. + * But to be on the safe side, if we hit this issue we just restore + * the original length and let the console API sort it out. + */ + if (len == 0) { + len = orig_len; + } wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, NULL, 0); } Py_END_ALLOW_THREADS diff -Nru python3.10-3.10.7/Modules/itertoolsmodule.c python3.10-3.10.12/Modules/itertoolsmodule.c --- python3.10-3.10.7/Modules/itertoolsmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/itertoolsmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -1204,6 +1204,7 @@ PyErr_SetString(PyExc_TypeError, "state is not a tuple"); return NULL; } + // The second item can be 1/0 in old pickles and True/False in new pickles if (!PyArg_ParseTuple(state, "O!i", &PyList_Type, &saved, &firstpass)) { return NULL; } diff -Nru python3.10-3.10.7/Modules/mathmodule.c python3.10-3.10.12/Modules/mathmodule.c --- python3.10-3.10.7/Modules/mathmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/mathmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -2658,13 +2658,13 @@ if (m != n) { PyErr_SetString(PyExc_ValueError, "both points must have the same number of dimensions"); - return NULL; - + goto error_exit; } if (n > NUM_STACK_ELEMS) { diffs = (double *) PyObject_Malloc(n * sizeof(double)); if (diffs == NULL) { - return PyErr_NoMemory(); + PyErr_NoMemory(); + goto error_exit; } } for (i=0 ; iUnpicklingError == NULL) return NULL; - Py_INCREF(st->PickleError); - if (PyModule_AddObject(m, "PickleError", st->PickleError) < 0) + if (PyModule_AddObjectRef(m, "PickleError", st->PickleError) < 0) { return NULL; - Py_INCREF(st->PicklingError); - if (PyModule_AddObject(m, "PicklingError", st->PicklingError) < 0) + } + if (PyModule_AddObjectRef(m, "PicklingError", st->PicklingError) < 0) { return NULL; - Py_INCREF(st->UnpicklingError); - if (PyModule_AddObject(m, "UnpicklingError", st->UnpicklingError) < 0) + } + if (PyModule_AddObjectRef(m, "UnpicklingError", st->UnpicklingError) < 0) { return NULL; - + } if (_Pickle_InitState(st) < 0) return NULL; diff -Nru python3.10-3.10.7/Modules/posixmodule.c python3.10-3.10.12/Modules/posixmodule.c --- python3.10-3.10.7/Modules/posixmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/posixmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -21,6 +21,9 @@ FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */ # include # include +# include // UNLEN +# include "osdefs.h" // SEP +# define HAVE_SYMLINK #endif #ifdef __VXWORKS__ @@ -85,6 +88,8 @@ # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) +# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) +# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) @@ -169,6 +174,8 @@ # define HAVE_FUTIMENS_RUNTIME 1 # define HAVE_UTIMENSAT_RUNTIME 1 # define HAVE_PWRITEV_RUNTIME 1 +# define HAVE_MKFIFOAT_RUNTIME 1 +# define HAVE_MKNODAT_RUNTIME 1 #endif @@ -426,18 +433,7 @@ # ifdef HAVE_PROCESS_H # include # endif -# ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -# endif -# ifndef IO_REPARSE_TAG_MOUNT_POINT -# define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) -# endif -# include "osdefs.h" // SEP # include -# include -# include // ShellExecute() -# include // UNLEN -# define HAVE_SYMLINK #endif /* _MSC_VER */ #ifndef MAXPATHLEN @@ -4490,12 +4486,13 @@ dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. -The mode argument is ignored on Windows. +The mode argument is ignored on Windows. Where it is used, the current umask +value is first masked out. [clinic start generated code]*/ static PyObject * os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/ +/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ { int result; #ifdef HAVE_MKDIRAT @@ -7024,8 +7021,13 @@ os_sched_yield_impl(PyObject *module) /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ { - if (sched_yield()) + int result; + Py_BEGIN_ALLOW_THREADS + result = sched_yield(); + Py_END_ALLOW_THREADS + if (result < 0) { return posix_error(); + } Py_RETURN_NONE; } @@ -9280,11 +9282,6 @@ static int dup3_works = -1; #endif - if (fd < 0 || fd2 < 0) { - posix_error(); - return -1; - } - /* dup2() can fail with EINTR if the target FD is already open, because it * then has to be closed. See os_close_impl() for why we don't handle EINTR * upon close(), and therefore below. @@ -10554,18 +10551,35 @@ { int result; int async_err = 0; +#ifdef HAVE_MKFIFOAT + int mkfifoat_unavailable = 0; +#endif do { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) - result = mkfifoat(dir_fd, path->narrow, mode); - else + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKFIFOAT_RUNTIME) { + result = mkfifoat(dir_fd, path->narrow, mode); + + } else { + mkfifoat_unavailable = 1; + result = 0; + } + } else #endif result = mkfifo(path->narrow, mode); Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + +#ifdef HAVE_MKFIFOAT + if (mkfifoat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif + if (result != 0) return (!async_err) ? posix_error() : NULL; @@ -10606,18 +10620,33 @@ { int result; int async_err = 0; +#ifdef HAVE_MKNODAT + int mknodat_unavailable = 0; +#endif do { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) - result = mknodat(dir_fd, path->narrow, mode, device); - else + if (dir_fd != DEFAULT_DIR_FD) { + if (HAVE_MKNODAT_RUNTIME) { + result = mknodat(dir_fd, path->narrow, mode, device); + + } else { + mknodat_unavailable = 1; + result = 0; + } + } else #endif result = mknod(path->narrow, mode, device); Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); +#ifdef HAVE_MKNODAT + if (mknodat_unavailable) { + argument_unavailable_error(NULL, "dir_fd"); + return NULL; + } +#endif if (result != 0) return (!async_err) ? posix_error() : NULL; @@ -15466,6 +15495,14 @@ PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME) #endif +#ifdef HAVE_MKFIFOAT +PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME) +#endif + +#ifdef HAVE_MKNODAT +PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME) +#endif + #ifdef HAVE_RENAMEAT PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME) #endif @@ -15599,11 +15636,11 @@ #endif #ifdef HAVE_MKFIFOAT - { "HAVE_MKFIFOAT", NULL }, + { "HAVE_MKFIFOAT", probe_mkfifoat }, #endif #ifdef HAVE_MKNODAT - { "HAVE_MKNODAT", NULL }, + { "HAVE_MKNODAT", probe_mknodat }, #endif #ifdef HAVE_OPENAT diff -Nru python3.10-3.10.7/Modules/pyexpat.c python3.10-3.10.12/Modules/pyexpat.c --- python3.10-3.10.7/Modules/pyexpat.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/pyexpat.c 2023-06-06 22:30:33.000000000 +0000 @@ -1843,13 +1843,6 @@ } #endif -static void -pyexpat_destructor(PyObject *op) -{ - void *p = PyCapsule_GetPointer(op, PyExpat_CAPSULE_NAME); - PyMem_Free(p); -} - static int pyexpat_exec(PyObject *mod) { @@ -1933,46 +1926,40 @@ MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); #undef MYCONST - struct PyExpat_CAPI *capi = PyMem_Calloc(1, sizeof(struct PyExpat_CAPI)); - if (capi == NULL) { - PyErr_NoMemory(); - return -1; - } + static struct PyExpat_CAPI capi; /* initialize pyexpat dispatch table */ - capi->size = sizeof(*capi); - capi->magic = PyExpat_CAPI_MAGIC; - capi->MAJOR_VERSION = XML_MAJOR_VERSION; - capi->MINOR_VERSION = XML_MINOR_VERSION; - capi->MICRO_VERSION = XML_MICRO_VERSION; - capi->ErrorString = XML_ErrorString; - capi->GetErrorCode = XML_GetErrorCode; - capi->GetErrorColumnNumber = XML_GetErrorColumnNumber; - capi->GetErrorLineNumber = XML_GetErrorLineNumber; - capi->Parse = XML_Parse; - capi->ParserCreate_MM = XML_ParserCreate_MM; - capi->ParserFree = XML_ParserFree; - capi->SetCharacterDataHandler = XML_SetCharacterDataHandler; - capi->SetCommentHandler = XML_SetCommentHandler; - capi->SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; - capi->SetElementHandler = XML_SetElementHandler; - capi->SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; - capi->SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; - capi->SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; - capi->SetUserData = XML_SetUserData; - capi->SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; - capi->SetEncoding = XML_SetEncoding; - capi->DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; + capi.size = sizeof(capi); + capi.magic = PyExpat_CAPI_MAGIC; + capi.MAJOR_VERSION = XML_MAJOR_VERSION; + capi.MINOR_VERSION = XML_MINOR_VERSION; + capi.MICRO_VERSION = XML_MICRO_VERSION; + capi.ErrorString = XML_ErrorString; + capi.GetErrorCode = XML_GetErrorCode; + capi.GetErrorColumnNumber = XML_GetErrorColumnNumber; + capi.GetErrorLineNumber = XML_GetErrorLineNumber; + capi.Parse = XML_Parse; + capi.ParserCreate_MM = XML_ParserCreate_MM; + capi.ParserFree = XML_ParserFree; + capi.SetCharacterDataHandler = XML_SetCharacterDataHandler; + capi.SetCommentHandler = XML_SetCommentHandler; + capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; + capi.SetElementHandler = XML_SetElementHandler; + capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; + capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; + capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; + capi.SetUserData = XML_SetUserData; + capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; + capi.SetEncoding = XML_SetEncoding; + capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; #if XML_COMBINED_VERSION >= 20100 - capi->SetHashSalt = XML_SetHashSalt; + capi.SetHashSalt = XML_SetHashSalt; #else - capi->SetHashSalt = NULL; + capi.SetHashSalt = NULL; #endif /* export using capsule */ - PyObject *capi_object = PyCapsule_New(capi, PyExpat_CAPSULE_NAME, - pyexpat_destructor); + PyObject *capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); if (capi_object == NULL) { - PyMem_Free(capi); return -1; } diff -Nru python3.10-3.10.7/Modules/readline.c python3.10-3.10.12/Modules/readline.c --- python3.10-3.10.7/Modules/readline.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/readline.c 2023-06-06 22:30:33.000000000 +0000 @@ -1256,9 +1256,9 @@ rl_attempted_completion_function = flex_complete; /* Set Python word break characters */ completer_word_break_characters = - rl_completer_word_break_characters = strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?"); /* All nonalphanums except '.' */ + rl_completer_word_break_characters = completer_word_break_characters; mod_state->begidx = PyLong_FromLong(0L); mod_state->endidx = PyLong_FromLong(0L); diff -Nru python3.10-3.10.7/Modules/_sha3/kcp/KeccakSponge.inc python3.10-3.10.12/Modules/_sha3/kcp/KeccakSponge.inc --- python3.10-3.10.7/Modules/_sha3/kcp/KeccakSponge.inc 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_sha3/kcp/KeccakSponge.inc 2023-06-06 22:30:33.000000000 +0000 @@ -171,7 +171,7 @@ i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) { #ifdef SnP_FastLoop_Absorb /* processing full blocks first */ @@ -199,10 +199,10 @@ } else { /* normal lane: using the message queue */ - - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); #ifdef KeccakReference displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); #endif @@ -281,7 +281,7 @@ i = 0; curData = data; while(i < dataByteLen) { - if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { + if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) { for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { SnP_Permute(instance->state); SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); @@ -299,9 +299,10 @@ SnP_Permute(instance->state); instance->byteIOIndex = 0; } - partialBlock = (unsigned int)(dataByteLen - i); - if (partialBlock+instance->byteIOIndex > rateInBytes) + if (dataByteLen-i > rateInBytes-instance->byteIOIndex) partialBlock = rateInBytes-instance->byteIOIndex; + else + partialBlock = (unsigned int)(dataByteLen - i); i += partialBlock; SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); diff -Nru python3.10-3.10.7/Modules/_sha3/sha3module.c python3.10-3.10.12/Modules/_sha3/sha3module.c --- python3.10-3.10.7/Modules/_sha3/sha3module.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_sha3/sha3module.c 2023-06-06 22:30:33.000000000 +0000 @@ -65,7 +65,7 @@ #endif /* Prevent bus errors on platforms requiring aligned accesses such ARM. */ -#if HAVE_ALIGNED_REQUIRED && !defined(NO_MISALIGNED_ACCESSES) +#if defined(HAVE_ALIGNED_REQUIRED) && !defined(NO_MISALIGNED_ACCESSES) #define NO_MISALIGNED_ACCESSES #endif diff -Nru python3.10-3.10.7/Modules/signalmodule.c python3.10-3.10.12/Modules/signalmodule.c --- python3.10-3.10.7/Modules/signalmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/signalmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -177,6 +177,10 @@ static inline int compare_handler(PyObject *func, PyObject *dfl_ign_handler) { + // See https://github.com/python/cpython/pull/102399 + if (func == NULL || dfl_ign_handler == NULL) { + return 0; + } assert(PyLong_CheckExact(dfl_ign_handler)); if (!PyLong_CheckExact(func)) { return 0; diff -Nru python3.10-3.10.7/Modules/socketmodule.c python3.10-3.10.12/Modules/socketmodule.c --- python3.10-3.10.7/Modules/socketmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/socketmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -1053,6 +1053,7 @@ subsequent call to getaddrinfo() does not destroy the outcome of the first call. */ if (error) { + res = NULL; // no-op, remind us that it is invalid; gh-100795 set_gaierror(error); return -1; } @@ -1163,6 +1164,7 @@ #endif Py_END_ALLOW_THREADS if (error) { + res = NULL; // no-op, remind us that it is invalid; gh-100795 set_gaierror(error); return -1; } @@ -6514,6 +6516,7 @@ error = getaddrinfo(hptr, pptr, &hints, &res0); Py_END_ALLOW_THREADS if (error) { + res0 = NULL; // gh-100795 set_gaierror(error); goto err; } @@ -6608,6 +6611,7 @@ error = getaddrinfo(hostp, pbuf, &hints, &res); Py_END_ALLOW_THREADS if (error) { + res = NULL; // gh-100795 set_gaierror(error); goto fail; } diff -Nru python3.10-3.10.7/Modules/_sre.c python3.10-3.10.12/Modules/_sre.c --- python3.10-3.10.7/Modules/_sre.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_sre.c 2023-06-06 22:30:33.000000000 +0000 @@ -1519,7 +1519,7 @@ #endif /* Report failure */ -#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return 0; } while (0) +#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return -1; } while (0) /* Extract opcode, argument, or skip count from code array */ #define GET_OP \ @@ -1543,7 +1543,7 @@ skip = *code; \ VTRACE(("%lu (skip to %p)\n", \ (unsigned long)skip, code+skip)); \ - if (skip-adj > (uintptr_t)(end - code)) \ + if (skip-adj > (uintptr_t)(end - code)) \ FAIL; \ code++; \ } while (0) @@ -1632,9 +1632,10 @@ } } - return 1; + return 0; } +/* Returns 0 on success, -1 on failure, and 1 if the last op is JUMP. */ static int _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) { @@ -1712,7 +1713,7 @@ case SRE_OP_IN_LOC_IGNORE: GET_SKIP; /* Stop 1 before the end; we check the FAILURE below */ - if (!_validate_charset(code, code+skip-2)) + if (_validate_charset(code, code+skip-2)) FAIL; if (code[skip-2] != SRE_OP_FAILURE) FAIL; @@ -1766,7 +1767,7 @@ } /* Validate the charset */ if (flags & SRE_INFO_CHARSET) { - if (!_validate_charset(code, newcode-1)) + if (_validate_charset(code, newcode-1)) FAIL; if (newcode[-1] != SRE_OP_FAILURE) FAIL; @@ -1787,7 +1788,7 @@ if (skip == 0) break; /* Stop 2 before the end; we check the JUMP below */ - if (!_validate_inner(code, code+skip-3, groups)) + if (_validate_inner(code, code+skip-3, groups)) FAIL; code += skip-3; /* Check that it ends with a JUMP, and that each JUMP @@ -1801,6 +1802,8 @@ else if (code+skip-1 != target) FAIL; } + if (code != target) + FAIL; } break; @@ -1815,7 +1818,7 @@ FAIL; if (max > SRE_MAXREPEAT) FAIL; - if (!_validate_inner(code, code+skip-4, groups)) + if (_validate_inner(code, code+skip-4, groups)) FAIL; code += skip-4; GET_OP; @@ -1834,7 +1837,7 @@ FAIL; if (max > SRE_MAXREPEAT) FAIL; - if (!_validate_inner(code, code+skip-3, groups)) + if (_validate_inner(code, code+skip-3, groups)) FAIL; code += skip-3; GET_OP; @@ -1886,24 +1889,17 @@ to allow arbitrary jumps anywhere in the code; so we just look for a JUMP opcode preceding our skip target. */ - if (skip >= 3 && skip-3 < (uintptr_t)(end - code) && - code[skip-3] == SRE_OP_JUMP) - { - VTRACE(("both then and else parts present\n")); - if (!_validate_inner(code+1, code+skip-3, groups)) - FAIL; + VTRACE(("then part:\n")); + int rc = _validate_inner(code+1, code+skip-1, groups); + if (rc == 1) { + VTRACE(("else part:\n")); code += skip-2; /* Position after JUMP, at */ GET_SKIP; - if (!_validate_inner(code, code+skip-1, groups)) - FAIL; - code += skip-1; - } - else { - VTRACE(("only a then part present\n")); - if (!_validate_inner(code+1, code+skip-1, groups)) - FAIL; - code += skip-1; + rc = _validate_inner(code, code+skip-1, groups); } + if (rc) + FAIL; + code += skip-1; break; case SRE_OP_ASSERT: @@ -1914,7 +1910,7 @@ if (arg & 0x80000000) FAIL; /* Width too large */ /* Stop 1 before the end; we check the SUCCESS below */ - if (!_validate_inner(code+1, code+skip-2, groups)) + if (_validate_inner(code+1, code+skip-2, groups)) FAIL; code += skip-2; GET_OP; @@ -1922,6 +1918,12 @@ FAIL; break; + case SRE_OP_JUMP: + if (code + 1 != end) + FAIL; + VTRACE(("JUMP: %d\n", __LINE__)); + return 1; + default: FAIL; @@ -1929,7 +1931,7 @@ } VTRACE(("okay\n")); - return 1; + return 0; } static int @@ -1944,7 +1946,7 @@ static int _validate(PatternObject *self) { - if (!_validate_outer(self->code, self->code+self->codesize, self->groups)) + if (_validate_outer(self->code, self->code+self->codesize, self->groups)) { PyErr_SetString(PyExc_RuntimeError, "invalid SRE code"); return 0; diff -Nru python3.10-3.10.7/Modules/_ssl.c python3.10-3.10.12/Modules/_ssl.c --- python3.10-3.10.7/Modules/_ssl.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ssl.c 2023-06-06 22:30:33.000000000 +0000 @@ -671,6 +671,16 @@ ERR_GET_REASON(e) == SSL_R_CERTIFICATE_VERIFY_FAILED) { type = state->PySSLCertVerificationErrorObject; } +#if defined(SSL_R_UNEXPECTED_EOF_WHILE_READING) + /* OpenSSL 3.0 changed transport EOF from SSL_ERROR_SYSCALL with + * zero return value to SSL_ERROR_SSL with a special error code. */ + if (ERR_GET_LIB(e) == ERR_LIB_SSL && + ERR_GET_REASON(e) == SSL_R_UNEXPECTED_EOF_WHILE_READING) { + p = PY_SSL_ERROR_EOF; + type = state->PySSLEOFErrorObject; + errstr = "EOF occurred in violation of protocol"; + } +#endif break; } default: @@ -2005,24 +2015,44 @@ _ssl__SSLSocket_shared_ciphers_impl(PySSLSocket *self) /*[clinic end generated code: output=3d174ead2e42c4fd input=0bfe149da8fe6306]*/ { - STACK_OF(SSL_CIPHER) *ciphers; - int i; + STACK_OF(SSL_CIPHER) *server_ciphers; + STACK_OF(SSL_CIPHER) *client_ciphers; + int i, len; PyObject *res; + const SSL_CIPHER* cipher; + + /* Rather than use SSL_get_shared_ciphers, we use an equivalent algorithm because: + + 1) It returns a colon seperated list of strings, in an undefined + order, that we would have to post process back into tuples. + 2) It will return a truncated string with no indication that it has + done so, if the buffer is too small. + */ - ciphers = SSL_get_ciphers(self->ssl); - if (!ciphers) + server_ciphers = SSL_get_ciphers(self->ssl); + if (!server_ciphers) Py_RETURN_NONE; - res = PyList_New(sk_SSL_CIPHER_num(ciphers)); + client_ciphers = SSL_get_client_ciphers(self->ssl); + if (!client_ciphers) + Py_RETURN_NONE; + + res = PyList_New(sk_SSL_CIPHER_num(server_ciphers)); if (!res) return NULL; - for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { - PyObject *tup = cipher_to_tuple(sk_SSL_CIPHER_value(ciphers, i)); + len = 0; + for (i = 0; i < sk_SSL_CIPHER_num(server_ciphers); i++) { + cipher = sk_SSL_CIPHER_value(server_ciphers, i); + if (sk_SSL_CIPHER_find(client_ciphers, cipher) < 0) + continue; + + PyObject *tup = cipher_to_tuple(cipher); if (!tup) { Py_DECREF(res); return NULL; } - PyList_SET_ITEM(res, i, tup); + PyList_SET_ITEM(res, len++, tup); } + Py_SET_SIZE(res, len); return res; } @@ -3114,10 +3144,6 @@ #ifdef SSL_OP_SINGLE_ECDH_USE options |= SSL_OP_SINGLE_ECDH_USE; #endif -#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF - /* Make OpenSSL 3.0.0 behave like 1.1.1 */ - options |= SSL_OP_IGNORE_UNEXPECTED_EOF; -#endif SSL_CTX_set_options(self->ctx, options); /* A bare minimum cipher list without completely broken cipher suites. diff -Nru python3.10-3.10.7/Modules/_ssl_data_111.h python3.10-3.10.12/Modules/_ssl_data_111.h --- python3.10-3.10.7/Modules/_ssl_data_111.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ssl_data_111.h 2023-06-06 22:30:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* File generated by Tools/ssl/make_ssl_data.py *//* Generated on 2021-04-09T09:36:21.493286 */ +/* File generated by Tools/ssl/make_ssl_data.py *//* Generated on 2023-06-01T02:58:04.081473 */ static struct py_ssl_library_code library_codes[] = { #ifdef ERR_LIB_ASN1 {"ASN1", ERR_LIB_ASN1}, @@ -1375,6 +1375,11 @@ #else {"UNSUPPORTED_COMPRESSION_ALGORITHM", 46, 151}, #endif + #ifdef CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM}, + #else + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", 46, 194}, + #endif #ifdef CMS_R_UNSUPPORTED_CONTENT_TYPE {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE}, #else @@ -4860,6 +4865,11 @@ #else {"MISSING_PARAMETERS", 20, 290}, #endif + #ifdef SSL_R_MISSING_PSK_KEX_MODES_EXTENSION + {"MISSING_PSK_KEX_MODES_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_PSK_KEX_MODES_EXTENSION}, + #else + {"MISSING_PSK_KEX_MODES_EXTENSION", 20, 310}, + #endif #ifdef SSL_R_MISSING_RSA_CERTIFICATE {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, #else @@ -5065,6 +5075,11 @@ #else {"NULL_SSL_METHOD_PASSED", 20, 196}, #endif + #ifdef SSL_R_OCSP_CALLBACK_FAILURE + {"OCSP_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_OCSP_CALLBACK_FAILURE}, + #else + {"OCSP_CALLBACK_FAILURE", 20, 294}, + #endif #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, #else diff -Nru python3.10-3.10.7/Modules/_ssl_data_300.h python3.10-3.10.12/Modules/_ssl_data_300.h --- python3.10-3.10.7/Modules/_ssl_data_300.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_ssl_data_300.h 2023-06-06 22:30:33.000000000 +0000 @@ -1,4 +1,4 @@ -/* File generated by Tools/ssl/make_ssl_data.py *//* Generated on 2021-04-09T09:44:43.288448 */ +/* File generated by Tools/ssl/make_ssl_data.py *//* Generated on 2023-06-01T03:03:52.163218 */ static struct py_ssl_library_code library_codes[] = { #ifdef ERR_LIB_ASN1 {"ASN1", ERR_LIB_ASN1}, @@ -1035,6 +1035,11 @@ #else {"NO_INVERSE", 3, 108}, #endif + #ifdef BN_R_NO_PRIME_CANDIDATE + {"NO_PRIME_CANDIDATE", ERR_LIB_BN, BN_R_NO_PRIME_CANDIDATE}, + #else + {"NO_PRIME_CANDIDATE", 3, 121}, + #endif #ifdef BN_R_NO_SOLUTION {"NO_SOLUTION", ERR_LIB_BN, BN_R_NO_SOLUTION}, #else @@ -1255,6 +1260,11 @@ #else {"INVALID_OPTION", 58, 174}, #endif + #ifdef CMP_R_MISSING_CERTID + {"MISSING_CERTID", ERR_LIB_CMP, CMP_R_MISSING_CERTID}, + #else + {"MISSING_CERTID", 58, 165}, + #endif #ifdef CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION {"MISSING_KEY_INPUT_FOR_CREATING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION}, #else @@ -1280,21 +1290,41 @@ #else {"MISSING_PRIVATE_KEY", 58, 131}, #endif + #ifdef CMP_R_MISSING_PRIVATE_KEY_FOR_POPO + {"MISSING_PRIVATE_KEY_FOR_POPO", ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY_FOR_POPO}, + #else + {"MISSING_PRIVATE_KEY_FOR_POPO", 58, 190}, + #endif #ifdef CMP_R_MISSING_PROTECTION {"MISSING_PROTECTION", ERR_LIB_CMP, CMP_R_MISSING_PROTECTION}, #else {"MISSING_PROTECTION", 58, 143}, #endif + #ifdef CMP_R_MISSING_PUBLIC_KEY + {"MISSING_PUBLIC_KEY", ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY}, + #else + {"MISSING_PUBLIC_KEY", 58, 183}, + #endif #ifdef CMP_R_MISSING_REFERENCE_CERT {"MISSING_REFERENCE_CERT", ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT}, #else {"MISSING_REFERENCE_CERT", 58, 168}, #endif + #ifdef CMP_R_MISSING_SECRET + {"MISSING_SECRET", ERR_LIB_CMP, CMP_R_MISSING_SECRET}, + #else + {"MISSING_SECRET", 58, 178}, + #endif #ifdef CMP_R_MISSING_SENDER_IDENTIFICATION {"MISSING_SENDER_IDENTIFICATION", ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION}, #else {"MISSING_SENDER_IDENTIFICATION", 58, 111}, #endif + #ifdef CMP_R_MISSING_TRUST_ANCHOR + {"MISSING_TRUST_ANCHOR", ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR}, + #else + {"MISSING_TRUST_ANCHOR", 58, 179}, + #endif #ifdef CMP_R_MISSING_TRUST_STORE {"MISSING_TRUST_STORE", ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE}, #else @@ -1455,6 +1485,11 @@ #else {"WRONG_ALGORITHM_OID", 58, 138}, #endif + #ifdef CMP_R_WRONG_CERTID + {"WRONG_CERTID", ERR_LIB_CMP, CMP_R_WRONG_CERTID}, + #else + {"WRONG_CERTID", 58, 189}, + #endif #ifdef CMP_R_WRONG_CERTID_IN_RP {"WRONG_CERTID_IN_RP", ERR_LIB_CMP, CMP_R_WRONG_CERTID_IN_RP}, #else @@ -1885,6 +1920,11 @@ #else {"UNSUPPORTED_COMPRESSION_ALGORITHM", 46, 151}, #endif + #ifdef CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM}, + #else + {"UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM", 46, 194}, + #endif #ifdef CMS_R_UNSUPPORTED_CONTENT_TYPE {"UNSUPPORTED_CONTENT_TYPE", ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE}, #else @@ -2045,6 +2085,11 @@ #else {"RECURSIVE_DIRECTORY_INCLUDE", 14, 111}, #endif + #ifdef CONF_R_RELATIVE_PATH + {"RELATIVE_PATH", ERR_LIB_CONF, CONF_R_RELATIVE_PATH}, + #else + {"RELATIVE_PATH", 14, 125}, + #endif #ifdef CONF_R_SSL_COMMAND_SECTION_EMPTY {"SSL_COMMAND_SECTION_EMPTY", ERR_LIB_CONF, CONF_R_SSL_COMMAND_SECTION_EMPTY}, #else @@ -2235,6 +2280,11 @@ #else {"INSUFFICIENT_SECURE_DATA_SPACE", 15, 108}, #endif + #ifdef CRYPTO_R_INVALID_NEGATIVE_VALUE + {"INVALID_NEGATIVE_VALUE", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NEGATIVE_VALUE}, + #else + {"INVALID_NEGATIVE_VALUE", 15, 122}, + #endif #ifdef CRYPTO_R_INVALID_NULL_ARGUMENT {"INVALID_NULL_ARGUMENT", ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NULL_ARGUMENT}, #else @@ -2605,6 +2655,11 @@ #else {"SEED_LEN_SMALL", 10, 110}, #endif + #ifdef DSA_R_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_DSA, DSA_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 10, 116}, + #endif #ifdef DSO_R_CTRL_FAILED {"CTRL_FAILED", ERR_LIB_DSO, DSO_R_CTRL_FAILED}, #else @@ -2745,6 +2800,11 @@ #else {"EC_GROUP_NEW_BY_NAME_FAILURE", 16, 119}, #endif + #ifdef EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED + {"EXPLICIT_PARAMS_NOT_SUPPORTED", ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED}, + #else + {"EXPLICIT_PARAMS_NOT_SUPPORTED", 16, 127}, + #endif #ifdef EC_R_FAILED_MAKING_PUBLIC_KEY {"FAILED_MAKING_PUBLIC_KEY", ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY}, #else @@ -2850,6 +2910,11 @@ #else {"INVALID_KEY", 16, 116}, #endif + #ifdef EC_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_EC, EC_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 16, 117}, + #endif #ifdef EC_R_INVALID_NAMED_GROUP_CONVERSION {"INVALID_NAMED_GROUP_CONVERSION", ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION}, #else @@ -3010,6 +3075,11 @@ #else {"SLOT_FULL", 16, 108}, #endif + #ifdef EC_R_TOO_MANY_RETRIES + {"TOO_MANY_RETRIES", ERR_LIB_EC, EC_R_TOO_MANY_RETRIES}, + #else + {"TOO_MANY_RETRIES", 16, 176}, + #endif #ifdef EC_R_UNDEFINED_GENERATOR {"UNDEFINED_GENERATOR", ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR}, #else @@ -3690,6 +3760,11 @@ #else {"PUBLIC_KEY_NOT_RSA", 6, 106}, #endif + #ifdef EVP_R_SETTING_XOF_FAILED + {"SETTING_XOF_FAILED", ERR_LIB_EVP, EVP_R_SETTING_XOF_FAILED}, + #else + {"SETTING_XOF_FAILED", 6, 227}, + #endif #ifdef EVP_R_SET_DEFAULT_PROPERTY_FAILURE {"SET_DEFAULT_PROPERTY_FAILURE", ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE}, #else @@ -3865,6 +3940,11 @@ #else {"FAILED_READING_DATA", 61, 128}, #endif + #ifdef HTTP_R_HEADER_PARSE_ERROR + {"HEADER_PARSE_ERROR", ERR_LIB_HTTP, HTTP_R_HEADER_PARSE_ERROR}, + #else + {"HEADER_PARSE_ERROR", 61, 126}, + #endif #ifdef HTTP_R_INCONSISTENT_CONTENT_LENGTH {"INCONSISTENT_CONTENT_LENGTH", ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH}, #else @@ -3935,6 +4015,16 @@ #else {"RESPONSE_PARSE_ERROR", 61, 104}, #endif + #ifdef HTTP_R_RETRY_TIMEOUT + {"RETRY_TIMEOUT", ERR_LIB_HTTP, HTTP_R_RETRY_TIMEOUT}, + #else + {"RETRY_TIMEOUT", 61, 129}, + #endif + #ifdef HTTP_R_SERVER_CANCELED_CONNECTION + {"SERVER_CANCELED_CONNECTION", ERR_LIB_HTTP, HTTP_R_SERVER_CANCELED_CONNECTION}, + #else + {"SERVER_CANCELED_CONNECTION", 61, 127}, + #endif #ifdef HTTP_R_SOCK_NOT_SUPPORTED {"SOCK_NOT_SUPPORTED", ERR_LIB_HTTP, HTTP_R_SOCK_NOT_SUPPORTED}, #else @@ -4100,6 +4190,16 @@ #else {"UNSUPPORTED_REQUESTORNAME_TYPE", 39, 129}, #endif + #ifdef OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT + {"COULD_NOT_DECODE_OBJECT", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_COULD_NOT_DECODE_OBJECT}, + #else + {"COULD_NOT_DECODE_OBJECT", 60, 101}, + #endif + #ifdef OSSL_DECODER_R_DECODER_NOT_FOUND + {"DECODER_NOT_FOUND", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_DECODER_NOT_FOUND}, + #else + {"DECODER_NOT_FOUND", 60, 102}, + #endif #ifdef OSSL_DECODER_R_MISSING_GET_PARAMS {"MISSING_GET_PARAMS", ERR_LIB_OSSL_DECODER, OSSL_DECODER_R_MISSING_GET_PARAMS}, #else @@ -4190,6 +4290,11 @@ #else {"NOT_PARAMETERS", 44, 104}, #endif + #ifdef OSSL_STORE_R_NO_LOADERS_FOUND + {"NO_LOADERS_FOUND", ERR_LIB_OSSL_STORE, OSSL_STORE_R_NO_LOADERS_FOUND}, + #else + {"NO_LOADERS_FOUND", 44, 123}, + #endif #ifdef OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR {"PASSPHRASE_CALLBACK_ERROR", ERR_LIB_OSSL_STORE, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR}, #else @@ -4935,6 +5040,11 @@ #else {"INVALID_DIGEST_SIZE", 57, 218}, #endif + #ifdef PROV_R_INVALID_INPUT_LENGTH + {"INVALID_INPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH}, + #else + {"INVALID_INPUT_LENGTH", 57, 230}, + #endif #ifdef PROV_R_INVALID_ITERATION_COUNT {"INVALID_ITERATION_COUNT", ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT}, #else @@ -4970,6 +5080,11 @@ #else {"INVALID_MODE", 57, 125}, #endif + #ifdef PROV_R_INVALID_OUTPUT_LENGTH + {"INVALID_OUTPUT_LENGTH", ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH}, + #else + {"INVALID_OUTPUT_LENGTH", 57, 217}, + #endif #ifdef PROV_R_INVALID_PADDING_MODE {"INVALID_PADDING_MODE", ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE}, #else @@ -5035,6 +5150,16 @@ #else {"KEY_SIZE_TOO_SMALL", 57, 171}, #endif + #ifdef PROV_R_LENGTH_TOO_LARGE + {"LENGTH_TOO_LARGE", ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE}, + #else + {"LENGTH_TOO_LARGE", 57, 202}, + #endif + #ifdef PROV_R_MISMATCHING_DOMAIN_PARAMETERS + {"MISMATCHING_DOMAIN_PARAMETERS", ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS}, + #else + {"MISMATCHING_DOMAIN_PARAMETERS", 57, 203}, + #endif #ifdef PROV_R_MISSING_CEK_ALG {"MISSING_CEK_ALG", ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG}, #else @@ -5695,6 +5820,11 @@ #else {"INVALID_LABEL", 4, 160}, #endif + #ifdef RSA_R_INVALID_LENGTH + {"INVALID_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_LENGTH}, + #else + {"INVALID_LENGTH", 4, 181}, + #endif #ifdef RSA_R_INVALID_MESSAGE_LENGTH {"INVALID_MESSAGE_LENGTH", ERR_LIB_RSA, RSA_R_INVALID_MESSAGE_LENGTH}, #else @@ -5880,6 +6010,11 @@ #else {"Q_NOT_PRIME", 4, 129}, #endif + #ifdef RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", ERR_LIB_RSA, RSA_R_RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT}, + #else + {"RANDOMNESS_SOURCE_STRENGTH_INSUFFICIENT", 4, 180}, + #endif #ifdef RSA_R_RSA_OPERATIONS_NOT_SUPPORTED {"RSA_OPERATIONS_NOT_SUPPORTED", ERR_LIB_RSA, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED}, #else @@ -6680,6 +6815,11 @@ #else {"INVALID_TICKET_KEYS_LENGTH", 20, 325}, #endif + #ifdef SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", ERR_LIB_SSL, SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED}, + #else + {"LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED", 20, 333}, + #endif #ifdef SSL_R_LENGTH_MISMATCH {"LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_LENGTH_MISMATCH}, #else @@ -6725,6 +6865,11 @@ #else {"MISSING_PARAMETERS", 20, 290}, #endif + #ifdef SSL_R_MISSING_PSK_KEX_MODES_EXTENSION + {"MISSING_PSK_KEX_MODES_EXTENSION", ERR_LIB_SSL, SSL_R_MISSING_PSK_KEX_MODES_EXTENSION}, + #else + {"MISSING_PSK_KEX_MODES_EXTENSION", 20, 310}, + #endif #ifdef SSL_R_MISSING_RSA_CERTIFICATE {"MISSING_RSA_CERTIFICATE", ERR_LIB_SSL, SSL_R_MISSING_RSA_CERTIFICATE}, #else @@ -6940,6 +7085,11 @@ #else {"NULL_SSL_METHOD_PASSED", 20, 196}, #endif + #ifdef SSL_R_OCSP_CALLBACK_FAILURE + {"OCSP_CALLBACK_FAILURE", ERR_LIB_SSL, SSL_R_OCSP_CALLBACK_FAILURE}, + #else + {"OCSP_CALLBACK_FAILURE", 20, 305}, + #endif #ifdef SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED {"OLD_SESSION_CIPHER_NOT_RETURNED", ERR_LIB_SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED}, #else diff -Nru python3.10-3.10.7/Modules/syslogmodule.c python3.10-3.10.12/Modules/syslogmodule.c --- python3.10-3.10.7/Modules/syslogmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/syslogmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -207,9 +207,14 @@ */ PyObject *ident = S_ident_o; Py_XINCREF(ident); +#ifdef __APPLE__ + // gh-98178: On macOS, libc syslog() is not thread-safe + syslog(priority, "%s", message); +#else Py_BEGIN_ALLOW_THREADS; syslog(priority, "%s", message); Py_END_ALLOW_THREADS; +#endif Py_XDECREF(ident); Py_RETURN_NONE; } @@ -235,7 +240,7 @@ if (!PyArg_ParseTuple(args, "l;mask for priority", &maskpri)) return NULL; - if (PySys_Audit("syslog.setlogmask", "(O)", args ? args : Py_None) < 0) { + if (PySys_Audit("syslog.setlogmask", "l", maskpri) < 0) { return NULL; } omaskpri = setlogmask(maskpri); diff -Nru python3.10-3.10.7/Modules/termios.c python3.10-3.10.12/Modules/termios.c --- python3.10-3.10.7/Modules/termios.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/termios.c 2023-06-06 22:30:33.000000000 +0000 @@ -82,7 +82,12 @@ { termiosmodulestate *state = PyModule_GetState(module); struct termios mode; - if (tcgetattr(fd, &mode) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcgetattr(fd, &mode); + Py_END_ALLOW_THREADS + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -169,7 +174,12 @@ /* Get the old mode, in case there are any hidden fields... */ termiosmodulestate *state = PyModule_GetState(module); struct termios mode; - if (tcgetattr(fd, &mode) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcgetattr(fd, &mode); + Py_END_ALLOW_THREADS + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -211,7 +221,12 @@ return PyErr_SetFromErrno(state->TermiosError); if (cfsetospeed(&mode, (speed_t) ospeed) == -1) return PyErr_SetFromErrno(state->TermiosError); - if (tcsetattr(fd, when, &mode) == -1) + + Py_BEGIN_ALLOW_THREADS + r = tcsetattr(fd, when, &mode); + Py_END_ALLOW_THREADS + + if (r == -1) return PyErr_SetFromErrno(state->TermiosError); Py_RETURN_NONE; @@ -235,7 +250,13 @@ /*[clinic end generated code: output=5945f589b5d3ac66 input=dc2f32417691f8ed]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcsendbreak(fd, duration) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcsendbreak(fd, duration); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -256,7 +277,13 @@ /*[clinic end generated code: output=5fd86944c6255955 input=c99241b140b32447]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcdrain(fd) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcdrain(fd); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -282,7 +309,13 @@ /*[clinic end generated code: output=2424f80312ec2f21 input=0f7d08122ddc07b5]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcflush(fd, queue) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcflush(fd, queue); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } @@ -308,7 +341,13 @@ /*[clinic end generated code: output=afd10928e6ea66eb input=c6aff0640b6efd9c]*/ { termiosmodulestate *state = PyModule_GetState(module); - if (tcflow(fd, action) == -1) { + int r; + + Py_BEGIN_ALLOW_THREADS + r = tcflow(fd, action); + Py_END_ALLOW_THREADS + + if (r == -1) { return PyErr_SetFromErrno(state->TermiosError); } diff -Nru python3.10-3.10.7/Modules/_testcapimodule.c python3.10-3.10.12/Modules/_testcapimodule.c --- python3.10-3.10.7/Modules/_testcapimodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_testcapimodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -4368,12 +4368,19 @@ PyThread_exit_thread(); } +static test_c_thread_t test_c_thread; + static PyObject * -call_in_temporary_c_thread(PyObject *self, PyObject *callback) +call_in_temporary_c_thread(PyObject *self, PyObject *args) { PyObject *res = NULL; - test_c_thread_t test_c_thread; + PyObject *callback = NULL; long thread; + int wait = 1; + if (!PyArg_ParseTuple(args, "O|i", &callback, &wait)) + { + return NULL; + } test_c_thread.start_event = PyThread_allocate_lock(); test_c_thread.exit_event = PyThread_allocate_lock(); @@ -4400,6 +4407,10 @@ PyThread_acquire_lock(test_c_thread.start_event, 1); PyThread_release_lock(test_c_thread.start_event); + if (!wait) { + Py_RETURN_NONE; + } + Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(test_c_thread.exit_event, 1); PyThread_release_lock(test_c_thread.exit_event); @@ -4410,13 +4421,32 @@ exit: Py_CLEAR(test_c_thread.callback); - if (test_c_thread.start_event) + if (test_c_thread.start_event) { PyThread_free_lock(test_c_thread.start_event); - if (test_c_thread.exit_event) + test_c_thread.start_event = NULL; + } + if (test_c_thread.exit_event) { PyThread_free_lock(test_c_thread.exit_event); + test_c_thread.exit_event = NULL; + } return res; } +static PyObject * +join_temporary_c_thread(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(test_c_thread.exit_event, 1); + PyThread_release_lock(test_c_thread.exit_event); + Py_END_ALLOW_THREADS + Py_CLEAR(test_c_thread.callback); + PyThread_free_lock(test_c_thread.start_event); + test_c_thread.start_event = NULL; + PyThread_free_lock(test_c_thread.exit_event); + test_c_thread.exit_event = NULL; + Py_RETURN_NONE; +} + /* marshal */ static PyObject* @@ -5155,6 +5185,40 @@ return PyMapping_Items(obj); } +static PyObject * +test_mapping_has_key_string(PyObject *self, PyObject *Py_UNUSED(args)) +{ + PyObject *context = PyDict_New(); + PyObject *val = PyLong_FromLong(1); + + // Since this uses `const char*` it is easier to test this in C: + PyDict_SetItemString(context, "a", val); + if (!PyMapping_HasKeyString(context, "a")) { + PyErr_SetString(PyExc_RuntimeError, + "Existing mapping key does not exist"); + return NULL; + } + if (PyMapping_HasKeyString(context, "b")) { + PyErr_SetString(PyExc_RuntimeError, + "Missing mapping key exists"); + return NULL; + } + + Py_DECREF(val); + Py_DECREF(context); + Py_RETURN_NONE; +} + +static PyObject * +mapping_has_key(PyObject* self, PyObject *args) +{ + PyObject *context, *key; + if (!PyArg_ParseTuple(args, "OO", &context, &key)) { + return NULL; + } + return PyLong_FromLong(PyMapping_HasKey(context, key)); +} + static PyObject * test_pythread_tss_key_state(PyObject *self, PyObject *args) @@ -5475,8 +5539,10 @@ if (pyargs == NULL) { return NULL; } + assert(args != NULL || nargs == 0); + PyObject* const* args_offset = args == NULL ? NULL : args + nargs; PyObject *pykwargs = PyObject_Vectorcall((PyObject*)&PyDict_Type, - args + nargs, 0, kwargs); + args_offset, 0, kwargs); return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs); } @@ -5635,6 +5701,7 @@ static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*); +static PyObject *gh_99240_clear_args(PyObject *, PyObject *); static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -5748,6 +5815,7 @@ METH_VARARGS|METH_KEYWORDS}, {"getargs_s_hash_int2", (PyCFunction)(void(*)(void))getargs_s_hash_int2, METH_VARARGS|METH_KEYWORDS}, + {"gh_99240_clear_args", gh_99240_clear_args, METH_VARARGS}, {"getargs_z", getargs_z, METH_VARARGS}, {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"getargs_z_hash", getargs_z_hash, METH_VARARGS}, @@ -5840,8 +5908,9 @@ {"docstring_with_signature_with_defaults", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_signature_with_defaults}, - {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O, + {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS, PyDoc_STR("set_error_class(error_class) -> None")}, + {"join_temporary_c_thread", join_temporary_c_thread, METH_NOARGS}, {"pymarshal_write_long_to_file", pymarshal_write_long_to_file, METH_VARARGS}, {"pymarshal_write_object_to_file", @@ -5892,6 +5961,8 @@ {"get_mapping_keys", get_mapping_keys, METH_O}, {"get_mapping_values", get_mapping_values, METH_O}, {"get_mapping_items", get_mapping_items, METH_O}, + {"test_mapping_has_key_string", test_mapping_has_key_string, METH_NOARGS}, + {"mapping_has_key", mapping_has_key, METH_VARARGS}, {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS}, {"hamt", new_hamt, METH_NOARGS}, {"bad_get", (PyCFunction)(void(*)(void))bad_get, METH_FASTCALL}, @@ -7462,3 +7533,21 @@ PyBuffer_Release(&buf); Py_RETURN_NONE; } + +static PyObject * +gh_99240_clear_args(PyObject *self, PyObject *args) +{ + char *a = NULL; + char *b = NULL; + + if (!PyArg_ParseTuple(args, "eses", "idna", &a, "idna", &b)) { + if (a || b) { + PyErr_Clear(); + PyErr_SetString(PyExc_AssertionError, "Arguments are not cleared."); + } + return NULL; + } + PyMem_Free(a); + PyMem_Free(b); + Py_RETURN_NONE; +} diff -Nru python3.10-3.10.7/Modules/_testclinic.c python3.10-3.10.12/Modules/_testclinic.c --- python3.10-3.10.7/Modules/_testclinic.c 1970-01-01 00:00:00.000000000 +0000 +++ python3.10-3.10.12/Modules/_testclinic.c 2023-06-06 22:30:33.000000000 +0000 @@ -0,0 +1,1031 @@ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + +/* Always enable assertions */ +#undef NDEBUG + +#define PY_SSIZE_T_CLEAN + +#include "Python.h" + +#include "clinic/_testclinic.c.h" + + +/* Pack arguments to a tuple, implicitly increase all the arguments' refcount. + * NULL arguments will be replaced to Py_None. */ +static PyObject * +pack_arguments_newref(int argc, ...) +{ + assert(!PyErr_Occurred()); + PyObject *tuple = PyTuple_New(argc); + if (!tuple) { + return NULL; + } + + va_list vargs; + va_start(vargs, argc); + for (int i = 0; i < argc; i++) { + PyObject *arg = va_arg(vargs, PyObject *); + if (arg) { + if (_PyObject_IsFreed(arg)) { + PyErr_Format(PyExc_AssertionError, + "argument %d at %p is freed or corrupted!", + i, arg); + va_end(vargs); + Py_DECREF(tuple); + return NULL; + } + } + else { + arg = Py_None; + } + PyTuple_SET_ITEM(tuple, i, Py_NewRef(arg)); + } + va_end(vargs); + return tuple; +} + +/* Pack arguments to a tuple. + * `wrapper` is function which converts primitive type to PyObject. + * `arg_type` is type that arguments should be converted to before wrapped. */ +#define RETURN_PACKED_ARGS(argc, wrapper, arg_type, ...) do { \ + assert(!PyErr_Occurred()); \ + arg_type in[argc] = {__VA_ARGS__}; \ + PyObject *out[argc] = {NULL,}; \ + for (int _i = 0; _i < argc; _i++) { \ + out[_i] = wrapper(in[_i]); \ + assert(out[_i] || PyErr_Occurred()); \ + if (!out[_i]) { \ + for (int _j = 0; _j < _i; _j++) { \ + Py_DECREF(out[_j]); \ + } \ + return NULL; \ + } \ + } \ + PyObject *tuple = PyTuple_New(argc); \ + if (!tuple) { \ + for (int _i = 0; _i < argc; _i++) { \ + Py_DECREF(out[_i]); \ + } \ + return NULL; \ + } \ + for (int _i = 0; _i < argc; _i++) { \ + PyTuple_SET_ITEM(tuple, _i, out[_i]); \ + } \ + return tuple; \ + } while (0) + + +/*[clinic input] +module _testclinic +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d4981b80d6efdb12]*/ + + +/*[clinic input] +test_empty_function + +[clinic start generated code]*/ + +static PyObject * +test_empty_function_impl(PyObject *module) +/*[clinic end generated code: output=0f8aeb3ddced55cb input=0dd7048651ad4ae4]*/ +{ + Py_RETURN_NONE; +} + + +/*[clinic input] +objects_converter + + a: object + b: object = NULL + / + +[clinic start generated code]*/ + +static PyObject * +objects_converter_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=3f9c9415ec86c695 input=1533b1bd94187de4]*/ +{ + return pack_arguments_newref(2, a, b); +} + + +/*[clinic input] +bytes_object_converter + + a: PyBytesObject + / + +[clinic start generated code]*/ + +static PyObject * +bytes_object_converter_impl(PyObject *module, PyBytesObject *a) +/*[clinic end generated code: output=7732da869d74b784 input=94211751e7996236]*/ +{ + if (!PyBytes_Check(a)) { + PyErr_SetString(PyExc_AssertionError, + "argument a is not a PyBytesObject"); + return NULL; + } + return pack_arguments_newref(1, a); +} + + +/*[clinic input] +byte_array_object_converter + + a: PyByteArrayObject + / + +[clinic start generated code]*/ + +static PyObject * +byte_array_object_converter_impl(PyObject *module, PyByteArrayObject *a) +/*[clinic end generated code: output=51f15c76f302b1f7 input=b04d253db51c6f56]*/ +{ + if (!PyByteArray_Check(a)) { + PyErr_SetString(PyExc_AssertionError, + "argument a is not a PyByteArrayObject"); + return NULL; + } + return pack_arguments_newref(1, a); +} + + +/*[clinic input] +unicode_converter + + a: unicode + / + +[clinic start generated code]*/ + +static PyObject * +unicode_converter_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=1b4a4adbb6ac6e34 input=de7b5adbf07435ba]*/ +{ + if (!PyUnicode_Check(a)) { + PyErr_SetString(PyExc_AssertionError, + "argument a is not a unicode object"); + return NULL; + } + return pack_arguments_newref(1, a); +} + + +/*[clinic input] +bool_converter + + a: bool = True + b: bool(accept={object}) = True + c: bool(accept={int}) = True + / + +[clinic start generated code]*/ + +static PyObject * +bool_converter_impl(PyObject *module, int a, int b, int c) +/*[clinic end generated code: output=17005b0c29afd590 input=7f6537705b2f32f4]*/ +{ + PyObject *obj_a = a ? Py_True : Py_False; + PyObject *obj_b = b ? Py_True : Py_False; + PyObject *obj_c = c ? Py_True : Py_False; + return pack_arguments_newref(3, obj_a, obj_b, obj_c); +} + + +/*[clinic input] +char_converter + + a: char = b'A' + b: char = b'\a' + c: char = b'\b' + d: char = b'\t' + e: char = b'\n' + f: char = b'\v' + g: char = b'\f' + h: char = b'\r' + i: char = b'"' + j: char = b"'" + k: char = b'?' + l: char = b'\\' + m: char = b'\000' + n: char = b'\377' + / + +[clinic start generated code]*/ + +static PyObject * +char_converter_impl(PyObject *module, char a, char b, char c, char d, char e, + char f, char g, char h, char i, char j, char k, char l, + char m, char n) +/*[clinic end generated code: output=f929dbd2e55a9871 input=b601bc5bc7fe85e3]*/ +{ + RETURN_PACKED_ARGS(14, PyLong_FromUnsignedLong, unsigned char, + a, b, c, d, e, f, g, h, i, j, k, l, m, n); +} + + +/*[clinic input] +unsigned_char_converter + + a: unsigned_char = 12 + b: unsigned_char(bitwise=False) = 34 + c: unsigned_char(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_char_converter_impl(PyObject *module, unsigned char a, + unsigned char b, unsigned char c) +/*[clinic end generated code: output=490af3b39ce0b199 input=e859502fbe0b3185]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned char, a, b, c); +} + + +/*[clinic input] +short_converter + + a: short = 12 + / + +[clinic start generated code]*/ + +static PyObject * +short_converter_impl(PyObject *module, short a) +/*[clinic end generated code: output=1ebb7ddb64248988 input=b4e2309a66f650ae]*/ +{ + RETURN_PACKED_ARGS(1, PyLong_FromLong, long, a); +} + + +/*[clinic input] +unsigned_short_converter + + a: unsigned_short = 12 + b: unsigned_short(bitwise=False) = 34 + c: unsigned_short(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_short_converter_impl(PyObject *module, unsigned short a, + unsigned short b, unsigned short c) +/*[clinic end generated code: output=5f92cc72fc8707a7 input=9d15cd11e741d0c6]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); +} + + +/*[clinic input] +int_converter + + a: int = 12 + b: int(accept={int}) = 34 + c: int(accept={str}) = 45 + / + +[clinic start generated code]*/ + +static PyObject * +int_converter_impl(PyObject *module, int a, int b, int c) +/*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromLong, long, a, b, c); +} + + +/*[clinic input] +unsigned_int_converter + + a: unsigned_int = 12 + b: unsigned_int(bitwise=False) = 34 + c: unsigned_int(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_int_converter_impl(PyObject *module, unsigned int a, unsigned int b, + unsigned int c) +/*[clinic end generated code: output=399a57a05c494cc7 input=8427ed9a3f96272d]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); +} + + +/*[clinic input] +long_converter + + a: long = 12 + / + +[clinic start generated code]*/ + +static PyObject * +long_converter_impl(PyObject *module, long a) +/*[clinic end generated code: output=9663d936a652707a input=84ad0ef28f24bd85]*/ +{ + RETURN_PACKED_ARGS(1, PyLong_FromLong, long, a); +} + + +/*[clinic input] +unsigned_long_converter + + a: unsigned_long = 12 + b: unsigned_long(bitwise=False) = 34 + c: unsigned_long(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_long_converter_impl(PyObject *module, unsigned long a, + unsigned long b, unsigned long c) +/*[clinic end generated code: output=120b82ea9ebd93a8 input=440dd6f1817f5d91]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLong, unsigned long, a, b, c); +} + + +/*[clinic input] +long_long_converter + + a: long_long = 12 + / + +[clinic start generated code]*/ + +static PyObject * +long_long_converter_impl(PyObject *module, long long a) +/*[clinic end generated code: output=5fb5f2220770c3e1 input=730fcb3eecf4d993]*/ +{ + RETURN_PACKED_ARGS(1, PyLong_FromLongLong, long long, a); +} + + +/*[clinic input] +unsigned_long_long_converter + + a: unsigned_long_long = 12 + b: unsigned_long_long(bitwise=False) = 34 + c: unsigned_long_long(bitwise=True) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +unsigned_long_long_converter_impl(PyObject *module, unsigned long long a, + unsigned long long b, unsigned long long c) +/*[clinic end generated code: output=65b7273e63501762 input=300737b0bdb230e9]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromUnsignedLongLong, unsigned long long, + a, b, c); +} + + +/*[clinic input] +py_ssize_t_converter + + a: Py_ssize_t = 12 + b: Py_ssize_t(accept={int}) = 34 + c: Py_ssize_t(accept={int, NoneType}) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +py_ssize_t_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c) +/*[clinic end generated code: output=ce252143e0ed0372 input=76d0f342e9317a1f]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromSsize_t, Py_ssize_t, a, b, c); +} + + +/*[clinic input] +slice_index_converter + + a: slice_index = 12 + b: slice_index(accept={int}) = 34 + c: slice_index(accept={int, NoneType}) = 56 + / + +[clinic start generated code]*/ + +static PyObject * +slice_index_converter_impl(PyObject *module, Py_ssize_t a, Py_ssize_t b, + Py_ssize_t c) +/*[clinic end generated code: output=923c6cac77666a6b input=64f99f3f83265e47]*/ +{ + RETURN_PACKED_ARGS(3, PyLong_FromSsize_t, Py_ssize_t, a, b, c); +} + + +/*[clinic input] +size_t_converter + + a: size_t = 12 + / + +[clinic start generated code]*/ + +static PyObject * +size_t_converter_impl(PyObject *module, size_t a) +/*[clinic end generated code: output=412b5b7334ab444d input=83ae7d9171fbf208]*/ +{ + RETURN_PACKED_ARGS(1, PyLong_FromSize_t, size_t, a); +} + + +/*[clinic input] +float_converter + + a: float = 12.5 + / + +[clinic start generated code]*/ + +static PyObject * +float_converter_impl(PyObject *module, float a) +/*[clinic end generated code: output=1c98f64f2cf1d55c input=a625b59ad68047d8]*/ +{ + RETURN_PACKED_ARGS(1, PyFloat_FromDouble, double, a); +} + + +/*[clinic input] +double_converter + + a: double = 12.5 + / + +[clinic start generated code]*/ + +static PyObject * +double_converter_impl(PyObject *module, double a) +/*[clinic end generated code: output=a4e8532d284d035d input=098df188f24e7c62]*/ +{ + RETURN_PACKED_ARGS(1, PyFloat_FromDouble, double, a); +} + + +/*[clinic input] +py_complex_converter + + a: Py_complex + / + +[clinic start generated code]*/ + +static PyObject * +py_complex_converter_impl(PyObject *module, Py_complex a) +/*[clinic end generated code: output=9e6ca2eb53b14846 input=e9148a8ca1dbf195]*/ +{ + RETURN_PACKED_ARGS(1, PyComplex_FromCComplex, Py_complex, a); +} + + +/*[clinic input] +str_converter + + a: str = "a" + b: str(accept={robuffer}) = "b" + c: str(accept={robuffer, str}, zeroes=True) = "c" + / + +[clinic start generated code]*/ + +static PyObject * +str_converter_impl(PyObject *module, const char *a, const char *b, + const char *c, Py_ssize_clean_t c_length) +/*[clinic end generated code: output=203880b5c6d9fbb4 input=bff2656c92ee25de]*/ +{ + assert(!PyErr_Occurred()); + PyObject *out[3] = {NULL,}; + int i = 0; + PyObject *arg; + + arg = PyUnicode_FromString(a); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromString(b); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromStringAndSize(c, c_length); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + PyObject *tuple = PyTuple_New(3); + if (!tuple) { + goto error; + } + for (int j = 0; j < 3; j++) { + PyTuple_SET_ITEM(tuple, j, out[j]); + } + return tuple; + +error: + for (int j = 0; j < i; j++) { + Py_DECREF(out[j]); + } + return NULL; +} + + +/*[clinic input] +str_converter_encoding + + a: str(encoding="idna") + b: str(encoding="idna", accept={bytes, bytearray, str}) + c: str(encoding="idna", accept={bytes, bytearray, str}, zeroes=True) + / + +[clinic start generated code]*/ + +static PyObject * +str_converter_encoding_impl(PyObject *module, char *a, char *b, char *c, + Py_ssize_clean_t c_length) +/*[clinic end generated code: output=ebef1a3f9b730a24 input=0c5cf5159d0e870d]*/ +{ + assert(!PyErr_Occurred()); + PyObject *out[3] = {NULL,}; + int i = 0; + PyObject *arg; + + arg = PyUnicode_FromString(a); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromString(b); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + arg = PyUnicode_FromStringAndSize(c, c_length); + assert(arg || PyErr_Occurred()); + if (!arg) { + goto error; + } + out[i++] = arg; + + PyObject *tuple = PyTuple_New(3); + if (!tuple) { + goto error; + } + for (int j = 0; j < 3; j++) { + PyTuple_SET_ITEM(tuple, j, out[j]); + } + return tuple; + +error: + for (int j = 0; j < i; j++) { + Py_DECREF(out[j]); + } + return NULL; +} + + +static PyObject * +bytes_from_buffer(Py_buffer *buf) +{ + PyObject *bytes_obj = PyBytes_FromStringAndSize(NULL, buf->len); + if (!bytes_obj) { + return NULL; + } + void *bytes_obj_buf = ((PyBytesObject *)bytes_obj)->ob_sval; + if (PyBuffer_ToContiguous(bytes_obj_buf, buf, buf->len, 'C') < 0) { + Py_DECREF(bytes_obj); + return NULL; + } + return bytes_obj; +} + +/*[clinic input] +py_buffer_converter + + a: Py_buffer(accept={str, buffer, NoneType}) + b: Py_buffer(accept={rwbuffer}) + / + +[clinic start generated code]*/ + +static PyObject * +py_buffer_converter_impl(PyObject *module, Py_buffer *a, Py_buffer *b) +/*[clinic end generated code: output=52fb13311e3d6d03 input=775de727de5c7421]*/ +{ + RETURN_PACKED_ARGS(2, bytes_from_buffer, Py_buffer *, a, b); +} + + +/*[clinic input] +keywords + + a: object + b: object + +[clinic start generated code]*/ + +static PyObject * +keywords_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=850aaed53e26729e input=f44b89e718c1a93b]*/ +{ + return pack_arguments_newref(2, a, b); +} + + +/*[clinic input] +keywords_kwonly + + a: object + * + b: object + +[clinic start generated code]*/ + +static PyObject * +keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=a45c48241da584dc input=1f08e39c3312b015]*/ +{ + return pack_arguments_newref(2, a, b); +} + + +/*[clinic input] +keywords_opt + + a: object + b: object = None + c: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, PyObject *c) +/*[clinic end generated code: output=25e4b67d91c76a66 input=b0ba0e4f04904556]*/ +{ + return pack_arguments_newref(3, a, b, c); +} + + +/*[clinic input] +keywords_opt_kwonly + + a: object + b: object = None + * + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_opt_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=6aa5b655a6e9aeb0 input=f79da689d6c51076]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +keywords_kwonly_opt + + a: object + * + b: object = None + c: object = None + +[clinic start generated code]*/ + +static PyObject * +keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=707f78eb0f55c2b1 input=e0fa1a0e46dca791]*/ +{ + return pack_arguments_newref(3, a, b, c); +} + + +/*[clinic input] +posonly_keywords + + a: object + / + b: object + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=6ac88f4a5f0bfc8d input=fde0a2f79fe82b06]*/ +{ + return pack_arguments_newref(2, a, b); +} + + +/*[clinic input] +posonly_kwonly + + a: object + / + * + b: object + +[clinic start generated code]*/ + +static PyObject * +posonly_kwonly_impl(PyObject *module, PyObject *a, PyObject *b) +/*[clinic end generated code: output=483e6790d3482185 input=78b3712768da9a19]*/ +{ + return pack_arguments_newref(2, a, b); +} + + +/*[clinic input] +posonly_keywords_kwonly + + a: object + / + b: object + * + c: object + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_kwonly_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c) +/*[clinic end generated code: output=2fae573e8cc3fad8 input=a1ad5d2295eb803c]*/ +{ + return pack_arguments_newref(3, a, b, c); +} + + +/*[clinic input] +posonly_keywords_opt + + a: object + / + b: object + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=f5eb66241bcf68fb input=51c10de2a120e279]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +posonly_opt_keywords_opt + + a: object + b: object = None + / + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_keywords_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=d54a30e549296ffd input=f408a1de7dfaf31f]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +posonly_kwonly_opt + + a: object + / + * + b: object + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=a20503fe36b4fd62 input=3494253975272f52]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +posonly_opt_kwonly_opt + + a: object + b: object = None + / + * + c: object = None + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d) +/*[clinic end generated code: output=64f3204a3a0413b6 input=d17516581e478412]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +posonly_keywords_kwonly_opt + + a: object + / + b: object + * + c: object + d: object = None + e: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_kwonly_opt_impl(PyObject *module, PyObject *a, PyObject *b, + PyObject *c, PyObject *d, PyObject *e) +/*[clinic end generated code: output=dbd7e7ddd6257fa0 input=33529f29e97e5adb]*/ +{ + return pack_arguments_newref(5, a, b, c, d, e); +} + + +/*[clinic input] +posonly_keywords_opt_kwonly_opt + + a: object + / + b: object + c: object = None + * + d: object = None + e: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, PyObject *d, + PyObject *e) +/*[clinic end generated code: output=775d12ae44653045 input=4d4cc62f11441301]*/ +{ + return pack_arguments_newref(5, a, b, c, d, e); +} + + +/*[clinic input] +posonly_opt_keywords_opt_kwonly_opt + + a: object + b: object = None + / + c: object = None + * + d: object = None + +[clinic start generated code]*/ + +static PyObject * +posonly_opt_keywords_opt_kwonly_opt_impl(PyObject *module, PyObject *a, + PyObject *b, PyObject *c, + PyObject *d) +/*[clinic end generated code: output=40c6dc422591eade input=3964960a68622431]*/ +{ + return pack_arguments_newref(4, a, b, c, d); +} + + +/*[clinic input] +keyword_only_parameter + + * + a: object + +[clinic start generated code]*/ + +static PyObject * +keyword_only_parameter_impl(PyObject *module, PyObject *a) +/*[clinic end generated code: output=c454b6ce98232787 input=8d2868b8d0b27bdb]*/ +{ + return pack_arguments_newref(1, a); +} + + +/*[clinic input] +gh_99240_double_free + + a: str(encoding="idna") + b: str(encoding="idna") + / + +Proof-of-concept of GH-99240 double-free bug. + +[clinic start generated code]*/ + +static PyObject * +gh_99240_double_free_impl(PyObject *module, char *a, char *b) +/*[clinic end generated code: output=586dc714992fe2ed input=23db44aa91870fc7]*/ +{ + Py_RETURN_NONE; +} + + +static PyMethodDef tester_methods[] = { + TEST_EMPTY_FUNCTION_METHODDEF + OBJECTS_CONVERTER_METHODDEF + BYTES_OBJECT_CONVERTER_METHODDEF + BYTE_ARRAY_OBJECT_CONVERTER_METHODDEF + UNICODE_CONVERTER_METHODDEF + BOOL_CONVERTER_METHODDEF + CHAR_CONVERTER_METHODDEF + UNSIGNED_CHAR_CONVERTER_METHODDEF + SHORT_CONVERTER_METHODDEF + UNSIGNED_SHORT_CONVERTER_METHODDEF + INT_CONVERTER_METHODDEF + UNSIGNED_INT_CONVERTER_METHODDEF + LONG_CONVERTER_METHODDEF + UNSIGNED_LONG_CONVERTER_METHODDEF + LONG_LONG_CONVERTER_METHODDEF + UNSIGNED_LONG_LONG_CONVERTER_METHODDEF + PY_SSIZE_T_CONVERTER_METHODDEF + SLICE_INDEX_CONVERTER_METHODDEF + SIZE_T_CONVERTER_METHODDEF + FLOAT_CONVERTER_METHODDEF + DOUBLE_CONVERTER_METHODDEF + PY_COMPLEX_CONVERTER_METHODDEF + STR_CONVERTER_METHODDEF + STR_CONVERTER_ENCODING_METHODDEF + PY_BUFFER_CONVERTER_METHODDEF + KEYWORDS_METHODDEF + KEYWORDS_KWONLY_METHODDEF + KEYWORDS_OPT_METHODDEF + KEYWORDS_OPT_KWONLY_METHODDEF + KEYWORDS_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_METHODDEF + POSONLY_KWONLY_METHODDEF + POSONLY_KEYWORDS_KWONLY_METHODDEF + POSONLY_KEYWORDS_OPT_METHODDEF + POSONLY_OPT_KEYWORDS_OPT_METHODDEF + POSONLY_KWONLY_OPT_METHODDEF + POSONLY_OPT_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_KWONLY_OPT_METHODDEF + POSONLY_KEYWORDS_OPT_KWONLY_OPT_METHODDEF + POSONLY_OPT_KEYWORDS_OPT_KWONLY_OPT_METHODDEF + KEYWORD_ONLY_PARAMETER_METHODDEF + GH_99240_DOUBLE_FREE_METHODDEF + {NULL, NULL} +}; + +static struct PyModuleDef _testclinic_module = { + PyModuleDef_HEAD_INIT, + .m_name = "_testclinic", + .m_size = 0, + .m_methods = tester_methods, +}; + +PyMODINIT_FUNC +PyInit__testclinic(void) +{ + return PyModule_Create(&_testclinic_module); +} + +#undef RETURN_PACKED_ARGS diff -Nru python3.10-3.10.7/Modules/_threadmodule.c python3.10-3.10.12/Modules/_threadmodule.c --- python3.10-3.10.7/Modules/_threadmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_threadmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -842,6 +842,11 @@ return 0; } +#define HEAD_LOCK(runtime) \ + PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK) +#define HEAD_UNLOCK(runtime) \ + PyThread_release_lock((runtime)->interpreters.mutex) + static int local_clear(localobject *self) { @@ -852,18 +857,23 @@ /* Remove all strong references to dummies from the thread states */ if (self->key) { PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyRuntimeState *runtime = &_PyRuntime; + HEAD_LOCK(runtime); PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - for(; tstate; tstate = PyThreadState_Next(tstate)) { - if (tstate->dict == NULL) { - continue; - } - PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None); - if (v != NULL) { - Py_DECREF(v); - } - else { - PyErr_Clear(); + HEAD_UNLOCK(runtime); + while (tstate) { + if (tstate->dict) { + PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None); + if (v != NULL) { + Py_DECREF(v); + } + else { + PyErr_Clear(); + } } + HEAD_LOCK(runtime); + tstate = PyThreadState_Next(tstate); + HEAD_UNLOCK(runtime); } } return 0; diff -Nru python3.10-3.10.7/Modules/unicodedata.c python3.10-3.10.12/Modules/unicodedata.c --- python3.10-3.10.7/Modules/unicodedata.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/unicodedata.c 2023-06-06 22:30:33.000000000 +0000 @@ -805,7 +805,7 @@ { /* UCD 3.2.0 is requested, quickchecks must be disabled. */ if (UCD_Check(self)) { - return NO; + return MAYBE; } Py_ssize_t i, len; diff -Nru python3.10-3.10.7/Modules/_winapi.c python3.10-3.10.12/Modules/_winapi.c --- python3.10-3.10.7/Modules/_winapi.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_winapi.c 2023-06-06 22:30:33.000000000 +0000 @@ -1403,6 +1403,30 @@ } /*[clinic input] +_winapi.UnmapViewOfFile + + address: LPCVOID + / +[clinic start generated code]*/ + +static PyObject * +_winapi_UnmapViewOfFile_impl(PyObject *module, LPCVOID address) +/*[clinic end generated code: output=4f7e18ac75d19744 input=8c4b6119ad9288a3]*/ +{ + BOOL success; + + Py_BEGIN_ALLOW_THREADS + success = UnmapViewOfFile(address); + Py_END_ALLOW_THREADS + + if (!success) { + return PyErr_SetFromWindowsErr(0); + } + + Py_RETURN_NONE; +} + +/*[clinic input] _winapi.OpenFileMapping -> HANDLE desired_access: DWORD @@ -2095,6 +2119,7 @@ _WINAPI_READFILE_METHODDEF _WINAPI_SETNAMEDPIPEHANDLESTATE_METHODDEF _WINAPI_TERMINATEPROCESS_METHODDEF + _WINAPI_UNMAPVIEWOFFILE_METHODDEF _WINAPI_VIRTUALQUERYSIZE_METHODDEF _WINAPI_WAITNAMEDPIPE_METHODDEF _WINAPI_WAITFORMULTIPLEOBJECTS_METHODDEF diff -Nru python3.10-3.10.7/Modules/_zoneinfo.c python3.10-3.10.12/Modules/_zoneinfo.c --- python3.10-3.10.7/Modules/_zoneinfo.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Modules/_zoneinfo.c 2023-06-06 22:30:33.000000000 +0000 @@ -2648,8 +2648,9 @@ goto error; } - Py_INCREF(&PyZoneInfo_ZoneInfoType); - PyModule_AddObject(m, "ZoneInfo", (PyObject *)&PyZoneInfo_ZoneInfoType); + if (PyModule_AddObjectRef(m, "ZoneInfo", (PyObject *)&PyZoneInfo_ZoneInfoType) < 0) { + goto error; + } /* Populate imports */ PyObject *_tzpath_module = PyImport_ImportModule("zoneinfo._tzpath"); diff -Nru python3.10-3.10.7/Objects/bytearrayobject.c python3.10-3.10.12/Objects/bytearrayobject.c --- python3.10-3.10.7/Objects/bytearrayobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/bytearrayobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -2442,11 +2442,16 @@ bytearrayiter_reduce(bytesiterobject *it, PyObject *Py_UNUSED(ignored)) { _Py_IDENTIFIER(iter); + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); } else { - return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); + return Py_BuildValue("N(())", iter); } } diff -Nru python3.10-3.10.7/Objects/bytesobject.c python3.10-3.10.12/Objects/bytesobject.c --- python3.10-3.10.7/Objects/bytesobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/bytesobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -470,8 +470,10 @@ len = strlen(p); if (writer != NULL) { str = _PyBytesWriter_Prepare(writer, str, len); - if (str == NULL) + if (str == NULL) { + PyMem_Free(p); return NULL; + } memcpy(str, p, len); PyMem_Free(p); str += len; @@ -3144,11 +3146,16 @@ striter_reduce(striterobject *it, PyObject *Py_UNUSED(ignored)) { _Py_IDENTIFIER(iter); + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); } else { - return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); + return Py_BuildValue("N(())", iter); } } diff -Nru python3.10-3.10.7/Objects/descrobject.c python3.10-3.10.12/Objects/descrobject.c --- python3.10-3.10.7/Objects/descrobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/descrobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -755,7 +755,7 @@ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - descr_methods, /* tp_methods */ + 0, /* tp_methods */ descr_members, /* tp_members */ method_getset, /* tp_getset */ 0, /* tp_base */ @@ -1675,9 +1675,10 @@ Py_DECREF(type); if (new == NULL) return NULL; - - Py_XINCREF(pold->prop_name); - Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name); + if (PyObject_TypeCheck((new), &PyProperty_Type)) { + Py_XINCREF(pold->prop_name); + Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name); + } return new; } diff -Nru python3.10-3.10.7/Objects/exceptions.c python3.10-3.10.12/Objects/exceptions.c --- python3.10-3.10.7/Objects/exceptions.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/exceptions.c 2023-06-06 22:30:33.000000000 +0000 @@ -156,8 +156,14 @@ return NULL; } while (PyDict_Next(state, &i, &d_key, &d_value)) { - if (PyObject_SetAttr(self, d_key, d_value) < 0) + Py_INCREF(d_key); + Py_INCREF(d_value); + int res = PyObject_SetAttr(self, d_key, d_value); + Py_DECREF(d_value); + Py_DECREF(d_key); + if (res < 0) { return NULL; + } } } Py_RETURN_NONE; diff -Nru python3.10-3.10.7/Objects/funcobject.c python3.10-3.10.12/Objects/funcobject.c --- python3.10-3.10.7/Objects/funcobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/funcobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -247,7 +247,6 @@ } Py_SETREF(op->func_annotations, ann_dict); } - Py_INCREF(op->func_annotations); assert(PyDict_Check(op->func_annotations)); return op->func_annotations; } @@ -474,7 +473,11 @@ if (op->func_annotations == NULL) return NULL; } - return func_get_annotation_dict(op); + PyObject *d = func_get_annotation_dict(op); + if (d) { + Py_INCREF(d); + } + return d; } static int diff -Nru python3.10-3.10.7/Objects/genericaliasobject.c python3.10-3.10.12/Objects/genericaliasobject.c --- python3.10-3.10.7/Objects/genericaliasobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/genericaliasobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -209,6 +209,9 @@ Py_ssize_t iparam = 0; for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) { PyObject *t = PyTuple_GET_ITEM(args, iarg); + if (PyType_Check(t)) { + continue; + } int typevar = is_typevar(t); if (typevar < 0) { Py_DECREF(parameters); @@ -260,6 +263,11 @@ static PyObject * subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems) { + if (PyType_Check(obj)) { + Py_INCREF(obj); + return obj; + } + _Py_IDENTIFIER(__parameters__); PyObject *subparams; if (_PyObject_LookupAttrId(obj, &PyId___parameters__, &subparams) < 0) { diff -Nru python3.10-3.10.7/Objects/iterobject.c python3.10-3.10.12/Objects/iterobject.c --- python3.10-3.10.7/Objects/iterobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/iterobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -104,11 +104,16 @@ static PyObject * iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored)) { + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_seq != NULL) - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); else - return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); + return Py_BuildValue("N(())", iter); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -218,7 +223,7 @@ } result = _PyObject_CallNoArg(it->it_callable); - if (result != NULL) { + if (result != NULL && it->it_sentinel != NULL){ int ok; ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ); @@ -226,7 +231,6 @@ return result; /* Common case, fast path */ } - Py_DECREF(result); if (ok > 0) { Py_CLEAR(it->it_callable); Py_CLEAR(it->it_sentinel); @@ -237,17 +241,23 @@ Py_CLEAR(it->it_callable); Py_CLEAR(it->it_sentinel); } + Py_XDECREF(result); return NULL; } static PyObject * calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored)) { + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_callable != NULL && it->it_sentinel != NULL) - return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_iter), - it->it_callable, it->it_sentinel); + return Py_BuildValue("N(OO)", iter, it->it_callable, it->it_sentinel); else - return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); + return Py_BuildValue("N(())", iter); } static PyMethodDef calliter_methods[] = { diff -Nru python3.10-3.10.7/Objects/listobject.c python3.10-3.10.12/Objects/listobject.c --- python3.10-3.10.7/Objects/listobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/listobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -77,8 +77,14 @@ if (newsize == 0) new_allocated = 0; - num_allocated_bytes = new_allocated * sizeof(PyObject *); - items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes); + if (new_allocated <= (size_t)PY_SSIZE_T_MAX / sizeof(PyObject *)) { + num_allocated_bytes = new_allocated * sizeof(PyObject *); + items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes); + } + else { + // integer overflow + items = NULL; + } if (items == NULL) { PyErr_NoMemory(); return -1; @@ -3399,17 +3405,31 @@ _Py_IDENTIFIER(reversed); PyObject *list; + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + /* the objects are not the same, index is of different types! */ if (forward) { + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + if (!iter) { + return NULL; + } listiterobject *it = (listiterobject *)_it; - if (it->it_seq) - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + if (it->it_seq) { + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); + } + Py_DECREF(iter); } else { + PyObject *reversed = _PyEval_GetBuiltinId(&PyId_reversed); + if (!reversed) { + return NULL; + } listreviterobject *it = (listreviterobject *)_it; - if (it->it_seq) - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_reversed), - it->it_seq, it->it_index); + if (it->it_seq) { + return Py_BuildValue("N(O)n", reversed, it->it_seq, it->it_index); + } + Py_DECREF(reversed); } /* empty iterator, create an empty list */ list = PyList_New(0); diff -Nru python3.10-3.10.7/Objects/longobject.c python3.10-3.10.12/Objects/longobject.c --- python3.10-3.10.7/Objects/longobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/longobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -36,8 +36,8 @@ #define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS) #define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS) -#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits" -#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion" +#define _MAX_STR_DIGITS_ERROR_FMT_TO_INT "Exceeds the limit (%d) for integer string conversion: value has %zd digits; use sys.set_int_max_str_digits() to increase the limit" +#define _MAX_STR_DIGITS_ERROR_FMT_TO_STR "Exceeds the limit (%d) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit" static PyObject * get_small_int(sdigit ival) diff -Nru python3.10-3.10.7/Objects/object.c python3.10-3.10.12/Objects/object.c --- python3.10-3.10.7/Objects/object.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/object.c 2023-06-06 22:30:33.000000000 +0000 @@ -1091,8 +1091,9 @@ tsize = -tsize; } size_t size = _PyObject_VAR_SIZE(tp, tsize); + assert(size <= (size_t)PY_SSIZE_T_MAX); + dictoffset += (Py_ssize_t)size; - dictoffset += (long)size; _PyObject_ASSERT(obj, dictoffset > 0); _PyObject_ASSERT(obj, dictoffset % SIZEOF_VOID_P == 0); } @@ -1319,6 +1320,8 @@ PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%U'", tp->tp_name, name); + + set_attribute_error_context(obj, name); } done: Py_XDECREF(descr); diff -Nru python3.10-3.10.7/Objects/obmalloc.c python3.10-3.10.12/Objects/obmalloc.c --- python3.10-3.10.7/Objects/obmalloc.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/obmalloc.c 2023-06-06 22:30:33.000000000 +0000 @@ -2962,7 +2962,6 @@ * will be living in full pools -- would be a shame to miss them. */ for (i = 0; i < maxarenas; ++i) { - uint j; uintptr_t base = arenas[i].address; /* Skip arenas which are not allocated. */ @@ -2981,8 +2980,7 @@ /* visit every pool in the arena */ assert(base <= (uintptr_t) arenas[i].pool_address); - for (j = 0; base < (uintptr_t) arenas[i].pool_address; - ++j, base += POOL_SIZE) { + for (; base < (uintptr_t) arenas[i].pool_address; base += POOL_SIZE) { poolp p = (poolp)base; const uint sz = p->szidx; uint freeblocks; diff -Nru python3.10-3.10.7/Objects/tupleobject.c python3.10-3.10.12/Objects/tupleobject.c --- python3.10-3.10.7/Objects/tupleobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/tupleobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -1115,11 +1115,16 @@ tupleiter_reduce(tupleiterobject *it, PyObject *Py_UNUSED(ignored)) { _Py_IDENTIFIER(iter); + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_seq) - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); else - return Py_BuildValue("N(())", _PyEval_GetBuiltinId(&PyId_iter)); + return Py_BuildValue("N(())", iter); } static PyObject * diff -Nru python3.10-3.10.7/Objects/unicodeobject.c python3.10-3.10.12/Objects/unicodeobject.c --- python3.10-3.10.7/Objects/unicodeobject.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Objects/unicodeobject.c 2023-06-06 22:30:33.000000000 +0000 @@ -16070,14 +16070,21 @@ unicodeiter_reduce(unicodeiterobject *it, PyObject *Py_UNUSED(ignored)) { _Py_IDENTIFIER(iter); + PyObject *iter = _PyEval_GetBuiltinId(&PyId_iter); + + /* _PyEval_GetBuiltinId can invoke arbitrary code, + * call must be before access of iterator pointers. + * see issue #101765 */ + if (it->it_seq != NULL) { - return Py_BuildValue("N(O)n", _PyEval_GetBuiltinId(&PyId_iter), - it->it_seq, it->it_index); + return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index); } else { PyObject *u = (PyObject *)_PyUnicode_New(0); - if (u == NULL) + if (u == NULL) { + Py_XDECREF(iter); return NULL; - return Py_BuildValue("N(N)", _PyEval_GetBuiltinId(&PyId_iter), u); + } + return Py_BuildValue("N(N)", iter, u); } } diff -Nru python3.10-3.10.7/Parser/parser.c python3.10-3.10.12/Parser/parser.c --- python3.10-3.10.7/Parser/parser.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Parser/parser.c 2023-06-06 22:30:33.000000000 +0000 @@ -22039,7 +22039,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22065,6 +22064,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22089,7 +22089,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_1_type, _seq); p->level--; return _seq; } @@ -22108,7 +22107,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22134,6 +22132,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22158,7 +22157,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_2_type, _seq); p->level--; return _seq; } @@ -22177,7 +22175,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22212,6 +22209,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22236,7 +22234,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_4_type, _seq); p->level--; return _seq; } @@ -22297,7 +22294,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22332,6 +22328,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22356,7 +22353,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_6_type, _seq); p->level--; return _seq; } @@ -22417,7 +22413,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22452,6 +22447,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22476,7 +22472,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_8_type, _seq); p->level--; return _seq; } @@ -22537,7 +22532,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22572,6 +22566,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22596,7 +22591,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_10_type, _seq); p->level--; return _seq; } @@ -22657,7 +22651,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22683,6 +22676,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22712,7 +22706,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_11_type, _seq); p->level--; return _seq; } @@ -22731,7 +22724,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -22766,6 +22758,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -22790,7 +22783,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_13_type, _seq); p->level--; return _seq; } @@ -23323,7 +23315,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -23349,6 +23340,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -23378,7 +23370,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_22_type, _seq); p->level--; return _seq; } @@ -23513,7 +23504,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -23548,6 +23538,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -23572,7 +23563,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_26_type, _seq); p->level--; return _seq; } @@ -23633,7 +23623,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -23668,6 +23657,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -23692,7 +23682,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_28_type, _seq); p->level--; return _seq; } @@ -23858,7 +23847,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -23884,6 +23872,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -23908,7 +23897,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_31_type, _seq); p->level--; return _seq; } @@ -23927,7 +23915,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -23953,6 +23940,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -23982,7 +23970,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_32_type, _seq); p->level--; return _seq; } @@ -24001,7 +23988,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24036,6 +24022,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24060,7 +24047,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_34_type, _seq); p->level--; return _seq; } @@ -24168,7 +24154,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24203,6 +24188,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24227,7 +24213,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_37_type, _seq); p->level--; return _seq; } @@ -24335,7 +24320,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24370,6 +24354,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24394,7 +24379,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_40_type, _seq); p->level--; return _seq; } @@ -24455,7 +24439,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24490,6 +24473,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24514,7 +24498,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_42_type, _seq); p->level--; return _seq; } @@ -24575,7 +24558,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24610,6 +24592,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24634,7 +24617,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_44_type, _seq); p->level--; return _seq; } @@ -24695,7 +24677,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24730,6 +24711,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24754,7 +24736,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_46_type, _seq); p->level--; return _seq; } @@ -24892,7 +24873,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -24918,6 +24898,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -24947,7 +24928,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_48_type, _seq); p->level--; return _seq; } @@ -25013,7 +24993,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25039,6 +25018,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25068,7 +25048,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_50_type, _seq); p->level--; return _seq; } @@ -25087,7 +25066,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25122,6 +25100,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25146,7 +25125,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_52_type, _seq); p->level--; return _seq; } @@ -25477,7 +25455,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25512,6 +25489,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25536,7 +25514,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_58_type, _seq); p->level--; return _seq; } @@ -25597,7 +25574,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25632,6 +25608,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25656,7 +25633,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_60_type, _seq); p->level--; return _seq; } @@ -25775,7 +25751,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25810,6 +25785,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25834,7 +25810,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_63_type, _seq); p->level--; return _seq; } @@ -25895,7 +25870,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -25930,6 +25904,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -25954,7 +25929,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_65_type, _seq); p->level--; return _seq; } @@ -26198,7 +26172,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26224,6 +26197,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26248,7 +26222,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_70_type, _seq); p->level--; return _seq; } @@ -26267,7 +26240,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26293,6 +26265,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26317,7 +26290,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq); p->level--; return _seq; } @@ -26336,7 +26308,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26362,6 +26333,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26386,7 +26358,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_72_type, _seq); p->level--; return _seq; } @@ -26405,7 +26376,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26431,6 +26401,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26460,7 +26431,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_73_type, _seq); p->level--; return _seq; } @@ -26479,7 +26449,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26505,6 +26474,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26529,7 +26499,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq); p->level--; return _seq; } @@ -26548,7 +26517,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26574,6 +26542,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26603,7 +26572,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_75_type, _seq); p->level--; return _seq; } @@ -26622,7 +26590,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26648,6 +26615,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26677,7 +26645,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_76_type, _seq); p->level--; return _seq; } @@ -26696,7 +26663,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26722,6 +26688,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26751,7 +26718,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq); p->level--; return _seq; } @@ -26770,7 +26736,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26796,6 +26761,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26820,7 +26786,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq); p->level--; return _seq; } @@ -26839,7 +26804,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26865,6 +26829,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26894,7 +26859,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq); p->level--; return _seq; } @@ -26913,7 +26877,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -26939,6 +26902,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -26963,7 +26927,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_80_type, _seq); p->level--; return _seq; } @@ -26982,7 +26945,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27008,6 +26970,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27037,7 +27000,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq); p->level--; return _seq; } @@ -27056,7 +27018,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27082,6 +27043,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27106,7 +27068,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq); p->level--; return _seq; } @@ -27125,7 +27086,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27151,6 +27111,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27180,7 +27141,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq); p->level--; return _seq; } @@ -27199,7 +27159,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27225,6 +27184,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27254,7 +27214,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_84_type, _seq); p->level--; return _seq; } @@ -27323,7 +27282,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27349,6 +27307,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27378,7 +27337,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_86_type, _seq); p->level--; return _seq; } @@ -27397,7 +27355,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27432,6 +27389,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27456,7 +27414,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq); p->level--; return _seq; } @@ -27517,7 +27474,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27543,6 +27499,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27572,7 +27529,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq); p->level--; return _seq; } @@ -27591,7 +27547,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27617,6 +27572,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27641,7 +27597,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_90_type, _seq); p->level--; return _seq; } @@ -27660,7 +27615,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27686,6 +27640,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27710,7 +27665,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_91_type, _seq); p->level--; return _seq; } @@ -27729,7 +27683,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27755,6 +27708,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27779,7 +27733,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_92_type, _seq); p->level--; return _seq; } @@ -27798,7 +27751,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27824,6 +27776,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27853,7 +27806,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_93_type, _seq); p->level--; return _seq; } @@ -27872,7 +27824,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27898,6 +27849,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27922,7 +27874,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_94_type, _seq); p->level--; return _seq; } @@ -27941,7 +27892,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -27967,6 +27917,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -27996,7 +27947,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_95_type, _seq); p->level--; return _seq; } @@ -28015,7 +27965,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28041,6 +27990,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28070,7 +28020,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_96_type, _seq); p->level--; return _seq; } @@ -28089,7 +28038,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28115,6 +28063,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28144,7 +28093,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_97_type, _seq); p->level--; return _seq; } @@ -28163,7 +28111,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28189,6 +28136,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28213,7 +28161,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_98_type, _seq); p->level--; return _seq; } @@ -28232,7 +28179,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28258,6 +28204,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28287,7 +28234,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_99_type, _seq); p->level--; return _seq; } @@ -28306,7 +28252,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28332,6 +28277,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28356,7 +28302,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_100_type, _seq); p->level--; return _seq; } @@ -28375,7 +28320,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28401,6 +28345,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28430,7 +28375,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_101_type, _seq); p->level--; return _seq; } @@ -28449,7 +28393,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28475,6 +28418,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28499,7 +28443,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq); p->level--; return _seq; } @@ -28518,7 +28461,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28544,6 +28486,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28573,7 +28516,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq); p->level--; return _seq; } @@ -28592,7 +28534,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28618,6 +28559,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28647,7 +28589,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_104_type, _seq); p->level--; return _seq; } @@ -28666,7 +28607,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28692,6 +28632,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28721,7 +28662,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq); p->level--; return _seq; } @@ -28740,7 +28680,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28766,6 +28705,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28795,7 +28735,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_106_type, _seq); p->level--; return _seq; } @@ -28858,7 +28797,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -28893,6 +28831,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -28917,7 +28856,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq); p->level--; return _seq; } @@ -29256,7 +29194,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29282,6 +29219,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29311,7 +29249,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_114_type, _seq); p->level--; return _seq; } @@ -29498,7 +29435,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29533,6 +29469,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29557,7 +29494,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq); p->level--; return _seq; } @@ -29618,7 +29554,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29644,6 +29579,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29673,7 +29609,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_120_type, _seq); p->level--; return _seq; } @@ -29692,7 +29627,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29718,6 +29652,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29742,7 +29677,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq); p->level--; return _seq; } @@ -29761,7 +29695,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29787,6 +29720,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29811,7 +29745,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq); p->level--; return _seq; } @@ -29830,7 +29763,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -29865,6 +29797,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -29889,7 +29822,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); p->level--; return _seq; } @@ -29998,7 +29930,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30033,6 +29964,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30057,7 +29989,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); p->level--; return _seq; } @@ -30118,7 +30049,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30153,6 +30083,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30177,7 +30108,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); p->level--; return _seq; } @@ -30238,7 +30168,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30273,6 +30202,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30297,7 +30227,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); p->level--; return _seq; } @@ -30358,7 +30287,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30393,6 +30321,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30417,7 +30346,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); p->level--; return _seq; } @@ -30478,7 +30406,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30504,6 +30431,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30528,7 +30456,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq); p->level--; return _seq; } @@ -30547,7 +30474,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30582,6 +30508,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30606,7 +30533,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_136_type, _seq); p->level--; return _seq; } @@ -30667,7 +30593,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30693,6 +30618,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30722,7 +30648,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_137_type, _seq); p->level--; return _seq; } @@ -30782,7 +30707,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -30817,6 +30741,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -30841,7 +30766,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_140_type, _seq); p->level--; return _seq; } @@ -31451,7 +31375,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -31477,6 +31400,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -31501,7 +31425,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_149_type, _seq); p->level--; return _seq; } @@ -31520,7 +31443,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -31546,6 +31468,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -31570,7 +31493,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_150_type, _seq); p->level--; return _seq; } @@ -31589,7 +31511,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -31615,6 +31536,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -31639,7 +31561,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_151_type, _seq); p->level--; return _seq; } @@ -31909,7 +31830,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -31935,6 +31855,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -31959,7 +31880,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_156_type, _seq); p->level--; return _seq; } @@ -31978,7 +31898,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32004,6 +31923,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32033,7 +31953,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_157_type, _seq); p->level--; return _seq; } @@ -32052,7 +31971,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32078,6 +31996,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32102,7 +32021,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_158_type, _seq); p->level--; return _seq; } @@ -32121,7 +32039,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32147,6 +32064,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32176,7 +32094,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_159_type, _seq); p->level--; return _seq; } @@ -32394,7 +32311,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32429,6 +32345,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32453,7 +32370,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_164_type, _seq); p->level--; return _seq; } @@ -32514,7 +32430,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32549,6 +32464,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32573,7 +32489,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_166_type, _seq); p->level--; return _seq; } @@ -32634,7 +32549,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32669,6 +32583,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32693,7 +32608,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_168_type, _seq); p->level--; return _seq; } @@ -32754,7 +32668,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -32789,6 +32702,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -32813,7 +32727,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_170_type, _seq); p->level--; return _seq; } @@ -33234,7 +33147,6 @@ } void *_res = NULL; int _mark = p->mark; - int _start_mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { p->error_indicator = 1; @@ -33269,6 +33181,7 @@ _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); if (!_new_children) { + PyMem_Free(_children); p->error_indicator = 1; PyErr_NoMemory(); p->level--; @@ -33293,7 +33206,6 @@ } for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_180_type, _seq); p->level--; return _seq; } diff -Nru python3.10-3.10.7/Parser/pegen.c python3.10-3.10.12/Parser/pegen.c --- python3.10-3.10.7/Parser/pegen.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Parser/pegen.c 2023-06-06 22:30:33.000000000 +0000 @@ -809,7 +809,7 @@ static long memo_statistics[NSTATISTICS]; void -_PyPegen_clear_memo_statistics() +_PyPegen_clear_memo_statistics(void) { for (int i = 0; i < NSTATISTICS; i++) { memo_statistics[i] = 0; @@ -817,7 +817,7 @@ } PyObject * -_PyPegen_get_memo_statistics() +_PyPegen_get_memo_statistics(void) { PyObject *ret = PyList_New(NSTATISTICS); if (ret == NULL) { @@ -1328,6 +1328,10 @@ const char *end; switch (PyTokenizer_Get(p->tok, &start, &end)) { case ERRORTOKEN: + if (PyErr_Occurred()) { + ret = -1; + goto exit; + } if (p->tok->level != 0) { int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; if (current_err_line > error_lineno) { diff -Nru python3.10-3.10.7/Parser/tokenizer.c python3.10-3.10.12/Parser/tokenizer.c --- python3.10-3.10.7/Parser/tokenizer.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Parser/tokenizer.c 2023-06-06 22:30:33.000000000 +0000 @@ -419,7 +419,11 @@ error_ret(tok); goto error; } - if (!tok_reserve_buf(tok, buflen + 1)) { + // Make room for the null terminator *and* potentially + // an extra newline character that we may need to artificially + // add. + size_t buffer_size = buflen + 2; + if (!tok_reserve_buf(tok, buffer_size)) { goto error; } memcpy(tok->inp, buf, buflen); @@ -973,6 +977,7 @@ return 0; } if (tok->inp[-1] != '\n') { + assert(tok->inp + 1 < tok->end); /* Last line does not end in \n, fake one */ *tok->inp++ = '\n'; *tok->inp = '\0'; @@ -1530,7 +1535,7 @@ } while (c == ' ' || c == '\t' || c == '\014'); /* Set start of current token */ - tok->start = tok->cur - 1; + tok->start = tok->cur == NULL ? NULL : tok->cur - 1; /* Skip comment, unless it's a type comment */ if (c == '#') { @@ -1965,6 +1970,8 @@ /* Get rest of string */ while (end_quote_size != quote_size) { c = tok_nextc(tok); + if (tok->done == E_DECODE) + break; if (c == EOF || (quote_size == 1 && c == '\n')) { assert(tok->multi_line_start != NULL); // shift the tok_state's location into diff -Nru python3.10-3.10.7/PC/clinic/_msi.c.h python3.10-3.10.12/PC/clinic/_msi.c.h --- python3.10-3.10.7/PC/clinic/_msi.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/clinic/_msi.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -195,7 +195,7 @@ { PyObject *return_value = NULL; int field; - const Py_UNICODE *value; + const Py_UNICODE *value = NULL; if (!_PyArg_CheckPositional("SetString", nargs, 2, 2)) { goto exit; @@ -244,7 +244,7 @@ { PyObject *return_value = NULL; int field; - const Py_UNICODE *value; + const Py_UNICODE *value = NULL; if (!_PyArg_CheckPositional("SetStream", nargs, 2, 2)) { goto exit; @@ -555,7 +555,7 @@ _msi_Database_OpenView(msiobj *self, PyObject *arg) { PyObject *return_value = NULL; - const Py_UNICODE *sql; + const Py_UNICODE *sql = NULL; if (!PyUnicode_Check(arg)) { _PyArg_BadArgument("OpenView", "argument", "str", arg); @@ -650,7 +650,7 @@ _msi_OpenDatabase(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const Py_UNICODE *path; + const Py_UNICODE *path = NULL; int persist; if (!_PyArg_CheckPositional("OpenDatabase", nargs, 2, 2)) { @@ -713,4 +713,4 @@ exit: return return_value; } -/*[clinic end generated code: output=49debf733ee5cab2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=19b24ee4e6420dcd input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/PC/clinic/winreg.c.h python3.10-3.10.12/PC/clinic/winreg.c.h --- python3.10-3.10.7/PC/clinic/winreg.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/clinic/winreg.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -148,7 +148,7 @@ winreg_ConnectRegistry(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const Py_UNICODE *computer_name; + const Py_UNICODE *computer_name = NULL; HKEY key; HKEY _return_value; @@ -220,7 +220,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; HKEY _return_value; if (!_PyArg_CheckPositional("CreateKey", nargs, 2, 2)) { @@ -301,7 +301,7 @@ static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&O&|ii:CreateKeyEx", _keywords, 0}; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; int reserved = 0; REGSAM access = KEY_WRITE; HKEY _return_value; @@ -354,7 +354,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; if (!_PyArg_CheckPositional("DeleteKey", nargs, 2, 2)) { goto exit; @@ -428,7 +428,7 @@ static const char * const _keywords[] = {"key", "sub_key", "access", "reserved", NULL}; static _PyArg_Parser _parser = {"O&O&|ii:DeleteKeyEx", _keywords, 0}; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; REGSAM access = KEY_WOW64_64KEY; int reserved = 0; @@ -469,7 +469,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *value; + const Py_UNICODE *value = NULL; if (!_PyArg_CheckPositional("DeleteValue", nargs, 2, 2)) { goto exit; @@ -619,7 +619,7 @@ winreg_ExpandEnvironmentStrings(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - const Py_UNICODE *string; + const Py_UNICODE *string = NULL; if (!PyUnicode_Check(arg)) { _PyArg_BadArgument("ExpandEnvironmentStrings", "argument", "str", arg); @@ -724,8 +724,8 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *sub_key; - const Py_UNICODE *file_name; + const Py_UNICODE *sub_key = NULL; + const Py_UNICODE *file_name = NULL; if (!_PyArg_CheckPositional("LoadKey", nargs, 3, 3)) { goto exit; @@ -805,7 +805,7 @@ static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&O&|ii:OpenKey", _keywords, 0}; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; int reserved = 0; REGSAM access = KEY_READ; HKEY _return_value; @@ -862,7 +862,7 @@ static const char * const _keywords[] = {"key", "sub_key", "reserved", "access", NULL}; static _PyArg_Parser _parser = {"O&O&|ii:OpenKeyEx", _keywords, 0}; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; int reserved = 0; REGSAM access = KEY_READ; HKEY _return_value; @@ -953,7 +953,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; if (!_PyArg_CheckPositional("QueryValue", nargs, 2, 2)) { goto exit; @@ -1016,7 +1016,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *name; + const Py_UNICODE *name = NULL; if (!_PyArg_CheckPositional("QueryValueEx", nargs, 2, 2)) { goto exit; @@ -1084,7 +1084,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *file_name; + const Py_UNICODE *file_name = NULL; if (!_PyArg_CheckPositional("SaveKey", nargs, 2, 2)) { goto exit; @@ -1153,7 +1153,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *sub_key; + const Py_UNICODE *sub_key = NULL; DWORD type; PyObject *value_obj; @@ -1228,7 +1228,7 @@ { PyObject *return_value = NULL; HKEY key; - const Py_UNICODE *value_name; + const Py_UNICODE *value_name = NULL; PyObject *reserved; DWORD type; PyObject *value; @@ -1349,4 +1349,4 @@ exit: return return_value; } -/*[clinic end generated code: output=8ce6fb3b6cd46242 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1c96481d6be5c0d8 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/PC/_msi.c python3.10-3.10.12/PC/_msi.c --- python3.10-3.10.7/PC/_msi.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/_msi.c 2023-06-06 22:30:33.000000000 +0000 @@ -360,7 +360,7 @@ int code; char buf[2000]; char *res = buf; - DWORD size = sizeof(buf); + DWORD size = Py_ARRAY_LENGTH(buf); MSIHANDLE err = MsiGetLastErrorRecord(); if (err == 0) { @@ -484,7 +484,7 @@ unsigned int status; WCHAR buf[2000]; WCHAR *res = buf; - DWORD size = sizeof(buf); + DWORD size = Py_ARRAY_LENGTH(buf); PyObject* string; status = MsiRecordGetStringW(self->h, field, res, &size); diff -Nru python3.10-3.10.7/PC/python_uwp.cpp python3.10-3.10.12/PC/python_uwp.cpp --- python3.10-3.10.7/PC/python_uwp.cpp 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/python_uwp.cpp 2023-06-06 22:30:33.000000000 +0000 @@ -10,6 +10,7 @@ #include +#include #include #include @@ -28,37 +29,49 @@ #endif static std::wstring -get_user_base() +get_package_family() { try { - const auto appData = winrt::Windows::Storage::ApplicationData::Current(); - if (appData) { - const auto localCache = appData.LocalCacheFolder(); - if (localCache) { - auto path = localCache.Path(); - if (!path.empty()) { - return std::wstring(path) + L"\\local-packages"; - } - } + UINT32 nameLength = MAX_PATH; + std::wstring name; + name.resize(nameLength); + DWORD rc = GetCurrentPackageFamilyName(&nameLength, name.data()); + if (rc == ERROR_SUCCESS) { + name.resize(nameLength - 1); + return name; } - } catch (...) { + else if (rc != ERROR_INSUFFICIENT_BUFFER) { + throw rc; + } + name.resize(nameLength); + rc = GetCurrentPackageFamilyName(&nameLength, name.data()); + if (rc != ERROR_SUCCESS) { + throw rc; + } + name.resize(nameLength - 1); + return name; } + catch (...) { + } + return std::wstring(); } static std::wstring -get_package_family() +get_user_base() { try { - const auto package = winrt::Windows::ApplicationModel::Package::Current(); - if (package) { - const auto id = package.Id(); - if (id) { - return std::wstring(id.FamilyName()); + const auto appData = winrt::Windows::Storage::ApplicationData::Current(); + if (appData) { + const auto localCache = appData.LocalCacheFolder(); + if (localCache) { + std::wstring path { localCache.Path().c_str() }; + if (!path.empty()) { + return path + L"\\local-packages"; + } } } - } - catch (...) { + } catch (...) { } return std::wstring(); @@ -68,13 +81,24 @@ get_package_home() { try { - const auto package = winrt::Windows::ApplicationModel::Package::Current(); - if (package) { - const auto path = package.InstalledLocation(); - if (path) { - return std::wstring(path.Path()); - } + UINT32 pathLength = MAX_PATH; + std::wstring path; + path.resize(pathLength); + DWORD rc = GetCurrentPackagePath(&pathLength, path.data()); + if (rc == ERROR_SUCCESS) { + path.resize(pathLength - 1); + return path; + } + else if (rc != ERROR_INSUFFICIENT_BUFFER) { + throw rc; + } + path.resize(pathLength); + rc = GetCurrentPackagePath(&pathLength, path.data()); + if (rc != ERROR_SUCCESS) { + throw rc; } + path.resize(pathLength - 1); + return path; } catch (...) { } diff -Nru python3.10-3.10.7/PC/python_ver_rc.h python3.10-3.10.12/PC/python_ver_rc.h --- python3.10-3.10.7/PC/python_ver_rc.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/python_ver_rc.h 2023-06-06 22:30:33.000000000 +0000 @@ -5,7 +5,7 @@ #include "winver.h" #define PYTHON_COMPANY "Python Software Foundation" -#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2022 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC." +#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2023 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC." #define MS_WINDOWS #include "modsupport.h" diff -Nru python3.10-3.10.7/PC/winreg.c python3.10-3.10.12/PC/winreg.c --- python3.10-3.10.7/PC/winreg.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PC/winreg.c 2023-06-06 22:30:33.000000000 +0000 @@ -564,42 +564,54 @@ { Py_ssize_t i,j; switch (typ) { - case REG_DWORD: - if (value != Py_None && !PyLong_Check(value)) - return FALSE; - *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); - if (*retDataBuf == NULL){ - PyErr_NoMemory(); - return FALSE; - } - *retDataSize = sizeof(DWORD); - if (value == Py_None) { - DWORD zero = 0; - memcpy(*retDataBuf, &zero, sizeof(DWORD)); - } - else { - DWORD d = PyLong_AsUnsignedLong(value); + case REG_DWORD: + { + if (value != Py_None && !PyLong_Check(value)) { + return FALSE; + } + DWORD d; + if (value == Py_None) { + d = 0; + } + else if (PyLong_Check(value)) { + d = PyLong_AsUnsignedLong(value); + if (d == (DWORD)(-1) && PyErr_Occurred()) { + return FALSE; + } + } + *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); + if (*retDataBuf == NULL) { + PyErr_NoMemory(); + return FALSE; + } memcpy(*retDataBuf, &d, sizeof(DWORD)); + *retDataSize = sizeof(DWORD); + break; } - break; - case REG_QWORD: - if (value != Py_None && !PyLong_Check(value)) - return FALSE; - *retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1); - if (*retDataBuf == NULL){ - PyErr_NoMemory(); - return FALSE; - } - *retDataSize = sizeof(DWORD64); - if (value == Py_None) { - DWORD64 zero = 0; - memcpy(*retDataBuf, &zero, sizeof(DWORD64)); - } - else { - DWORD64 d = PyLong_AsUnsignedLongLong(value); + case REG_QWORD: + { + if (value != Py_None && !PyLong_Check(value)) { + return FALSE; + } + DWORD64 d; + if (value == Py_None) { + d = 0; + } + else if (PyLong_Check(value)) { + d = PyLong_AsUnsignedLongLong(value); + if (d == (DWORD64)(-1) && PyErr_Occurred()) { + return FALSE; + } + } + *retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1); + if (*retDataBuf == NULL) { + PyErr_NoMemory(); + return FALSE; + } memcpy(*retDataBuf, &d, sizeof(DWORD64)); + *retDataSize = sizeof(DWORD64); + break; } - break; case REG_SZ: case REG_EXPAND_SZ: { diff -Nru python3.10-3.10.7/PCbuild/get_externals.bat python3.10-3.10.12/PCbuild/get_externals.bat --- python3.10-3.10.7/PCbuild/get_externals.bat 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/get_externals.bat 2023-06-06 22:30:33.000000000 +0000 @@ -53,13 +53,13 @@ set libraries= set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 -if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1q -set libraries=%libraries% sqlite-3.37.2.0 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1u +set libraries=%libraries% sqlite-3.40.1.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.5 -set libraries=%libraries% zlib-1.2.12 +set libraries=%libraries% zlib-1.2.13 for %%e in (%libraries%) do ( if exist "%EXTERNALS_DIR%\%%e" ( @@ -77,7 +77,7 @@ set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.3.0 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1q +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1u if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 diff -Nru python3.10-3.10.7/PCbuild/pyproject.props python3.10-3.10.12/PCbuild/pyproject.props --- python3.10-3.10.7/PCbuild/pyproject.props 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/pyproject.props 2023-06-06 22:30:33.000000000 +0000 @@ -21,6 +21,13 @@ false + + <_VCToolsVersion>$([System.Version]::Parse(`$(VCToolsVersion)`).Major).$([System.Version]::Parse(`$(VCToolsVersion)`).Minor) + + + true + + <_DebugPreprocessorDefinition>NDEBUG; <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG; @@ -47,6 +54,7 @@ true $(EnableControlFlowGuard) /utf-8 %(AdditionalOptions) + -d2pattern-opt-disable:-932189325 %(AdditionalOptions) OnlyExplicitInline @@ -76,6 +84,7 @@ PGUpdate advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;%(AdditionalDependencies) /OPT:REF,NOICF /CGTHREADS:1 /PDBTHREADS:1 %(AdditionalOptions) + -d2:-pattern-opt-disable:-932189325 %(AdditionalOptions) true diff -Nru python3.10-3.10.7/PCbuild/python.props python3.10-3.10.12/PCbuild/python.props --- python3.10-3.10.7/PCbuild/python.props 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/python.props 2023-06-06 22:30:33.000000000 +0000 @@ -52,23 +52,32 @@ $(PySourcePath)PCbuild\$(ArchName)\ $(BuildPath)\ $(BuildPath)instrumented\ - - - $(EXTERNALS_DIR) + + + + + $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.37.2.0\ - $(ExternalsDir)bzip2-1.0.8\ - $(ExternalsDir)xz-5.2.5\ - $(ExternalsDir)libffi-3.3.0\ - $(ExternalsDir)libffi-3.3.0\$(ArchName)\ - $(libffiOutDir)include - $(ExternalsDir)openssl-1.1.1q\ - $(ExternalsDir)openssl-bin-1.1.1q\$(ArchName)\ - $(opensslOutDir)include - $(ExternalsDir)\nasm-2.11.06\ - $(ExternalsDir)\zlib-1.2.12\ - + + + + + + $(ExternalsDir)sqlite-3.40.1.0\ + $(ExternalsDir)bzip2-1.0.8\ + $(ExternalsDir)xz-5.2.5\ + $(ExternalsDir)libffi-3.3.0\ + $(libffiDir)$(ArchName)\ + $(libffiOutDir)include + $(ExternalsDir)openssl-1.1.1u\ + $(ExternalsDir)openssl-bin-1.1.1u\$(ArchName)\ + $(opensslOutDir)include + $(ExternalsDir)\nasm-2.11.06\ + $(ExternalsDir)\zlib-1.2.13\ + + + _d diff -Nru python3.10-3.10.7/PCbuild/python.vcxproj python3.10-3.10.12/PCbuild/python.vcxproj --- python3.10-3.10.7/PCbuild/python.vcxproj 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/python.vcxproj 2023-06-06 22:30:33.000000000 +0000 @@ -94,7 +94,8 @@ Console - 2000000 + 2000000 + 8000000 diff -Nru python3.10-3.10.7/PCbuild/pythonw.vcxproj python3.10-3.10.12/PCbuild/pythonw.vcxproj --- python3.10-3.10.7/PCbuild/pythonw.vcxproj 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/pythonw.vcxproj 2023-06-06 22:30:33.000000000 +0000 @@ -89,7 +89,8 @@ - 2000000 + 2000000 + 8000000 diff -Nru python3.10-3.10.7/PCbuild/readme.txt python3.10-3.10.12/PCbuild/readme.txt --- python3.10-3.10.7/PCbuild/readme.txt 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/readme.txt 2023-06-06 22:30:33.000000000 +0000 @@ -167,7 +167,7 @@ Homepage: https://tukaani.org/xz/ _ssl - Python wrapper for version 1.1.1q of the OpenSSL secure sockets + Python wrapper for version 1.1.1u of the OpenSSL secure sockets library, which is downloaded from our binaries repository at https://github.com/python/cpython-bin-deps. @@ -186,7 +186,7 @@ again when building. _sqlite3 - Wraps SQLite 3.37.2, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.40.1, which is itself built by sqlite3.vcxproj Homepage: https://www.sqlite.org/ _tkinter diff -Nru python3.10-3.10.7/PCbuild/tcltk.props python3.10-3.10.12/PCbuild/tcltk.props --- python3.10-3.10.7/PCbuild/tcltk.props 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/PCbuild/tcltk.props 2023-06-06 22:30:33.000000000 +0000 @@ -2,22 +2,26 @@ - 8 - 6 - 12 - 0 - $(TclMajorVersion) - $(TclMinorVersion) - $(TclPatchLevel) - $(TclRevision) - 8 - 4 - 3 - 6 - $(ExternalsDir)tcl-core-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\ - $(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\ - $(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\ - $(ExternalsDir)tcltk-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\$(ArchName)\ + 8.6.12.0 + $(TclVersion) + 8.4.3.6 + $([System.Version]::Parse($(TclVersion)).Major) + $([System.Version]::Parse($(TclVersion)).Minor) + $([System.Version]::Parse($(TclVersion)).Build) + $([System.Version]::Parse($(TclVersion)).Revision) + $([System.Version]::Parse($(TkVersion)).Major) + $([System.Version]::Parse($(TkVersion)).Minor) + $([System.Version]::Parse($(TkVersion)).Build) + $([System.Version]::Parse($(TkVersion)).Revision) + $([System.Version]::Parse($(TixVersion)).Major) + $([System.Version]::Parse($(TixVersion)).Minor) + $([System.Version]::Parse($(TixVersion)).Build) + $([System.Version]::Parse($(TixVersion)).Revision) + $(ExternalsDir)tcl-core-$(TclVersion)\ + $(ExternalsDir)tk-$(TkVersion)\ + $(ExternalsDir)tix-$(TixVersion)\ + $(ExternalsDir)tcltk-$(TclVersion)\$(ArchName)\ + tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).dll tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).lib diff -Nru python3.10-3.10.7/Python/bltinmodule.c python3.10-3.10.12/Python/bltinmodule.c --- python3.10-3.10.7/Python/bltinmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/bltinmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -567,9 +567,11 @@ filter_dealloc(filterobject *lz) { PyObject_GC_UnTrack(lz); + Py_TRASHCAN_BEGIN(lz, filter_dealloc) Py_XDECREF(lz->func); Py_XDECREF(lz->it); Py_TYPE(lz)->tp_free(lz); + Py_TRASHCAN_END } static int @@ -2034,7 +2036,7 @@ /*[clinic input] input as builtin_input - prompt: object(c_default="NULL") = None + prompt: object(c_default="NULL") = "" / Read a string from standard input. The trailing newline is stripped. @@ -2048,7 +2050,7 @@ static PyObject * builtin_input_impl(PyObject *module, PyObject *prompt) -/*[clinic end generated code: output=83db5a191e7a0d60 input=5e8bb70c2908fe3c]*/ +/*[clinic end generated code: output=83db5a191e7a0d60 input=159c46d4ae40977e]*/ { PyObject *fin = _PySys_GetObjectId(&PyId_stdin); PyObject *fout = _PySys_GetObjectId(&PyId_stdout); diff -Nru python3.10-3.10.7/Python/ceval.c python3.10-3.10.12/Python/ceval.c --- python3.10-3.10.7/Python/ceval.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/ceval.c 2023-06-06 22:30:33.000000000 +0000 @@ -4718,7 +4718,9 @@ { int posonly_conflicts = 0; PyObject* posonly_names = PyList_New(0); - + if (posonly_names == NULL) { + goto fail; + } for(int k=0; k < co->co_posonlyargcount; k++){ PyObject* posonly_name = PyTuple_GET_ITEM(co->co_varnames, k); @@ -5512,7 +5514,7 @@ } } /* Always emit an opcode event if we're tracing all opcodes. */ - if (frame->f_trace_opcodes) { + if (frame->f_trace_opcodes && result == 0) { result = call_trace(func, obj, tstate, frame, trace_info, PyTrace_OPCODE, Py_None); } return result; diff -Nru python3.10-3.10.7/Python/ceval_gil.h python3.10-3.10.12/Python/ceval_gil.h --- python3.10-3.10.7/Python/ceval_gil.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/ceval_gil.h 2023-06-06 22:30:33.000000000 +0000 @@ -247,6 +247,7 @@ goto _ready; } + int drop_requested = 0; while (_Py_atomic_load_relaxed(&gil->locked)) { unsigned long saved_switchnum = gil->switch_number; @@ -262,11 +263,21 @@ { if (tstate_must_exit(tstate)) { MUTEX_UNLOCK(gil->mutex); + // gh-96387: If the loop requested a drop request in a previous + // iteration, reset the request. Otherwise, drop_gil() can + // block forever waiting for the thread which exited. Drop + // requests made by other threads are also reset: these threads + // may have to request again a drop request (iterate one more + // time). + if (drop_requested) { + RESET_GIL_DROP_REQUEST(interp); + } PyThread_exit_thread(); } assert(is_tstate_valid(tstate)); SET_GIL_DROP_REQUEST(interp); + drop_requested = 1; } } diff -Nru python3.10-3.10.7/Python/clinic/bltinmodule.c.h python3.10-3.10.12/Python/clinic/bltinmodule.c.h --- python3.10-3.10.7/Python/clinic/bltinmodule.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/clinic/bltinmodule.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -672,7 +672,7 @@ } PyDoc_STRVAR(builtin_input__doc__, -"input($module, prompt=None, /)\n" +"input($module, prompt=\'\', /)\n" "--\n" "\n" "Read a string from standard input. The trailing newline is stripped.\n" @@ -874,4 +874,4 @@ exit: return return_value; } -/*[clinic end generated code: output=da9ae459e9233259 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b5c1a7a1621b7cca input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Python/clinic/sysmodule.c.h python3.10-3.10.12/Python/clinic/sysmodule.c.h --- python3.10-3.10.7/Python/clinic/sysmodule.c.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/clinic/sysmodule.c.h 2023-06-06 22:30:33.000000000 +0000 @@ -651,7 +651,7 @@ "get_int_max_str_digits($module, /)\n" "--\n" "\n" -"Set the maximum string digits limit for non-binary int<->str conversions."); +"Return the maximum string digits limit for non-binary int<->str conversions."); #define SYS_GET_INT_MAX_STR_DIGITS_METHODDEF \ {"get_int_max_str_digits", (PyCFunction)sys_get_int_max_str_digits, METH_NOARGS, sys_get_int_max_str_digits__doc__}, @@ -1036,4 +1036,4 @@ #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=6230a1e3a4415744 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1d40b6af6e80cc71 input=a9049054013a1b77]*/ diff -Nru python3.10-3.10.7/Python/compile.c python3.10-3.10.12/Python/compile.c --- python3.10-3.10.7/Python/compile.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/compile.c 2023-06-06 22:30:33.000000000 +0000 @@ -2691,6 +2691,7 @@ return 1; } case Compare_kind: { + SET_LOC(c, e); Py_ssize_t i, n = asdl_seq_LEN(e->v.Compare.ops) - 1; if (n > 0) { if (!check_compare(c, e)) { @@ -3029,12 +3030,14 @@ compiler_break(struct compiler *c) { struct fblockinfo *loop = NULL; + int origin_loc = c->u->u_lineno; /* Emit instruction with line number */ ADDOP(c, NOP); if (!compiler_unwind_fblock_stack(c, 0, &loop)) { return 0; } if (loop == NULL) { + c->u->u_lineno = origin_loc; return compiler_error(c, "'break' outside loop"); } if (!compiler_unwind_fblock(c, loop, 0)) { @@ -3049,12 +3052,14 @@ compiler_continue(struct compiler *c) { struct fblockinfo *loop = NULL; + int origin_loc = c->u->u_lineno; /* Emit instruction with line number */ ADDOP(c, NOP); if (!compiler_unwind_fblock_stack(c, 0, &loop)) { return 0; } if (loop == NULL) { + c->u->u_lineno = origin_loc; return compiler_error(c, "'continue' not properly in loop"); } ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_block); diff -Nru python3.10-3.10.7/Python/dynload_win.c python3.10-3.10.12/Python/dynload_win.c --- python3.10-3.10.7/Python/dynload_win.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/dynload_win.c 2023-06-06 22:30:33.000000000 +0000 @@ -123,14 +123,15 @@ !strncmp(import_name,"python",6)) { char *pch; -#ifndef _DEBUG - /* In a release version, don't claim that python3.dll is - a Python DLL. */ + /* Don't claim that python3.dll is a Python DLL. */ +#ifdef _DEBUG + if (strcmp(import_name, "python3_d.dll") == 0) { +#else if (strcmp(import_name, "python3.dll") == 0) { +#endif import_data += 20; continue; } -#endif /* Ensure python prefix is followed only by numbers to the end of the basename */ diff -Nru python3.10-3.10.7/Python/getargs.c python3.10-3.10.12/Python/getargs.c --- python3.10-3.10.7/Python/getargs.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/getargs.c 2023-06-06 22:30:33.000000000 +0000 @@ -201,9 +201,9 @@ static int cleanup_ptr(PyObject *self, void *ptr) { - if (ptr) { - PyMem_Free(ptr); - } + void **pptr = (void **)ptr; + PyMem_Free(*pptr); + *pptr = NULL; return 0; } @@ -1168,7 +1168,7 @@ PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1214,7 +1214,7 @@ PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); diff -Nru python3.10-3.10.7/Python/getcopyright.c python3.10-3.10.12/Python/getcopyright.c --- python3.10-3.10.7/Python/getcopyright.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/getcopyright.c 2023-06-06 22:30:33.000000000 +0000 @@ -4,7 +4,7 @@ static const char cprt[] = "\ -Copyright (c) 2001-2022 Python Software Foundation.\n\ +Copyright (c) 2001-2023 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ diff -Nru python3.10-3.10.7/Python/import.c python3.10-3.10.12/Python/import.c --- python3.10-3.10.7/Python/import.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/import.c 2023-06-06 22:30:33.000000000 +0000 @@ -1006,7 +1006,8 @@ if (_PyUnicode_EqualToASCIIString(name, p->name)) { if (p->initfunc == NULL) { /* Cannot re-init internal module ("sys" or "builtins") */ - return PyImport_AddModuleObject(name); + mod = PyImport_AddModuleObject(name); + return Py_XNewRef(mod); } mod = (*p->initfunc)(); diff -Nru python3.10-3.10.7/Python/importlib_external.h python3.10-3.10.12/Python/importlib_external.h --- python3.10-3.10.7/Python/importlib_external.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/importlib_external.h 2023-06-06 22:30:33.000000000 +0000 @@ -836,7 +836,7 @@ 114,7,0,0,0,114,8,0,0,0,218,23,95,118,97,108, 105,100,97,116,101,95,116,105,109,101,115,116,97,109,112,95, 112,121,99,106,2,0,0,115,18,0,0,0,24,19,10,1, - 12,1,16,1,8,1,22,1,2,255,22,2,8,254,114,180, + 12,1,16,1,8,1,24,1,22,1,4,254,4,1,114,180, 0,0,0,99,4,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,4,0,0,0,67,0,0,0,115,42,0,0, 0,124,0,100,1,100,2,133,2,25,0,124,1,107,3,114, @@ -1468,1304 +1468,1304 @@ 98,121,116,101,115,95,100,97,116,97,90,11,99,111,100,101, 95,111,98,106,101,99,116,114,7,0,0,0,114,7,0,0, 0,114,8,0,0,0,114,241,0,0,0,182,3,0,0,115, - 170,0,0,0,10,7,4,1,4,1,4,1,4,1,4,1, + 166,0,0,0,10,7,4,1,4,1,4,1,4,1,4,1, 2,1,12,1,12,1,8,1,2,255,2,3,14,1,12,1, 4,1,2,255,12,3,2,1,14,1,12,1,4,1,2,255, 2,4,2,1,6,254,2,4,12,1,16,1,12,1,4,1, - 12,1,10,1,2,1,2,255,8,2,2,254,10,3,4,1, - 2,1,2,1,4,254,8,4,2,1,4,255,2,128,2,3, - 2,1,2,1,6,1,2,1,2,1,4,251,4,128,16,7, - 4,1,2,255,8,3,2,1,4,255,6,2,2,1,2,1, - 6,254,8,3,10,1,12,1,12,1,14,1,6,1,2,255, - 4,2,8,1,10,1,14,1,6,2,6,1,4,255,2,2, - 16,1,4,3,12,254,2,1,4,1,2,254,4,2,122,21, - 83,111,117,114,99,101,76,111,97,100,101,114,46,103,101,116, - 95,99,111,100,101,78,41,10,114,150,0,0,0,114,149,0, - 0,0,114,151,0,0,0,114,251,0,0,0,114,252,0,0, - 0,114,254,0,0,0,114,253,0,0,0,114,1,1,0,0, - 114,5,1,0,0,114,241,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,249, - 0,0,0,123,3,0,0,115,16,0,0,0,8,0,8,2, - 8,8,8,14,8,10,8,7,14,10,12,8,114,249,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,4,0,0,0,0,0,0,0,115,92,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,132, - 0,90,4,100,4,100,5,132,0,90,5,100,6,100,7,132, - 0,90,6,101,7,135,0,102,1,100,8,100,9,132,8,131, - 1,90,8,101,7,100,10,100,11,132,0,131,1,90,9,100, - 12,100,13,132,0,90,10,101,7,100,14,100,15,132,0,131, - 1,90,11,135,0,4,0,90,12,83,0,41,16,218,10,70, - 105,108,101,76,111,97,100,101,114,122,103,66,97,115,101,32, - 102,105,108,101,32,108,111,97,100,101,114,32,99,108,97,115, - 115,32,119,104,105,99,104,32,105,109,112,108,101,109,101,110, - 116,115,32,116,104,101,32,108,111,97,100,101,114,32,112,114, - 111,116,111,99,111,108,32,109,101,116,104,111,100,115,32,116, - 104,97,116,10,32,32,32,32,114,101,113,117,105,114,101,32, - 102,105,108,101,32,115,121,115,116,101,109,32,117,115,97,103, - 101,46,99,3,0,0,0,0,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,100,1,83,0, - 41,2,122,75,67,97,99,104,101,32,116,104,101,32,109,111, - 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, - 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, - 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, - 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, - 114,183,0,0,0,41,3,114,143,0,0,0,114,163,0,0, - 0,114,65,0,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,236,0,0,0,16,4,0,0,115,4, - 0,0,0,6,3,10,1,122,19,70,105,108,101,76,111,97, - 100,101,114,46,95,95,105,110,105,116,95,95,99,2,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,243,24,0,0,0,124,0,106,0,124,1, - 106,0,107,2,111,11,124,0,106,1,124,1,106,1,107,2, - 83,0,114,69,0,0,0,169,2,218,9,95,95,99,108,97, - 115,115,95,95,114,156,0,0,0,169,2,114,143,0,0,0, - 90,5,111,116,104,101,114,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,218,6,95,95,101,113,95,95,22,4, - 0,0,243,6,0,0,0,12,1,10,1,2,255,122,17,70, - 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,243,20,0,0,0,116,0, - 124,0,106,1,131,1,116,0,124,0,106,2,131,1,65,0, - 83,0,114,69,0,0,0,169,3,218,4,104,97,115,104,114, - 141,0,0,0,114,65,0,0,0,169,1,114,143,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 8,95,95,104,97,115,104,95,95,26,4,0,0,243,2,0, - 0,0,20,1,122,19,70,105,108,101,76,111,97,100,101,114, - 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, - 0,0,115,16,0,0,0,116,0,116,1,124,0,131,2,160, - 2,124,1,161,1,83,0,41,1,122,100,76,111,97,100,32, - 97,32,109,111,100,117,108,101,32,102,114,111,109,32,97,32, - 102,105,108,101,46,10,10,32,32,32,32,32,32,32,32,84, - 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,101, - 120,101,99,95,109,111,100,117,108,101,40,41,32,105,110,115, - 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,41, - 3,218,5,115,117,112,101,114,114,11,1,0,0,114,248,0, - 0,0,114,247,0,0,0,169,1,114,14,1,0,0,114,7, - 0,0,0,114,8,0,0,0,114,248,0,0,0,29,4,0, - 0,115,2,0,0,0,16,10,122,22,70,105,108,101,76,111, - 97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,243,6,0,0,0,124,0, - 106,0,83,0,169,1,122,58,82,101,116,117,114,110,32,116, - 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, - 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, - 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, - 114,46,114,71,0,0,0,114,247,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,203,0,0,0, - 41,4,0,0,243,2,0,0,0,6,3,122,23,70,105,108, - 101,76,111,97,100,101,114,46,103,101,116,95,102,105,108,101, - 110,97,109,101,99,2,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,8,0,0,0,67,0,0,0,115,128,0, - 0,0,116,0,124,0,116,1,116,2,102,2,131,2,114,36, - 116,3,160,4,116,5,124,1,131,1,161,1,143,12,125,2, - 124,2,160,6,161,0,87,0,2,0,100,1,4,0,4,0, - 131,3,1,0,83,0,49,0,115,29,119,1,1,0,1,0, - 1,0,89,0,1,0,100,1,83,0,116,3,160,7,124,1, - 100,2,161,2,143,12,125,2,124,2,160,6,161,0,87,0, - 2,0,100,1,4,0,4,0,131,3,1,0,83,0,49,0, - 115,57,119,1,1,0,1,0,1,0,89,0,1,0,100,1, - 83,0,41,3,122,39,82,101,116,117,114,110,32,116,104,101, - 32,100,97,116,97,32,102,114,111,109,32,112,97,116,104,32, - 97,115,32,114,97,119,32,98,121,116,101,115,46,78,218,1, - 114,41,8,114,185,0,0,0,114,249,0,0,0,218,19,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,114,91,0,0,0,90,9,111,112,101,110,95,99,111, - 100,101,114,109,0,0,0,90,4,114,101,97,100,114,92,0, - 0,0,41,3,114,143,0,0,0,114,65,0,0,0,114,94, - 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,255,0,0,0,46,4,0,0,115,14,0,0,0, - 14,2,16,1,6,1,36,255,14,3,6,1,36,255,122,19, - 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,100, - 97,116,97,99,2,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,2,0,0,0,67,0,0,0,115,20,0,0, - 0,100,1,100,2,108,0,109,1,125,2,1,0,124,2,124, - 0,131,1,83,0,41,3,78,114,0,0,0,0,41,1,218, - 10,70,105,108,101,82,101,97,100,101,114,41,2,218,17,105, - 109,112,111,114,116,108,105,98,46,114,101,97,100,101,114,115, - 114,31,1,0,0,41,3,114,143,0,0,0,114,244,0,0, - 0,114,31,1,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,19,103,101,116,95,114,101,115,111,117, - 114,99,101,95,114,101,97,100,101,114,55,4,0,0,115,4, - 0,0,0,12,2,8,1,122,30,70,105,108,101,76,111,97, - 100,101,114,46,103,101,116,95,114,101,115,111,117,114,99,101, - 95,114,101,97,100,101,114,41,13,114,150,0,0,0,114,149, - 0,0,0,114,151,0,0,0,114,152,0,0,0,114,236,0, - 0,0,114,16,1,0,0,114,22,1,0,0,114,160,0,0, - 0,114,248,0,0,0,114,203,0,0,0,114,255,0,0,0, - 114,33,1,0,0,90,13,95,95,99,108,97,115,115,99,101, - 108,108,95,95,114,7,0,0,0,114,7,0,0,0,114,25, - 1,0,0,114,8,0,0,0,114,11,1,0,0,11,4,0, - 0,115,24,0,0,0,8,0,4,2,8,3,8,6,8,4, - 2,3,14,1,2,11,10,1,8,4,2,9,18,1,114,11, - 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,3,0,0,0,64,0,0,0,115,46,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, - 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, - 7,156,1,100,8,100,9,132,2,90,6,100,10,83,0,41, - 11,218,16,83,111,117,114,99,101,70,105,108,101,76,111,97, - 100,101,114,122,62,67,111,110,99,114,101,116,101,32,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32, - 83,111,117,114,99,101,76,111,97,100,101,114,32,117,115,105, - 110,103,32,116,104,101,32,102,105,108,101,32,115,121,115,116, - 101,109,46,99,2,0,0,0,0,0,0,0,0,0,0,0, - 3,0,0,0,3,0,0,0,67,0,0,0,115,22,0,0, - 0,116,0,124,1,131,1,125,2,124,2,106,1,124,2,106, - 2,100,1,156,2,83,0,41,2,122,33,82,101,116,117,114, - 110,32,116,104,101,32,109,101,116,97,100,97,116,97,32,102, - 111,114,32,116,104,101,32,112,97,116,104,46,41,2,114,193, - 0,0,0,114,6,1,0,0,41,3,114,75,0,0,0,218, - 8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,105, - 122,101,41,3,114,143,0,0,0,114,65,0,0,0,114,10, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,252,0,0,0,65,4,0,0,115,4,0,0,0, - 8,2,14,1,122,27,83,111,117,114,99,101,70,105,108,101, - 76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,116, - 115,99,4,0,0,0,0,0,0,0,0,0,0,0,5,0, - 0,0,5,0,0,0,67,0,0,0,115,24,0,0,0,116, - 0,124,1,131,1,125,4,124,0,106,1,124,2,124,3,124, - 4,100,1,141,3,83,0,41,2,78,169,1,218,5,95,109, - 111,100,101,41,2,114,139,0,0,0,114,253,0,0,0,41, - 5,114,143,0,0,0,114,134,0,0,0,114,132,0,0,0, - 114,41,0,0,0,114,78,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,254,0,0,0,70,4, - 0,0,115,4,0,0,0,8,2,16,1,122,32,83,111,117, - 114,99,101,70,105,108,101,76,111,97,100,101,114,46,95,99, - 97,99,104,101,95,98,121,116,101,99,111,100,101,114,87,0, - 0,0,114,36,1,0,0,99,3,0,0,0,0,0,0,0, - 1,0,0,0,9,0,0,0,11,0,0,0,67,0,0,0, - 115,254,0,0,0,116,0,124,1,131,1,92,2,125,4,125, - 5,103,0,125,6,124,4,114,31,116,1,124,4,131,1,115, - 31,116,0,124,4,131,1,92,2,125,4,125,7,124,6,160, - 2,124,7,161,1,1,0,124,4,114,31,116,1,124,4,131, - 1,114,14,116,3,124,6,131,1,68,0,93,49,125,7,116, - 4,124,4,124,7,131,2,125,4,122,7,116,5,160,6,124, - 4,161,1,1,0,87,0,113,35,4,0,116,7,121,58,1, - 0,1,0,1,0,89,0,113,35,4,0,116,8,121,84,1, - 0,125,8,1,0,122,15,116,9,160,10,100,1,124,4,124, - 8,161,3,1,0,87,0,89,0,100,2,125,8,126,8,1, - 0,100,2,83,0,100,2,125,8,126,8,119,1,119,0,122, - 15,116,11,124,1,124,2,124,3,131,3,1,0,116,9,160, - 10,100,3,124,1,161,2,1,0,87,0,100,2,83,0,4, - 0,116,8,121,126,1,0,125,8,1,0,122,14,116,9,160, - 10,100,1,124,1,124,8,161,3,1,0,87,0,89,0,100, - 2,125,8,126,8,100,2,83,0,100,2,125,8,126,8,119, - 1,119,0,41,4,122,27,87,114,105,116,101,32,98,121,116, - 101,115,32,100,97,116,97,32,116,111,32,97,32,102,105,108, - 101,46,122,27,99,111,117,108,100,32,110,111,116,32,99,114, - 101,97,116,101,32,123,33,114,125,58,32,123,33,114,125,78, - 122,12,99,114,101,97,116,101,100,32,123,33,114,125,41,12, - 114,74,0,0,0,114,83,0,0,0,114,61,0,0,0,218, - 8,114,101,118,101,114,115,101,100,114,67,0,0,0,114,18, - 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, - 69,120,105,115,116,115,69,114,114,111,114,114,76,0,0,0, - 114,159,0,0,0,114,173,0,0,0,114,95,0,0,0,41, - 9,114,143,0,0,0,114,65,0,0,0,114,41,0,0,0, - 114,37,1,0,0,218,6,112,97,114,101,110,116,114,120,0, - 0,0,114,63,0,0,0,114,68,0,0,0,114,0,1,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,253,0,0,0,75,4,0,0,115,56,0,0,0,12,2, - 4,1,12,2,12,1,10,1,12,254,12,4,10,1,2,1, - 14,1,12,1,4,2,14,1,6,3,4,1,4,255,16,2, - 8,128,2,251,2,6,12,1,18,1,14,1,8,2,2,1, - 18,255,8,128,2,254,122,25,83,111,117,114,99,101,70,105, - 108,101,76,111,97,100,101,114,46,115,101,116,95,100,97,116, - 97,78,41,7,114,150,0,0,0,114,149,0,0,0,114,151, - 0,0,0,114,152,0,0,0,114,252,0,0,0,114,254,0, - 0,0,114,253,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,34,1,0,0, - 61,4,0,0,115,10,0,0,0,8,0,4,2,8,2,8, - 5,18,5,114,34,1,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, - 0,115,32,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, - 90,5,100,6,83,0,41,7,218,20,83,111,117,114,99,101, - 108,101,115,115,70,105,108,101,76,111,97,100,101,114,122,45, - 76,111,97,100,101,114,32,119,104,105,99,104,32,104,97,110, - 100,108,101,115,32,115,111,117,114,99,101,108,101,115,115,32, - 102,105,108,101,32,105,109,112,111,114,116,115,46,99,2,0, + 12,1,10,1,2,1,2,255,10,2,10,1,4,1,2,1, + 2,1,4,254,8,4,2,1,4,255,2,128,2,3,2,1, + 2,1,6,1,2,1,2,1,4,251,4,128,16,7,4,1, + 2,255,8,3,2,1,4,255,6,2,2,1,2,1,6,254, + 8,3,10,1,12,1,12,1,14,1,8,1,4,1,8,1, + 10,1,14,1,6,2,6,1,4,255,2,2,16,1,4,3, + 12,254,2,1,4,1,2,254,4,2,122,21,83,111,117,114, + 99,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100, + 101,78,41,10,114,150,0,0,0,114,149,0,0,0,114,151, + 0,0,0,114,251,0,0,0,114,252,0,0,0,114,254,0, + 0,0,114,253,0,0,0,114,1,1,0,0,114,5,1,0, + 0,114,241,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,249,0,0,0,123, + 3,0,0,115,16,0,0,0,8,0,8,2,8,8,8,14, + 8,10,8,7,14,10,12,8,114,249,0,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0, + 0,0,0,0,0,0,115,92,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, + 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,101, + 7,135,0,102,1,100,8,100,9,132,8,131,1,90,8,101, + 7,100,10,100,11,132,0,131,1,90,9,100,12,100,13,132, + 0,90,10,101,7,100,14,100,15,132,0,131,1,90,11,135, + 0,4,0,90,12,83,0,41,16,218,10,70,105,108,101,76, + 111,97,100,101,114,122,103,66,97,115,101,32,102,105,108,101, + 32,108,111,97,100,101,114,32,99,108,97,115,115,32,119,104, + 105,99,104,32,105,109,112,108,101,109,101,110,116,115,32,116, + 104,101,32,108,111,97,100,101,114,32,112,114,111,116,111,99, + 111,108,32,109,101,116,104,111,100,115,32,116,104,97,116,10, + 32,32,32,32,114,101,113,117,105,114,101,32,102,105,108,101, + 32,115,121,115,116,101,109,32,117,115,97,103,101,46,99,3, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, + 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, + 95,0,124,2,124,0,95,1,100,1,83,0,41,2,122,75, + 67,97,99,104,101,32,116,104,101,32,109,111,100,117,108,101, + 32,110,97,109,101,32,97,110,100,32,116,104,101,32,112,97, + 116,104,32,116,111,32,116,104,101,32,102,105,108,101,32,102, + 111,117,110,100,32,98,121,32,116,104,101,10,32,32,32,32, + 32,32,32,32,102,105,110,100,101,114,46,78,114,183,0,0, + 0,41,3,114,143,0,0,0,114,163,0,0,0,114,65,0, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,114,236,0,0,0,16,4,0,0,115,4,0,0,0,6, + 3,10,1,122,19,70,105,108,101,76,111,97,100,101,114,46, + 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, + 0,243,24,0,0,0,124,0,106,0,124,1,106,0,107,2, + 111,11,124,0,106,1,124,1,106,1,107,2,83,0,114,69, + 0,0,0,169,2,218,9,95,95,99,108,97,115,115,95,95, + 114,156,0,0,0,169,2,114,143,0,0,0,90,5,111,116, + 104,101,114,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,218,6,95,95,101,113,95,95,22,4,0,0,243,6, + 0,0,0,12,1,10,1,2,255,122,17,70,105,108,101,76, + 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, + 0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0, + 0,67,0,0,0,243,20,0,0,0,116,0,124,0,106,1, + 131,1,116,0,124,0,106,2,131,1,65,0,83,0,114,69, + 0,0,0,169,3,218,4,104,97,115,104,114,141,0,0,0, + 114,65,0,0,0,169,1,114,143,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,218,8,95,95,104, + 97,115,104,95,95,26,4,0,0,243,2,0,0,0,20,1, + 122,19,70,105,108,101,76,111,97,100,101,114,46,95,95,104, + 97,115,104,95,95,99,2,0,0,0,0,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,3,0,0,0,115,16, + 0,0,0,116,0,116,1,124,0,131,2,160,2,124,1,161, + 1,83,0,41,1,122,100,76,111,97,100,32,97,32,109,111, + 100,117,108,101,32,102,114,111,109,32,97,32,102,105,108,101, + 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, + 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, + 97,116,101,100,46,32,32,85,115,101,32,101,120,101,99,95, + 109,111,100,117,108,101,40,41,32,105,110,115,116,101,97,100, + 46,10,10,32,32,32,32,32,32,32,32,41,3,218,5,115, + 117,112,101,114,114,11,1,0,0,114,248,0,0,0,114,247, + 0,0,0,169,1,114,14,1,0,0,114,7,0,0,0,114, + 8,0,0,0,114,248,0,0,0,29,4,0,0,115,2,0, + 0,0,16,10,122,22,70,105,108,101,76,111,97,100,101,114, + 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,243,6,0,0,0,124,0,106,0,83,0, + 169,1,122,58,82,101,116,117,114,110,32,116,104,101,32,112, + 97,116,104,32,116,111,32,116,104,101,32,115,111,117,114,99, + 101,32,102,105,108,101,32,97,115,32,102,111,117,110,100,32, + 98,121,32,116,104,101,32,102,105,110,100,101,114,46,114,71, + 0,0,0,114,247,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,203,0,0,0,41,4,0,0, + 243,2,0,0,0,6,3,122,23,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,102,105,108,101,110,97,109,101, + 99,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,128,0,0,0,116,0, + 124,0,116,1,116,2,102,2,131,2,114,36,116,3,160,4, + 116,5,124,1,131,1,161,1,143,12,125,2,124,2,160,6, + 161,0,87,0,2,0,100,1,4,0,4,0,131,3,1,0, + 83,0,49,0,115,29,119,1,1,0,1,0,1,0,89,0, + 1,0,100,1,83,0,116,3,160,7,124,1,100,2,161,2, + 143,12,125,2,124,2,160,6,161,0,87,0,2,0,100,1, + 4,0,4,0,131,3,1,0,83,0,49,0,115,57,119,1, + 1,0,1,0,1,0,89,0,1,0,100,1,83,0,41,3, + 122,39,82,101,116,117,114,110,32,116,104,101,32,100,97,116, + 97,32,102,114,111,109,32,112,97,116,104,32,97,115,32,114, + 97,119,32,98,121,116,101,115,46,78,218,1,114,41,8,114, + 185,0,0,0,114,249,0,0,0,218,19,69,120,116,101,110, + 115,105,111,110,70,105,108,101,76,111,97,100,101,114,114,91, + 0,0,0,90,9,111,112,101,110,95,99,111,100,101,114,109, + 0,0,0,90,4,114,101,97,100,114,92,0,0,0,41,3, + 114,143,0,0,0,114,65,0,0,0,114,94,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,255, + 0,0,0,46,4,0,0,115,14,0,0,0,14,2,16,1, + 6,1,36,255,14,3,6,1,36,255,122,19,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,99, + 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, + 2,0,0,0,67,0,0,0,115,20,0,0,0,100,1,100, + 2,108,0,109,1,125,2,1,0,124,2,124,0,131,1,83, + 0,41,3,78,114,0,0,0,0,41,1,218,10,70,105,108, + 101,82,101,97,100,101,114,41,2,218,17,105,109,112,111,114, + 116,108,105,98,46,114,101,97,100,101,114,115,114,31,1,0, + 0,41,3,114,143,0,0,0,114,244,0,0,0,114,31,1, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,218,19,103,101,116,95,114,101,115,111,117,114,99,101,95, + 114,101,97,100,101,114,55,4,0,0,115,4,0,0,0,12, + 2,8,1,122,30,70,105,108,101,76,111,97,100,101,114,46, + 103,101,116,95,114,101,115,111,117,114,99,101,95,114,101,97, + 100,101,114,41,13,114,150,0,0,0,114,149,0,0,0,114, + 151,0,0,0,114,152,0,0,0,114,236,0,0,0,114,16, + 1,0,0,114,22,1,0,0,114,160,0,0,0,114,248,0, + 0,0,114,203,0,0,0,114,255,0,0,0,114,33,1,0, + 0,90,13,95,95,99,108,97,115,115,99,101,108,108,95,95, + 114,7,0,0,0,114,7,0,0,0,114,25,1,0,0,114, + 8,0,0,0,114,11,1,0,0,11,4,0,0,115,24,0, + 0,0,8,0,4,2,8,3,8,6,8,4,2,3,14,1, + 2,11,10,1,8,4,2,9,18,1,114,11,1,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,64,0,0,0,115,46,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, + 4,100,4,100,5,132,0,90,5,100,6,100,7,156,1,100, + 8,100,9,132,2,90,6,100,10,83,0,41,11,218,16,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,122, + 62,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,83,111,117,114, + 99,101,76,111,97,100,101,114,32,117,115,105,110,103,32,116, + 104,101,32,102,105,108,101,32,115,121,115,116,101,109,46,99, + 2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, + 3,0,0,0,67,0,0,0,115,22,0,0,0,116,0,124, + 1,131,1,125,2,124,2,106,1,124,2,106,2,100,1,156, + 2,83,0,41,2,122,33,82,101,116,117,114,110,32,116,104, + 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,116, + 104,101,32,112,97,116,104,46,41,2,114,193,0,0,0,114, + 6,1,0,0,41,3,114,75,0,0,0,218,8,115,116,95, + 109,116,105,109,101,90,7,115,116,95,115,105,122,101,41,3, + 114,143,0,0,0,114,65,0,0,0,114,10,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,252, + 0,0,0,65,4,0,0,115,4,0,0,0,8,2,14,1, + 122,27,83,111,117,114,99,101,70,105,108,101,76,111,97,100, + 101,114,46,112,97,116,104,95,115,116,97,116,115,99,4,0, 0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0, - 0,0,67,0,0,0,115,68,0,0,0,124,0,160,0,124, - 1,161,1,125,2,124,0,160,1,124,2,161,1,125,3,124, - 1,124,2,100,1,156,2,125,4,116,2,124,3,124,1,124, - 4,131,3,1,0,116,3,116,4,124,3,131,1,100,2,100, - 0,133,2,25,0,124,1,124,2,100,3,141,3,83,0,41, - 4,78,114,183,0,0,0,114,169,0,0,0,41,2,114,141, - 0,0,0,114,132,0,0,0,41,5,114,203,0,0,0,114, - 255,0,0,0,114,176,0,0,0,114,189,0,0,0,114,7, - 1,0,0,41,5,114,143,0,0,0,114,163,0,0,0,114, - 65,0,0,0,114,41,0,0,0,114,175,0,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,114,241,0, - 0,0,110,4,0,0,115,22,0,0,0,10,1,10,1,2, - 4,2,1,6,254,12,4,2,1,14,1,2,1,2,1,6, - 253,122,29,83,111,117,114,99,101,108,101,115,115,70,105,108, - 101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,101, - 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,114,23,0,0,0,41,2, - 122,39,82,101,116,117,114,110,32,78,111,110,101,32,97,115, - 32,116,104,101,114,101,32,105,115,32,110,111,32,115,111,117, - 114,99,101,32,99,111,100,101,46,78,114,7,0,0,0,114, - 247,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,1,1,0,0,126,4,0,0,114,24,0,0, - 0,122,31,83,111,117,114,99,101,108,101,115,115,70,105,108, - 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, - 99,101,78,41,6,114,150,0,0,0,114,149,0,0,0,114, - 151,0,0,0,114,152,0,0,0,114,241,0,0,0,114,1, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,41,1,0,0,106,4,0,0, - 115,8,0,0,0,8,0,4,2,8,2,12,16,114,41,1, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,64,0,0,0,115,92,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, - 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, - 132,0,90,8,100,12,100,13,132,0,90,9,100,14,100,15, - 132,0,90,10,100,16,100,17,132,0,90,11,101,12,100,18, - 100,19,132,0,131,1,90,13,100,20,83,0,41,21,114,30, - 1,0,0,122,93,76,111,97,100,101,114,32,102,111,114,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 115,46,10,10,32,32,32,32,84,104,101,32,99,111,110,115, - 116,114,117,99,116,111,114,32,105,115,32,100,101,115,105,103, - 110,101,100,32,116,111,32,119,111,114,107,32,119,105,116,104, - 32,70,105,108,101,70,105,110,100,101,114,46,10,10,32,32, - 32,32,99,3,0,0,0,0,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,100,0,83,0, - 114,69,0,0,0,114,183,0,0,0,41,3,114,143,0,0, - 0,114,141,0,0,0,114,65,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,236,0,0,0,139, - 4,0,0,115,4,0,0,0,6,1,10,1,122,28,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, - 0,0,0,114,12,1,0,0,114,69,0,0,0,114,13,1, - 0,0,114,15,1,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,16,1,0,0,143,4,0,0,114, - 17,1,0,0,122,26,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,95,95,101,113,95,95, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,114,18,1,0,0,114,69, - 0,0,0,114,19,1,0,0,114,21,1,0,0,114,7,0, - 0,0,114,7,0,0,0,114,8,0,0,0,114,22,1,0, - 0,147,4,0,0,114,23,1,0,0,122,28,69,120,116,101, - 110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,46, - 95,95,104,97,115,104,95,95,99,2,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,5,0,0,0,67,0,0, - 0,115,36,0,0,0,116,0,160,1,116,2,106,3,124,1, - 161,2,125,2,116,0,160,4,100,1,124,1,106,5,124,0, - 106,6,161,3,1,0,124,2,83,0,41,2,122,38,67,114, - 101,97,116,101,32,97,110,32,117,110,105,116,105,97,108,105, - 122,101,100,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,122,38,101,120,116,101,110,115,105,111,110,32, - 109,111,100,117,108,101,32,123,33,114,125,32,108,111,97,100, - 101,100,32,102,114,111,109,32,123,33,114,125,41,7,114,159, - 0,0,0,114,242,0,0,0,114,187,0,0,0,90,14,99, - 114,101,97,116,101,95,100,121,110,97,109,105,99,114,173,0, - 0,0,114,141,0,0,0,114,65,0,0,0,41,3,114,143, - 0,0,0,114,210,0,0,0,114,244,0,0,0,114,7,0, - 0,0,114,7,0,0,0,114,8,0,0,0,114,239,0,0, - 0,150,4,0,0,115,14,0,0,0,4,2,6,1,4,255, - 6,2,8,1,4,255,4,2,122,33,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,46,99,114, - 101,97,116,101,95,109,111,100,117,108,101,99,2,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,5,0,0,0, - 67,0,0,0,115,36,0,0,0,116,0,160,1,116,2,106, - 3,124,1,161,2,1,0,116,0,160,4,100,1,124,0,106, - 5,124,0,106,6,161,3,1,0,100,2,83,0,41,3,122, - 30,73,110,105,116,105,97,108,105,122,101,32,97,110,32,101, - 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,122, - 40,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,32,123,33,114,125,32,101,120,101,99,117,116,101,100,32, - 102,114,111,109,32,123,33,114,125,78,41,7,114,159,0,0, - 0,114,242,0,0,0,114,187,0,0,0,90,12,101,120,101, - 99,95,100,121,110,97,109,105,99,114,173,0,0,0,114,141, - 0,0,0,114,65,0,0,0,169,2,114,143,0,0,0,114, - 244,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,245,0,0,0,158,4,0,0,115,8,0,0, - 0,14,2,6,1,8,1,8,255,122,31,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,101, - 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,3, - 0,0,0,115,36,0,0,0,116,0,124,0,106,1,131,1, - 100,1,25,0,137,0,116,2,135,0,102,1,100,2,100,3, - 132,8,116,3,68,0,131,1,131,1,83,0,41,4,122,49, - 82,101,116,117,114,110,32,84,114,117,101,32,105,102,32,116, - 104,101,32,101,120,116,101,110,115,105,111,110,32,109,111,100, - 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, - 46,114,3,0,0,0,99,1,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,4,0,0,0,51,0,0,0,115, - 28,0,0,0,129,0,124,0,93,9,125,1,136,0,100,0, - 124,1,23,0,107,2,86,0,1,0,113,2,100,1,83,0, - 41,2,114,236,0,0,0,78,114,7,0,0,0,169,2,114, - 5,0,0,0,218,6,115,117,102,102,105,120,169,1,90,9, - 102,105,108,101,95,110,97,109,101,114,7,0,0,0,114,8, - 0,0,0,114,9,0,0,0,167,4,0,0,115,8,0,0, - 0,2,128,4,0,2,1,20,255,122,49,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,105, - 115,95,112,97,99,107,97,103,101,46,60,108,111,99,97,108, - 115,62,46,60,103,101,110,101,120,112,114,62,41,4,114,74, - 0,0,0,114,65,0,0,0,218,3,97,110,121,114,232,0, - 0,0,114,247,0,0,0,114,7,0,0,0,114,45,1,0, - 0,114,8,0,0,0,114,206,0,0,0,164,4,0,0,115, - 8,0,0,0,14,2,12,1,2,1,8,255,122,30,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,0,67,0,0,0,115,24,0,0,0,116,0,124,1,131, + 1,125,4,124,0,106,1,124,2,124,3,124,4,100,1,141, + 3,83,0,41,2,78,169,1,218,5,95,109,111,100,101,41, + 2,114,139,0,0,0,114,253,0,0,0,41,5,114,143,0, + 0,0,114,134,0,0,0,114,132,0,0,0,114,41,0,0, + 0,114,78,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,254,0,0,0,70,4,0,0,115,4, + 0,0,0,8,2,16,1,122,32,83,111,117,114,99,101,70, + 105,108,101,76,111,97,100,101,114,46,95,99,97,99,104,101, + 95,98,121,116,101,99,111,100,101,114,87,0,0,0,114,36, + 1,0,0,99,3,0,0,0,0,0,0,0,1,0,0,0, + 9,0,0,0,11,0,0,0,67,0,0,0,115,254,0,0, + 0,116,0,124,1,131,1,92,2,125,4,125,5,103,0,125, + 6,124,4,114,31,116,1,124,4,131,1,115,31,116,0,124, + 4,131,1,92,2,125,4,125,7,124,6,160,2,124,7,161, + 1,1,0,124,4,114,31,116,1,124,4,131,1,114,14,116, + 3,124,6,131,1,68,0,93,49,125,7,116,4,124,4,124, + 7,131,2,125,4,122,7,116,5,160,6,124,4,161,1,1, + 0,87,0,113,35,4,0,116,7,121,58,1,0,1,0,1, + 0,89,0,113,35,4,0,116,8,121,84,1,0,125,8,1, + 0,122,15,116,9,160,10,100,1,124,4,124,8,161,3,1, + 0,87,0,89,0,100,2,125,8,126,8,1,0,100,2,83, + 0,100,2,125,8,126,8,119,1,119,0,122,15,116,11,124, + 1,124,2,124,3,131,3,1,0,116,9,160,10,100,3,124, + 1,161,2,1,0,87,0,100,2,83,0,4,0,116,8,121, + 126,1,0,125,8,1,0,122,14,116,9,160,10,100,1,124, + 1,124,8,161,3,1,0,87,0,89,0,100,2,125,8,126, + 8,100,2,83,0,100,2,125,8,126,8,119,1,119,0,41, + 4,122,27,87,114,105,116,101,32,98,121,116,101,115,32,100, + 97,116,97,32,116,111,32,97,32,102,105,108,101,46,122,27, + 99,111,117,108,100,32,110,111,116,32,99,114,101,97,116,101, + 32,123,33,114,125,58,32,123,33,114,125,78,122,12,99,114, + 101,97,116,101,100,32,123,33,114,125,41,12,114,74,0,0, + 0,114,83,0,0,0,114,61,0,0,0,218,8,114,101,118, + 101,114,115,101,100,114,67,0,0,0,114,18,0,0,0,90, + 5,109,107,100,105,114,218,15,70,105,108,101,69,120,105,115, + 116,115,69,114,114,111,114,114,76,0,0,0,114,159,0,0, + 0,114,173,0,0,0,114,95,0,0,0,41,9,114,143,0, + 0,0,114,65,0,0,0,114,41,0,0,0,114,37,1,0, + 0,218,6,112,97,114,101,110,116,114,120,0,0,0,114,63, + 0,0,0,114,68,0,0,0,114,0,1,0,0,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,253,0,0, + 0,75,4,0,0,115,56,0,0,0,12,2,4,1,12,2, + 12,1,10,1,12,254,12,4,10,1,2,1,14,1,12,1, + 4,2,14,1,6,3,4,1,4,255,16,2,8,128,2,251, + 2,6,12,1,18,1,14,1,8,2,2,1,18,255,8,128, + 2,254,122,25,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,46,115,101,116,95,100,97,116,97,78,41,7, + 114,150,0,0,0,114,149,0,0,0,114,151,0,0,0,114, + 152,0,0,0,114,252,0,0,0,114,254,0,0,0,114,253, + 0,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,34,1,0,0,61,4,0,0, + 115,10,0,0,0,8,0,4,2,8,2,8,5,18,5,114, + 34,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,64,0,0,0,115,32,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, + 83,0,41,7,218,20,83,111,117,114,99,101,108,101,115,115, + 70,105,108,101,76,111,97,100,101,114,122,45,76,111,97,100, + 101,114,32,119,104,105,99,104,32,104,97,110,100,108,101,115, + 32,115,111,117,114,99,101,108,101,115,115,32,102,105,108,101, + 32,105,109,112,111,114,116,115,46,99,2,0,0,0,0,0, + 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, + 0,0,115,68,0,0,0,124,0,160,0,124,1,161,1,125, + 2,124,0,160,1,124,2,161,1,125,3,124,1,124,2,100, + 1,156,2,125,4,116,2,124,3,124,1,124,4,131,3,1, + 0,116,3,116,4,124,3,131,1,100,2,100,0,133,2,25, + 0,124,1,124,2,100,3,141,3,83,0,41,4,78,114,183, + 0,0,0,114,169,0,0,0,41,2,114,141,0,0,0,114, + 132,0,0,0,41,5,114,203,0,0,0,114,255,0,0,0, + 114,176,0,0,0,114,189,0,0,0,114,7,1,0,0,41, + 5,114,143,0,0,0,114,163,0,0,0,114,65,0,0,0, + 114,41,0,0,0,114,175,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,114,241,0,0,0,110,4, + 0,0,115,22,0,0,0,10,1,10,1,2,4,2,1,6, + 254,12,4,2,1,14,1,2,1,2,1,6,253,122,29,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0, - 0,67,0,0,0,114,23,0,0,0,41,2,122,63,82,101, - 116,117,114,110,32,78,111,110,101,32,97,115,32,97,110,32, + 0,67,0,0,0,114,23,0,0,0,41,2,122,39,82,101, + 116,117,114,110,32,78,111,110,101,32,97,115,32,116,104,101, + 114,101,32,105,115,32,110,111,32,115,111,117,114,99,101,32, + 99,111,100,101,46,78,114,7,0,0,0,114,247,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, + 1,1,0,0,126,4,0,0,114,24,0,0,0,122,31,83, + 111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,115,111,117,114,99,101,78,41, + 6,114,150,0,0,0,114,149,0,0,0,114,151,0,0,0, + 114,152,0,0,0,114,241,0,0,0,114,1,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,41,1,0,0,106,4,0,0,115,8,0,0, + 0,8,0,4,2,8,2,12,16,114,41,1,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,64,0,0,0,115,92,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, + 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, + 100,8,100,9,132,0,90,7,100,10,100,11,132,0,90,8, + 100,12,100,13,132,0,90,9,100,14,100,15,132,0,90,10, + 100,16,100,17,132,0,90,11,101,12,100,18,100,19,132,0, + 131,1,90,13,100,20,83,0,41,21,114,30,1,0,0,122, + 93,76,111,97,100,101,114,32,102,111,114,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,115,46,10,10, + 32,32,32,32,84,104,101,32,99,111,110,115,116,114,117,99, + 116,111,114,32,105,115,32,100,101,115,105,103,110,101,100,32, + 116,111,32,119,111,114,107,32,119,105,116,104,32,70,105,108, + 101,70,105,110,100,101,114,46,10,10,32,32,32,32,99,3, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, + 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, + 95,0,124,2,124,0,95,1,100,0,83,0,114,69,0,0, + 0,114,183,0,0,0,41,3,114,143,0,0,0,114,141,0, + 0,0,114,65,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,236,0,0,0,139,4,0,0,115, + 4,0,0,0,6,1,10,1,122,28,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,95,95, + 105,110,105,116,95,95,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,114, + 12,1,0,0,114,69,0,0,0,114,13,1,0,0,114,15, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,16,1,0,0,143,4,0,0,114,17,1,0,0, + 122,26,69,120,116,101,110,115,105,111,110,70,105,108,101,76, + 111,97,100,101,114,46,95,95,101,113,95,95,99,1,0,0, + 0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0, + 0,67,0,0,0,114,18,1,0,0,114,69,0,0,0,114, + 19,1,0,0,114,21,1,0,0,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,114,22,1,0,0,147,4,0, + 0,114,23,1,0,0,122,28,69,120,116,101,110,115,105,111, + 110,70,105,108,101,76,111,97,100,101,114,46,95,95,104,97, + 115,104,95,95,99,2,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,5,0,0,0,67,0,0,0,115,36,0, + 0,0,116,0,160,1,116,2,106,3,124,1,161,2,125,2, + 116,0,160,4,100,1,124,1,106,5,124,0,106,6,161,3, + 1,0,124,2,83,0,41,2,122,38,67,114,101,97,116,101, + 32,97,110,32,117,110,105,116,105,97,108,105,122,101,100,32, 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 32,99,97,110,110,111,116,32,99,114,101,97,116,101,32,97, - 32,99,111,100,101,32,111,98,106,101,99,116,46,78,114,7, - 0,0,0,114,247,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,241,0,0,0,170,4,0,0, - 114,24,0,0,0,122,28,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,99, - 111,100,101,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,114,23,0,0, - 0,41,2,122,53,82,101,116,117,114,110,32,78,111,110,101, - 32,97,115,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,115,32,104,97,118,101,32,110,111,32,115,111, - 117,114,99,101,32,99,111,100,101,46,78,114,7,0,0,0, - 114,247,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,1,1,0,0,174,4,0,0,114,24,0, - 0,0,122,30,69,120,116,101,110,115,105,111,110,70,105,108, - 101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114, - 99,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,114,26,1,0,0, - 114,27,1,0,0,114,71,0,0,0,114,247,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,203, - 0,0,0,178,4,0,0,114,28,1,0,0,122,32,69,120, - 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, - 114,46,103,101,116,95,102,105,108,101,110,97,109,101,78,41, - 14,114,150,0,0,0,114,149,0,0,0,114,151,0,0,0, - 114,152,0,0,0,114,236,0,0,0,114,16,1,0,0,114, - 22,1,0,0,114,239,0,0,0,114,245,0,0,0,114,206, - 0,0,0,114,241,0,0,0,114,1,1,0,0,114,160,0, - 0,0,114,203,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,30,1,0,0, - 131,4,0,0,115,24,0,0,0,8,0,4,2,8,6,8, - 4,8,4,8,3,8,8,8,6,8,6,8,4,2,4,14, - 1,114,30,1,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, - 108,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,90,4,100,3,100,4,132,0,90,5,100,5,100,6, - 132,0,90,6,100,7,100,8,132,0,90,7,100,9,100,10, - 132,0,90,8,100,11,100,12,132,0,90,9,100,13,100,14, - 132,0,90,10,100,15,100,16,132,0,90,11,100,17,100,18, - 132,0,90,12,100,19,100,20,132,0,90,13,100,21,100,22, - 132,0,90,14,100,23,100,24,132,0,90,15,100,25,83,0, - 41,26,218,14,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,97,38,1,0,0,82,101,112,114,101,115,101,110,116, - 115,32,97,32,110,97,109,101,115,112,97,99,101,32,112,97, - 99,107,97,103,101,39,115,32,112,97,116,104,46,32,32,73, - 116,32,117,115,101,115,32,116,104,101,32,109,111,100,117,108, - 101,32,110,97,109,101,10,32,32,32,32,116,111,32,102,105, - 110,100,32,105,116,115,32,112,97,114,101,110,116,32,109,111, - 100,117,108,101,44,32,97,110,100,32,102,114,111,109,32,116, - 104,101,114,101,32,105,116,32,108,111,111,107,115,32,117,112, - 32,116,104,101,32,112,97,114,101,110,116,39,115,10,32,32, - 32,32,95,95,112,97,116,104,95,95,46,32,32,87,104,101, - 110,32,116,104,105,115,32,99,104,97,110,103,101,115,44,32, - 116,104,101,32,109,111,100,117,108,101,39,115,32,111,119,110, - 32,112,97,116,104,32,105,115,32,114,101,99,111,109,112,117, - 116,101,100,44,10,32,32,32,32,117,115,105,110,103,32,112, - 97,116,104,95,102,105,110,100,101,114,46,32,32,70,111,114, - 32,116,111,112,45,108,101,118,101,108,32,109,111,100,117,108, - 101,115,44,32,116,104,101,32,112,97,114,101,110,116,32,109, - 111,100,117,108,101,39,115,32,112,97,116,104,10,32,32,32, - 32,105,115,32,115,121,115,46,112,97,116,104,46,114,0,0, - 0,0,99,4,0,0,0,0,0,0,0,0,0,0,0,4, - 0,0,0,3,0,0,0,67,0,0,0,115,44,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,116,2,124,0, - 160,3,161,0,131,1,124,0,95,4,124,0,106,5,124,0, - 95,6,124,3,124,0,95,7,100,0,83,0,114,69,0,0, - 0,41,8,218,5,95,110,97,109,101,218,5,95,112,97,116, - 104,114,136,0,0,0,218,16,95,103,101,116,95,112,97,114, - 101,110,116,95,112,97,116,104,218,17,95,108,97,115,116,95, - 112,97,114,101,110,116,95,112,97,116,104,218,6,95,101,112, - 111,99,104,218,11,95,108,97,115,116,95,101,112,111,99,104, - 218,12,95,112,97,116,104,95,102,105,110,100,101,114,169,4, - 114,143,0,0,0,114,141,0,0,0,114,65,0,0,0,90, - 11,112,97,116,104,95,102,105,110,100,101,114,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,114,236,0,0,0, - 195,4,0,0,115,10,0,0,0,6,1,6,1,14,1,8, - 1,10,1,122,23,95,78,97,109,101,115,112,97,99,101,80, - 97,116,104,46,95,95,105,110,105,116,95,95,99,1,0,0, - 0,0,0,0,0,0,0,0,0,4,0,0,0,3,0,0, - 0,67,0,0,0,115,38,0,0,0,124,0,106,0,160,1, - 100,1,161,1,92,3,125,1,125,2,125,3,124,2,100,2, - 107,2,114,15,100,3,83,0,124,1,100,4,102,2,83,0, - 41,5,122,62,82,101,116,117,114,110,115,32,97,32,116,117, - 112,108,101,32,111,102,32,40,112,97,114,101,110,116,45,109, - 111,100,117,108,101,45,110,97,109,101,44,32,112,97,114,101, - 110,116,45,112,97,116,104,45,97,116,116,114,45,110,97,109, - 101,41,114,97,0,0,0,114,10,0,0,0,41,2,114,15, - 0,0,0,114,65,0,0,0,90,8,95,95,112,97,116,104, - 95,95,41,2,114,48,1,0,0,114,104,0,0,0,41,4, - 114,143,0,0,0,114,40,1,0,0,218,3,100,111,116,90, - 2,109,101,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,218,23,95,102,105,110,100,95,112,97,114,101,110,116, - 95,112,97,116,104,95,110,97,109,101,115,202,4,0,0,115, - 8,0,0,0,18,2,8,1,4,2,8,3,122,38,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,46,95,102,105, - 110,100,95,112,97,114,101,110,116,95,112,97,116,104,95,110, - 97,109,101,115,99,1,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,28,0, - 0,0,124,0,160,0,161,0,92,2,125,1,125,2,116,1, - 116,2,106,3,124,1,25,0,124,2,131,2,83,0,114,69, - 0,0,0,41,4,114,57,1,0,0,114,155,0,0,0,114, - 15,0,0,0,218,7,109,111,100,117,108,101,115,41,3,114, - 143,0,0,0,90,18,112,97,114,101,110,116,95,109,111,100, - 117,108,101,95,110,97,109,101,90,14,112,97,116,104,95,97, - 116,116,114,95,110,97,109,101,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,50,1,0,0,212,4,0,0, - 115,4,0,0,0,12,1,16,1,122,31,95,78,97,109,101, - 115,112,97,99,101,80,97,116,104,46,95,103,101,116,95,112, - 97,114,101,110,116,95,112,97,116,104,99,1,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,67, - 0,0,0,115,100,0,0,0,116,0,124,0,160,1,161,0, - 131,1,125,1,124,1,124,0,106,2,107,3,115,17,124,0, - 106,3,124,0,106,4,107,3,114,47,124,0,160,5,124,0, - 106,6,124,1,161,2,125,2,124,2,100,0,117,1,114,40, - 124,2,106,7,100,0,117,0,114,40,124,2,106,8,114,40, - 124,2,106,8,124,0,95,9,124,1,124,0,95,2,124,0, - 106,3,124,0,95,4,124,0,106,9,83,0,114,69,0,0, - 0,41,10,114,136,0,0,0,114,50,1,0,0,114,51,1, - 0,0,114,52,1,0,0,114,53,1,0,0,114,54,1,0, - 0,114,48,1,0,0,114,164,0,0,0,114,202,0,0,0, - 114,49,1,0,0,41,3,114,143,0,0,0,90,11,112,97, - 114,101,110,116,95,112,97,116,104,114,210,0,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,218,12,95, - 114,101,99,97,108,99,117,108,97,116,101,216,4,0,0,115, - 18,0,0,0,12,2,22,1,14,1,18,3,6,1,8,1, - 6,1,8,1,6,1,122,27,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,114,101,99,97,108,99,117,108, - 97,116,101,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,243,12,0,0, - 0,116,0,124,0,160,1,161,0,131,1,83,0,114,69,0, - 0,0,41,2,218,4,105,116,101,114,114,59,1,0,0,114, - 21,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,218,8,95,95,105,116,101,114,95,95,230,4,0, - 0,243,2,0,0,0,12,1,122,23,95,78,97,109,101,115, - 112,97,99,101,80,97,116,104,46,95,95,105,116,101,114,95, - 95,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,2,0,0,0,67,0,0,0,115,12,0,0,0,124, - 0,160,0,161,0,124,1,25,0,83,0,114,69,0,0,0, - 169,1,114,59,1,0,0,41,2,114,143,0,0,0,218,5, - 105,110,100,101,120,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,218,11,95,95,103,101,116,105,116,101,109,95, - 95,233,4,0,0,114,63,1,0,0,122,26,95,78,97,109, - 101,115,112,97,99,101,80,97,116,104,46,95,95,103,101,116, - 105,116,101,109,95,95,99,3,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,3,0,0,0,67,0,0,0,115, - 14,0,0,0,124,2,124,0,106,0,124,1,60,0,100,0, - 83,0,114,69,0,0,0,41,1,114,49,1,0,0,41,3, - 114,143,0,0,0,114,65,1,0,0,114,65,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,11, - 95,95,115,101,116,105,116,101,109,95,95,236,4,0,0,115, - 2,0,0,0,14,1,122,26,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,95,115,101,116,105,116,101,109, - 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,114,60,1,0,0, - 114,69,0,0,0,41,2,114,4,0,0,0,114,59,1,0, - 0,114,21,1,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,7,95,95,108,101,110,95,95,239,4, - 0,0,114,63,1,0,0,122,22,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,46,95,95,108,101,110,95,95,99, + 122,38,101,120,116,101,110,115,105,111,110,32,109,111,100,117, + 108,101,32,123,33,114,125,32,108,111,97,100,101,100,32,102, + 114,111,109,32,123,33,114,125,41,7,114,159,0,0,0,114, + 242,0,0,0,114,187,0,0,0,90,14,99,114,101,97,116, + 101,95,100,121,110,97,109,105,99,114,173,0,0,0,114,141, + 0,0,0,114,65,0,0,0,41,3,114,143,0,0,0,114, + 210,0,0,0,114,244,0,0,0,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,114,239,0,0,0,150,4,0, + 0,115,14,0,0,0,4,2,6,1,4,255,6,2,8,1, + 4,255,4,2,122,33,69,120,116,101,110,115,105,111,110,70, + 105,108,101,76,111,97,100,101,114,46,99,114,101,97,116,101, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 0,0,0,0,2,0,0,0,5,0,0,0,67,0,0,0, + 115,36,0,0,0,116,0,160,1,116,2,106,3,124,1,161, + 2,1,0,116,0,160,4,100,1,124,0,106,5,124,0,106, + 6,161,3,1,0,100,2,83,0,41,3,122,30,73,110,105, + 116,105,97,108,105,122,101,32,97,110,32,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,122,40,101,120,116, + 101,110,115,105,111,110,32,109,111,100,117,108,101,32,123,33, + 114,125,32,101,120,101,99,117,116,101,100,32,102,114,111,109, + 32,123,33,114,125,78,41,7,114,159,0,0,0,114,242,0, + 0,0,114,187,0,0,0,90,12,101,120,101,99,95,100,121, + 110,97,109,105,99,114,173,0,0,0,114,141,0,0,0,114, + 65,0,0,0,169,2,114,143,0,0,0,114,244,0,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, + 245,0,0,0,158,4,0,0,115,8,0,0,0,14,2,6, + 1,8,1,8,255,122,31,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,101,120,101,99,95, + 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,3,0,0,0,115, + 36,0,0,0,116,0,124,0,106,1,131,1,100,1,25,0, + 137,0,116,2,135,0,102,1,100,2,100,3,132,8,116,3, + 68,0,131,1,131,1,83,0,41,4,122,49,82,101,116,117, + 114,110,32,84,114,117,101,32,105,102,32,116,104,101,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, + 105,115,32,97,32,112,97,99,107,97,103,101,46,114,3,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,4,0,0,0,51,0,0,0,115,28,0,0,0, + 129,0,124,0,93,9,125,1,136,0,100,0,124,1,23,0, + 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,236, + 0,0,0,78,114,7,0,0,0,169,2,114,5,0,0,0, + 218,6,115,117,102,102,105,120,169,1,90,9,102,105,108,101, + 95,110,97,109,101,114,7,0,0,0,114,8,0,0,0,114, + 9,0,0,0,167,4,0,0,115,8,0,0,0,2,128,4, + 0,2,1,20,255,122,49,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,105,115,95,112,97, + 99,107,97,103,101,46,60,108,111,99,97,108,115,62,46,60, + 103,101,110,101,120,112,114,62,41,4,114,74,0,0,0,114, + 65,0,0,0,218,3,97,110,121,114,232,0,0,0,114,247, + 0,0,0,114,7,0,0,0,114,45,1,0,0,114,8,0, + 0,0,114,206,0,0,0,164,4,0,0,115,8,0,0,0, + 14,2,12,1,2,1,8,255,122,30,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,105,115, + 95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,114,23,0,0,0,41,2,122,63,82,101,116,117,114,110, + 32,78,111,110,101,32,97,115,32,97,110,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,32,99,97,110, + 110,111,116,32,99,114,101,97,116,101,32,97,32,99,111,100, + 101,32,111,98,106,101,99,116,46,78,114,7,0,0,0,114, + 247,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,241,0,0,0,170,4,0,0,114,24,0,0, + 0,122,28,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,114,23,0,0,0,41,2,122, + 53,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 115,32,104,97,118,101,32,110,111,32,115,111,117,114,99,101, + 32,99,111,100,101,46,78,114,7,0,0,0,114,247,0,0, + 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, + 114,1,1,0,0,174,4,0,0,114,24,0,0,0,122,30, + 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, + 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,114,26,1,0,0,114,27,1,0, + 0,114,71,0,0,0,114,247,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,203,0,0,0,178, + 4,0,0,114,28,1,0,0,122,32,69,120,116,101,110,115, + 105,111,110,70,105,108,101,76,111,97,100,101,114,46,103,101, + 116,95,102,105,108,101,110,97,109,101,78,41,14,114,150,0, + 0,0,114,149,0,0,0,114,151,0,0,0,114,152,0,0, + 0,114,236,0,0,0,114,16,1,0,0,114,22,1,0,0, + 114,239,0,0,0,114,245,0,0,0,114,206,0,0,0,114, + 241,0,0,0,114,1,1,0,0,114,160,0,0,0,114,203, + 0,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,30,1,0,0,131,4,0,0, + 115,24,0,0,0,8,0,4,2,8,6,8,4,8,4,8, + 3,8,8,8,6,8,6,8,4,2,4,14,1,114,30,1, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,64,0,0,0,115,108,0,0,0, + 101,0,90,1,100,0,90,2,100,1,90,3,100,2,90,4, + 100,3,100,4,132,0,90,5,100,5,100,6,132,0,90,6, + 100,7,100,8,132,0,90,7,100,9,100,10,132,0,90,8, + 100,11,100,12,132,0,90,9,100,13,100,14,132,0,90,10, + 100,15,100,16,132,0,90,11,100,17,100,18,132,0,90,12, + 100,19,100,20,132,0,90,13,100,21,100,22,132,0,90,14, + 100,23,100,24,132,0,90,15,100,25,83,0,41,26,218,14, + 95,78,97,109,101,115,112,97,99,101,80,97,116,104,97,38, + 1,0,0,82,101,112,114,101,115,101,110,116,115,32,97,32, + 110,97,109,101,115,112,97,99,101,32,112,97,99,107,97,103, + 101,39,115,32,112,97,116,104,46,32,32,73,116,32,117,115, + 101,115,32,116,104,101,32,109,111,100,117,108,101,32,110,97, + 109,101,10,32,32,32,32,116,111,32,102,105,110,100,32,105, + 116,115,32,112,97,114,101,110,116,32,109,111,100,117,108,101, + 44,32,97,110,100,32,102,114,111,109,32,116,104,101,114,101, + 32,105,116,32,108,111,111,107,115,32,117,112,32,116,104,101, + 32,112,97,114,101,110,116,39,115,10,32,32,32,32,95,95, + 112,97,116,104,95,95,46,32,32,87,104,101,110,32,116,104, + 105,115,32,99,104,97,110,103,101,115,44,32,116,104,101,32, + 109,111,100,117,108,101,39,115,32,111,119,110,32,112,97,116, + 104,32,105,115,32,114,101,99,111,109,112,117,116,101,100,44, + 10,32,32,32,32,117,115,105,110,103,32,112,97,116,104,95, + 102,105,110,100,101,114,46,32,32,70,111,114,32,116,111,112, + 45,108,101,118,101,108,32,109,111,100,117,108,101,115,44,32, + 116,104,101,32,112,97,114,101,110,116,32,109,111,100,117,108, + 101,39,115,32,112,97,116,104,10,32,32,32,32,105,115,32, + 115,121,115,46,112,97,116,104,46,114,0,0,0,0,99,4, + 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,3, + 0,0,0,67,0,0,0,115,44,0,0,0,124,1,124,0, + 95,0,124,2,124,0,95,1,116,2,124,0,160,3,161,0, + 131,1,124,0,95,4,124,0,106,5,124,0,95,6,124,3, + 124,0,95,7,100,0,83,0,114,69,0,0,0,41,8,218, + 5,95,110,97,109,101,218,5,95,112,97,116,104,114,136,0, + 0,0,218,16,95,103,101,116,95,112,97,114,101,110,116,95, + 112,97,116,104,218,17,95,108,97,115,116,95,112,97,114,101, + 110,116,95,112,97,116,104,218,6,95,101,112,111,99,104,218, + 11,95,108,97,115,116,95,101,112,111,99,104,218,12,95,112, + 97,116,104,95,102,105,110,100,101,114,169,4,114,143,0,0, + 0,114,141,0,0,0,114,65,0,0,0,90,11,112,97,116, + 104,95,102,105,110,100,101,114,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,114,236,0,0,0,195,4,0,0, + 115,10,0,0,0,6,1,6,1,14,1,8,1,10,1,122, + 23,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, + 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,3,0,0,0,67,0,0, + 0,115,38,0,0,0,124,0,106,0,160,1,100,1,161,1, + 92,3,125,1,125,2,125,3,124,2,100,2,107,2,114,15, + 100,3,83,0,124,1,100,4,102,2,83,0,41,5,122,62, + 82,101,116,117,114,110,115,32,97,32,116,117,112,108,101,32, + 111,102,32,40,112,97,114,101,110,116,45,109,111,100,117,108, + 101,45,110,97,109,101,44,32,112,97,114,101,110,116,45,112, + 97,116,104,45,97,116,116,114,45,110,97,109,101,41,114,97, + 0,0,0,114,10,0,0,0,41,2,114,15,0,0,0,114, + 65,0,0,0,90,8,95,95,112,97,116,104,95,95,41,2, + 114,48,1,0,0,114,104,0,0,0,41,4,114,143,0,0, + 0,114,40,1,0,0,218,3,100,111,116,90,2,109,101,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,23, + 95,102,105,110,100,95,112,97,114,101,110,116,95,112,97,116, + 104,95,110,97,109,101,115,202,4,0,0,115,8,0,0,0, + 18,2,8,1,4,2,8,3,122,38,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,46,95,102,105,110,100,95,112, + 97,114,101,110,116,95,112,97,116,104,95,110,97,109,101,115, + 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,28,0,0,0,124,0, + 160,0,161,0,92,2,125,1,125,2,116,1,116,2,106,3, + 124,1,25,0,124,2,131,2,83,0,114,69,0,0,0,41, + 4,114,57,1,0,0,114,155,0,0,0,114,15,0,0,0, + 218,7,109,111,100,117,108,101,115,41,3,114,143,0,0,0, + 90,18,112,97,114,101,110,116,95,109,111,100,117,108,101,95, + 110,97,109,101,90,14,112,97,116,104,95,97,116,116,114,95, + 110,97,109,101,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,50,1,0,0,212,4,0,0,115,4,0,0, + 0,12,1,16,1,122,31,95,78,97,109,101,115,112,97,99, + 101,80,97,116,104,46,95,103,101,116,95,112,97,114,101,110, + 116,95,112,97,116,104,99,1,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, + 100,0,0,0,116,0,124,0,160,1,161,0,131,1,125,1, + 124,1,124,0,106,2,107,3,115,17,124,0,106,3,124,0, + 106,4,107,3,114,47,124,0,160,5,124,0,106,6,124,1, + 161,2,125,2,124,2,100,0,117,1,114,40,124,2,106,7, + 100,0,117,0,114,40,124,2,106,8,114,40,124,2,106,8, + 124,0,95,9,124,1,124,0,95,2,124,0,106,3,124,0, + 95,4,124,0,106,9,83,0,114,69,0,0,0,41,10,114, + 136,0,0,0,114,50,1,0,0,114,51,1,0,0,114,52, + 1,0,0,114,53,1,0,0,114,54,1,0,0,114,48,1, + 0,0,114,164,0,0,0,114,202,0,0,0,114,49,1,0, + 0,41,3,114,143,0,0,0,90,11,112,97,114,101,110,116, + 95,112,97,116,104,114,210,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,218,12,95,114,101,99,97, + 108,99,117,108,97,116,101,216,4,0,0,115,18,0,0,0, + 12,2,22,1,14,1,18,3,6,1,8,1,6,1,8,1, + 6,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,114,101,99,97,108,99,117,108,97,116,101,99, 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,243,12,0,0,0,100,1,160, - 0,124,0,106,1,161,1,83,0,41,2,78,122,20,95,78, - 97,109,101,115,112,97,99,101,80,97,116,104,40,123,33,114, - 125,41,41,2,114,89,0,0,0,114,49,1,0,0,114,21, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,218,8,95,95,114,101,112,114,95,95,242,4,0,0, - 114,63,1,0,0,122,23,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,95,95,114,101,112,114,95,95,99,2, + 3,0,0,0,67,0,0,0,243,12,0,0,0,116,0,124, + 0,160,1,161,0,131,1,83,0,114,69,0,0,0,41,2, + 218,4,105,116,101,114,114,59,1,0,0,114,21,1,0,0, + 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, + 8,95,95,105,116,101,114,95,95,230,4,0,0,243,2,0, + 0,0,12,1,122,23,95,78,97,109,101,115,112,97,99,101, + 80,97,116,104,46,95,95,105,116,101,114,95,95,99,2,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0, + 0,0,67,0,0,0,115,12,0,0,0,124,0,160,0,161, + 0,124,1,25,0,83,0,114,69,0,0,0,169,1,114,59, + 1,0,0,41,2,114,143,0,0,0,218,5,105,110,100,101, + 120,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, + 218,11,95,95,103,101,116,105,116,101,109,95,95,233,4,0, + 0,114,63,1,0,0,122,26,95,78,97,109,101,115,112,97, + 99,101,80,97,116,104,46,95,95,103,101,116,105,116,101,109, + 95,95,99,3,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,3,0,0,0,67,0,0,0,115,14,0,0,0, + 124,2,124,0,106,0,124,1,60,0,100,0,83,0,114,69, + 0,0,0,41,1,114,49,1,0,0,41,3,114,143,0,0, + 0,114,65,1,0,0,114,65,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,11,95,95,115,101, + 116,105,116,101,109,95,95,236,4,0,0,115,2,0,0,0, + 14,1,122,26,95,78,97,109,101,115,112,97,99,101,80,97, + 116,104,46,95,95,115,101,116,105,116,101,109,95,95,99,1, + 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3, + 0,0,0,67,0,0,0,114,60,1,0,0,114,69,0,0, + 0,41,2,114,4,0,0,0,114,59,1,0,0,114,21,1, + 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, + 0,218,7,95,95,108,101,110,95,95,239,4,0,0,114,63, + 1,0,0,122,22,95,78,97,109,101,115,112,97,99,101,80, + 97,116,104,46,95,95,108,101,110,95,95,99,1,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,243,12,0,0,0,100,1,160,0,124,0,106, + 1,161,1,83,0,41,2,78,122,20,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,40,123,33,114,125,41,41,2, + 114,89,0,0,0,114,49,1,0,0,114,21,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,8, + 95,95,114,101,112,114,95,95,242,4,0,0,114,63,1,0, + 0,122,23,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,95,114,101,112,114,95,95,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,124,1,124,0,160,0,161,0, + 118,0,83,0,114,69,0,0,0,114,64,1,0,0,169,2, + 114,143,0,0,0,218,4,105,116,101,109,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,218,12,95,95,99,111, + 110,116,97,105,110,115,95,95,245,4,0,0,114,63,1,0, + 0,122,27,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,95,99,111,110,116,97,105,110,115,95,95,99,2, 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,67,0,0,0,115,12,0,0,0,124,1,124,0, - 160,0,161,0,118,0,83,0,114,69,0,0,0,114,64,1, - 0,0,169,2,114,143,0,0,0,218,4,105,116,101,109,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,12, - 95,95,99,111,110,116,97,105,110,115,95,95,245,4,0,0, - 114,63,1,0,0,122,27,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,95,95,99,111,110,116,97,105,110,115, - 95,95,99,2,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,3,0,0,0,67,0,0,0,115,16,0,0,0, - 124,0,106,0,160,1,124,1,161,1,1,0,100,0,83,0, - 114,69,0,0,0,41,2,114,49,1,0,0,114,61,0,0, - 0,114,71,1,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,61,0,0,0,248,4,0,0,243,2, - 0,0,0,16,1,122,21,95,78,97,109,101,115,112,97,99, - 101,80,97,116,104,46,97,112,112,101,110,100,78,41,16,114, - 150,0,0,0,114,149,0,0,0,114,151,0,0,0,114,152, - 0,0,0,114,52,1,0,0,114,236,0,0,0,114,57,1, - 0,0,114,50,1,0,0,114,59,1,0,0,114,62,1,0, - 0,114,66,1,0,0,114,67,1,0,0,114,68,1,0,0, - 114,70,1,0,0,114,73,1,0,0,114,61,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,47,1,0,0,184,4,0,0,115,28,0,0, - 0,8,0,4,1,4,8,8,2,8,7,8,10,8,4,8, - 14,8,3,8,3,8,3,8,3,8,3,12,3,114,47,1, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,64,0,0,0,115,88,0,0,0, - 101,0,90,1,100,0,90,2,100,1,100,2,132,0,90,3, - 101,4,100,3,100,4,132,0,131,1,90,5,100,5,100,6, - 132,0,90,6,100,7,100,8,132,0,90,7,100,9,100,10, - 132,0,90,8,100,11,100,12,132,0,90,9,100,13,100,14, - 132,0,90,10,100,15,100,16,132,0,90,11,100,17,100,18, - 132,0,90,12,100,19,83,0,41,20,218,16,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,99,4,0,0, - 0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0, - 0,67,0,0,0,115,18,0,0,0,116,0,124,1,124,2, - 124,3,131,3,124,0,95,1,100,0,83,0,114,69,0,0, - 0,41,2,114,47,1,0,0,114,49,1,0,0,114,55,1, + 0,0,0,67,0,0,0,115,16,0,0,0,124,0,106,0, + 160,1,124,1,161,1,1,0,100,0,83,0,114,69,0,0, + 0,41,2,114,49,1,0,0,114,61,0,0,0,114,71,1, 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,236,0,0,0,254,4,0,0,115,2,0,0,0,18, - 1,122,25,95,78,97,109,101,115,112,97,99,101,76,111,97, - 100,101,114,46,95,95,105,110,105,116,95,95,99,1,0,0, - 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, - 0,67,0,0,0,115,24,0,0,0,116,0,160,1,100,1, - 116,2,161,2,1,0,100,2,160,3,124,0,106,4,161,1, - 83,0,41,3,122,115,82,101,116,117,114,110,32,114,101,112, - 114,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,109, - 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,32,32,84,104,101,32,105,109,112,111,114,116, - 32,109,97,99,104,105,110,101,114,121,32,100,111,101,115,32, - 116,104,101,32,106,111,98,32,105,116,115,101,108,102,46,10, - 10,32,32,32,32,32,32,32,32,122,82,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,109,111,100,117, - 108,101,95,114,101,112,114,40,41,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,32,97,110,100,32,115,108,97,116, - 101,100,32,102,111,114,32,114,101,109,111,118,97,108,32,105, - 110,32,80,121,116,104,111,110,32,51,46,49,50,122,25,60, - 109,111,100,117,108,101,32,123,33,114,125,32,40,110,97,109, - 101,115,112,97,99,101,41,62,41,5,114,99,0,0,0,114, - 100,0,0,0,114,101,0,0,0,114,89,0,0,0,114,150, - 0,0,0,41,1,114,244,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,218,11,109,111,100,117,108, - 101,95,114,101,112,114,1,5,0,0,115,8,0,0,0,6, - 7,2,1,4,255,12,2,122,28,95,78,97,109,101,115,112, - 97,99,101,76,111,97,100,101,114,46,109,111,100,117,108,101, - 95,114,101,112,114,99,2,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,114,23, - 0,0,0,41,2,78,84,114,7,0,0,0,114,247,0,0, - 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,206,0,0,0,12,5,0,0,243,2,0,0,0,4,1, - 122,27,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,114,23,0,0,0,41,2,78,114,10, - 0,0,0,114,7,0,0,0,114,247,0,0,0,114,7,0, - 0,0,114,7,0,0,0,114,8,0,0,0,114,1,1,0, - 0,15,5,0,0,114,77,1,0,0,122,27,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,46,103,101,116, - 95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,6,0,0,0,67,0,0,0, - 115,16,0,0,0,116,0,100,1,100,2,100,3,100,4,100, - 5,141,4,83,0,41,6,78,114,10,0,0,0,122,8,60, - 115,116,114,105,110,103,62,114,243,0,0,0,84,41,1,114, - 3,1,0,0,41,1,114,4,1,0,0,114,247,0,0,0, + 0,114,61,0,0,0,248,4,0,0,243,2,0,0,0,16, + 1,122,21,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,97,112,112,101,110,100,78,41,16,114,150,0,0,0, + 114,149,0,0,0,114,151,0,0,0,114,152,0,0,0,114, + 52,1,0,0,114,236,0,0,0,114,57,1,0,0,114,50, + 1,0,0,114,59,1,0,0,114,62,1,0,0,114,66,1, + 0,0,114,67,1,0,0,114,68,1,0,0,114,70,1,0, + 0,114,73,1,0,0,114,61,0,0,0,114,7,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 241,0,0,0,18,5,0,0,114,74,1,0,0,122,25,95, + 47,1,0,0,184,4,0,0,115,28,0,0,0,8,0,4, + 1,4,8,8,2,8,7,8,10,8,4,8,14,8,3,8, + 3,8,3,8,3,8,3,12,3,114,47,1,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,64,0,0,0,115,88,0,0,0,101,0,90,1, + 100,0,90,2,100,1,100,2,132,0,90,3,101,4,100,3, + 100,4,132,0,131,1,90,5,100,5,100,6,132,0,90,6, + 100,7,100,8,132,0,90,7,100,9,100,10,132,0,90,8, + 100,11,100,12,132,0,90,9,100,13,100,14,132,0,90,10, + 100,15,100,16,132,0,90,11,100,17,100,18,132,0,90,12, + 100,19,83,0,41,20,218,16,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,99,4,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, + 0,115,18,0,0,0,116,0,124,1,124,2,124,3,131,3, + 124,0,95,1,100,0,83,0,114,69,0,0,0,41,2,114, + 47,1,0,0,114,49,1,0,0,114,55,1,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,236,0, + 0,0,254,4,0,0,115,2,0,0,0,18,1,122,25,95, 78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46, - 103,101,116,95,99,111,100,101,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,114,23,0,0,0,114,237,0,0,0,114,7,0,0,0, - 114,238,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,239,0,0,0,21,5,0,0,114,240,0, - 0,0,122,30,95,78,97,109,101,115,112,97,99,101,76,111, - 97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,0, - 100,0,83,0,114,69,0,0,0,114,7,0,0,0,114,42, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,245,0,0,0,24,5,0,0,114,77,1,0,0, - 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,4, - 0,0,0,67,0,0,0,115,26,0,0,0,116,0,160,1, - 100,1,124,0,106,2,161,2,1,0,116,0,160,3,124,0, - 124,1,161,2,83,0,41,2,122,98,76,111,97,100,32,97, - 32,110,97,109,101,115,112,97,99,101,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,122,38,110,97, - 109,101,115,112,97,99,101,32,109,111,100,117,108,101,32,108, - 111,97,100,101,100,32,119,105,116,104,32,112,97,116,104,32, - 123,33,114,125,41,4,114,159,0,0,0,114,173,0,0,0, - 114,49,1,0,0,114,246,0,0,0,114,247,0,0,0,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,248, - 0,0,0,27,5,0,0,115,8,0,0,0,6,7,4,1, - 4,255,12,3,122,28,95,78,97,109,101,115,112,97,99,101, - 76,111,97,100,101,114,46,108,111,97,100,95,109,111,100,117, - 108,101,99,2,0,0,0,0,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,22,0,0,0, - 100,1,100,2,108,0,109,1,125,2,1,0,124,2,124,0, - 106,2,131,1,83,0,41,3,78,114,0,0,0,0,41,1, - 218,15,78,97,109,101,115,112,97,99,101,82,101,97,100,101, - 114,41,3,114,32,1,0,0,114,78,1,0,0,114,49,1, - 0,0,41,3,114,143,0,0,0,114,244,0,0,0,114,78, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,33,1,0,0,39,5,0,0,115,4,0,0,0, - 12,1,10,1,122,36,95,78,97,109,101,115,112,97,99,101, - 76,111,97,100,101,114,46,103,101,116,95,114,101,115,111,117, - 114,99,101,95,114,101,97,100,101,114,78,41,13,114,150,0, - 0,0,114,149,0,0,0,114,151,0,0,0,114,236,0,0, - 0,114,233,0,0,0,114,76,1,0,0,114,206,0,0,0, - 114,1,1,0,0,114,241,0,0,0,114,239,0,0,0,114, - 245,0,0,0,114,248,0,0,0,114,33,1,0,0,114,7, - 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,75,1,0,0,253,4,0,0,115,22,0,0,0, - 8,0,8,1,2,3,10,1,8,10,8,3,8,3,8,3, - 8,3,8,3,12,12,114,75,1,0,0,99,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, - 64,0,0,0,115,118,0,0,0,101,0,90,1,100,0,90, - 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, - 5,101,4,100,4,100,5,132,0,131,1,90,6,101,7,100, - 6,100,7,132,0,131,1,90,8,101,7,100,8,100,9,132, - 0,131,1,90,9,101,7,100,19,100,11,100,12,132,1,131, - 1,90,10,101,7,100,20,100,13,100,14,132,1,131,1,90, - 11,101,7,100,19,100,15,100,16,132,1,131,1,90,12,101, - 4,100,17,100,18,132,0,131,1,90,13,100,10,83,0,41, - 21,218,10,80,97,116,104,70,105,110,100,101,114,122,62,77, - 101,116,97,32,112,97,116,104,32,102,105,110,100,101,114,32, - 102,111,114,32,115,121,115,46,112,97,116,104,32,97,110,100, - 32,112,97,99,107,97,103,101,32,95,95,112,97,116,104,95, - 95,32,97,116,116,114,105,98,117,116,101,115,46,99,0,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,67,0,0,0,115,78,0,0,0,116,0,116,1,106, - 2,160,3,161,0,131,1,68,0,93,22,92,2,125,0,125, - 1,124,1,100,1,117,0,114,20,116,1,106,2,124,0,61, - 0,113,7,116,4,124,1,100,2,131,2,114,29,124,1,160, - 5,161,0,1,0,113,7,116,6,4,0,106,7,100,3,55, - 0,2,0,95,7,100,1,83,0,41,4,122,125,67,97,108, - 108,32,116,104,101,32,105,110,118,97,108,105,100,97,116,101, - 95,99,97,99,104,101,115,40,41,32,109,101,116,104,111,100, - 32,111,110,32,97,108,108,32,112,97,116,104,32,101,110,116, - 114,121,32,102,105,110,100,101,114,115,10,32,32,32,32,32, - 32,32,32,115,116,111,114,101,100,32,105,110,32,115,121,115, - 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,115,32,40,119,104,101,114,101,32,105,109,112, - 108,101,109,101,110,116,101,100,41,46,78,218,17,105,110,118, - 97,108,105,100,97,116,101,95,99,97,99,104,101,115,114,3, - 0,0,0,41,8,218,4,108,105,115,116,114,15,0,0,0, - 218,19,112,97,116,104,95,105,109,112,111,114,116,101,114,95, - 99,97,99,104,101,218,5,105,116,101,109,115,114,153,0,0, - 0,114,80,1,0,0,114,47,1,0,0,114,52,1,0,0, - 41,2,114,141,0,0,0,218,6,102,105,110,100,101,114,114, - 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,80, - 1,0,0,50,5,0,0,115,14,0,0,0,22,4,8,1, - 10,1,10,1,8,1,2,128,18,3,122,28,80,97,116,104, - 70,105,110,100,101,114,46,105,110,118,97,108,105,100,97,116, - 101,95,99,97,99,104,101,115,99,1,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,9,0,0,0,67,0,0, - 0,115,76,0,0,0,116,0,106,1,100,1,117,1,114,14, - 116,0,106,1,115,14,116,2,160,3,100,2,116,4,161,2, - 1,0,116,0,106,1,68,0,93,18,125,1,122,7,124,1, - 124,0,131,1,87,0,2,0,1,0,83,0,4,0,116,5, - 121,35,1,0,1,0,1,0,89,0,113,17,119,0,100,1, - 83,0,41,3,122,46,83,101,97,114,99,104,32,115,121,115, - 46,112,97,116,104,95,104,111,111,107,115,32,102,111,114,32, - 97,32,102,105,110,100,101,114,32,102,111,114,32,39,112,97, - 116,104,39,46,78,122,23,115,121,115,46,112,97,116,104,95, - 104,111,111,107,115,32,105,115,32,101,109,112,116,121,41,6, - 114,15,0,0,0,218,10,112,97,116,104,95,104,111,111,107, - 115,114,99,0,0,0,114,100,0,0,0,114,162,0,0,0, - 114,142,0,0,0,41,2,114,65,0,0,0,90,4,104,111, - 111,107,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,11,95,112,97,116,104,95,104,111,111,107,115,63,5, - 0,0,115,18,0,0,0,16,3,12,1,10,1,2,1,14, - 1,12,1,4,1,2,255,4,3,122,22,80,97,116,104,70, - 105,110,100,101,114,46,95,112,97,116,104,95,104,111,111,107, - 115,99,2,0,0,0,0,0,0,0,0,0,0,0,3,0, - 0,0,8,0,0,0,67,0,0,0,115,100,0,0,0,124, - 1,100,1,107,2,114,21,122,6,116,0,160,1,161,0,125, - 1,87,0,110,10,4,0,116,2,121,20,1,0,1,0,1, - 0,89,0,100,2,83,0,119,0,122,8,116,3,106,4,124, - 1,25,0,125,2,87,0,124,2,83,0,4,0,116,5,121, - 49,1,0,1,0,1,0,124,0,160,6,124,1,161,1,125, - 2,124,2,116,3,106,4,124,1,60,0,89,0,124,2,83, - 0,119,0,41,3,122,210,71,101,116,32,116,104,101,32,102, - 105,110,100,101,114,32,102,111,114,32,116,104,101,32,112,97, - 116,104,32,101,110,116,114,121,32,102,114,111,109,32,115,121, - 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, - 99,97,99,104,101,46,10,10,32,32,32,32,32,32,32,32, - 73,102,32,116,104,101,32,112,97,116,104,32,101,110,116,114, - 121,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32, - 99,97,99,104,101,44,32,102,105,110,100,32,116,104,101,32, - 97,112,112,114,111,112,114,105,97,116,101,32,102,105,110,100, - 101,114,10,32,32,32,32,32,32,32,32,97,110,100,32,99, - 97,99,104,101,32,105,116,46,32,73,102,32,110,111,32,102, - 105,110,100,101,114,32,105,115,32,97,118,97,105,108,97,98, - 108,101,44,32,115,116,111,114,101,32,78,111,110,101,46,10, - 10,32,32,32,32,32,32,32,32,114,10,0,0,0,78,41, - 7,114,18,0,0,0,114,82,0,0,0,218,17,70,105,108, - 101,78,111,116,70,111,117,110,100,69,114,114,111,114,114,15, - 0,0,0,114,82,1,0,0,218,8,75,101,121,69,114,114, - 111,114,114,86,1,0,0,41,3,114,221,0,0,0,114,65, - 0,0,0,114,84,1,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,20,95,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,76,5,0, - 0,115,28,0,0,0,8,8,2,1,12,1,12,1,6,3, - 2,253,2,4,12,1,4,4,12,253,10,1,12,1,4,1, - 2,253,122,31,80,97,116,104,70,105,110,100,101,114,46,95, - 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, - 99,104,101,99,3,0,0,0,0,0,0,0,0,0,0,0, - 7,0,0,0,4,0,0,0,67,0,0,0,115,138,0,0, - 0,116,0,124,2,100,1,131,2,114,27,116,1,160,2,124, - 2,161,1,155,0,100,2,157,2,125,3,116,3,160,4,124, - 3,116,5,161,2,1,0,124,2,160,6,124,1,161,1,92, - 2,125,4,125,5,110,21,116,1,160,2,124,2,161,1,155, - 0,100,3,157,2,125,3,116,3,160,4,124,3,116,5,161, - 2,1,0,124,2,160,7,124,1,161,1,125,4,103,0,125, - 5,124,4,100,0,117,1,114,58,116,1,160,8,124,1,124, - 4,161,2,83,0,116,1,160,9,124,1,100,0,161,2,125, - 6,124,5,124,6,95,10,124,6,83,0,41,4,78,114,161, - 0,0,0,122,53,46,102,105,110,100,95,115,112,101,99,40, - 41,32,110,111,116,32,102,111,117,110,100,59,32,102,97,108, - 108,105,110,103,32,98,97,99,107,32,116,111,32,102,105,110, - 100,95,108,111,97,100,101,114,40,41,122,53,46,102,105,110, - 100,95,115,112,101,99,40,41,32,110,111,116,32,102,111,117, - 110,100,59,32,102,97,108,108,105,110,103,32,98,97,99,107, - 32,116,111,32,102,105,110,100,95,109,111,100,117,108,101,40, - 41,41,11,114,153,0,0,0,114,159,0,0,0,90,12,95, - 111,98,106,101,99,116,95,110,97,109,101,114,99,0,0,0, - 114,100,0,0,0,114,162,0,0,0,114,161,0,0,0,114, - 229,0,0,0,114,224,0,0,0,114,207,0,0,0,114,202, - 0,0,0,41,7,114,221,0,0,0,114,163,0,0,0,114, - 84,1,0,0,114,166,0,0,0,114,164,0,0,0,114,165, - 0,0,0,114,210,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,218,16,95,108,101,103,97,99,121, - 95,103,101,116,95,115,112,101,99,98,5,0,0,115,26,0, - 0,0,10,4,16,1,12,2,16,1,16,2,12,2,10,1, - 4,1,8,1,12,1,12,1,6,1,4,1,122,27,80,97, - 116,104,70,105,110,100,101,114,46,95,108,101,103,97,99,121, - 95,103,101,116,95,115,112,101,99,78,99,4,0,0,0,0, - 0,0,0,0,0,0,0,9,0,0,0,5,0,0,0,67, - 0,0,0,115,166,0,0,0,103,0,125,4,124,2,68,0, - 93,67,125,5,116,0,124,5,116,1,116,2,102,2,131,2, - 115,14,113,4,124,0,160,3,124,5,161,1,125,6,124,6, - 100,1,117,1,114,71,116,4,124,6,100,2,131,2,114,35, - 124,6,160,5,124,1,124,3,161,2,125,7,110,6,124,0, - 160,6,124,1,124,6,161,2,125,7,124,7,100,1,117,0, - 114,46,113,4,124,7,106,7,100,1,117,1,114,55,124,7, - 2,0,1,0,83,0,124,7,106,8,125,8,124,8,100,1, - 117,0,114,66,116,9,100,3,131,1,130,1,124,4,160,10, - 124,8,161,1,1,0,113,4,116,11,160,12,124,1,100,1, - 161,2,125,7,124,4,124,7,95,8,124,7,83,0,41,4, - 122,63,70,105,110,100,32,116,104,101,32,108,111,97,100,101, - 114,32,111,114,32,110,97,109,101,115,112,97,99,101,95,112, - 97,116,104,32,102,111,114,32,116,104,105,115,32,109,111,100, - 117,108,101,47,112,97,99,107,97,103,101,32,110,97,109,101, - 46,78,114,226,0,0,0,122,19,115,112,101,99,32,109,105, - 115,115,105,110,103,32,108,111,97,100,101,114,41,13,114,185, - 0,0,0,114,109,0,0,0,218,5,98,121,116,101,115,114, - 89,1,0,0,114,153,0,0,0,114,226,0,0,0,114,90, - 1,0,0,114,164,0,0,0,114,202,0,0,0,114,142,0, - 0,0,114,191,0,0,0,114,159,0,0,0,114,207,0,0, - 0,41,9,114,221,0,0,0,114,163,0,0,0,114,65,0, - 0,0,114,225,0,0,0,218,14,110,97,109,101,115,112,97, - 99,101,95,112,97,116,104,90,5,101,110,116,114,121,114,84, - 1,0,0,114,210,0,0,0,114,165,0,0,0,114,7,0, - 0,0,114,7,0,0,0,114,8,0,0,0,218,9,95,103, - 101,116,95,115,112,101,99,119,5,0,0,115,42,0,0,0, - 4,5,8,1,14,1,2,1,10,1,8,1,10,1,14,1, - 12,2,8,1,2,1,10,1,8,1,6,1,8,1,8,1, - 10,5,2,128,12,2,6,1,4,1,122,20,80,97,116,104, - 70,105,110,100,101,114,46,95,103,101,116,95,115,112,101,99, - 99,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0, - 0,5,0,0,0,67,0,0,0,115,94,0,0,0,124,2, - 100,1,117,0,114,7,116,0,106,1,125,2,124,0,160,2, - 124,1,124,2,124,3,161,3,125,4,124,4,100,1,117,0, - 114,20,100,1,83,0,124,4,106,3,100,1,117,0,114,45, - 124,4,106,4,125,5,124,5,114,43,100,1,124,4,95,5, - 116,6,124,1,124,5,124,0,106,2,131,3,124,4,95,4, - 124,4,83,0,100,1,83,0,124,4,83,0,41,2,122,141, - 84,114,121,32,116,111,32,102,105,110,100,32,97,32,115,112, - 101,99,32,102,111,114,32,39,102,117,108,108,110,97,109,101, - 39,32,111,110,32,115,121,115,46,112,97,116,104,32,111,114, - 32,39,112,97,116,104,39,46,10,10,32,32,32,32,32,32, - 32,32,84,104,101,32,115,101,97,114,99,104,32,105,115,32, - 98,97,115,101,100,32,111,110,32,115,121,115,46,112,97,116, - 104,95,104,111,111,107,115,32,97,110,100,32,115,121,115,46, - 112,97,116,104,95,105,109,112,111,114,116,101,114,95,99,97, - 99,104,101,46,10,32,32,32,32,32,32,32,32,78,41,7, - 114,15,0,0,0,114,65,0,0,0,114,93,1,0,0,114, - 164,0,0,0,114,202,0,0,0,114,205,0,0,0,114,47, - 1,0,0,41,6,114,221,0,0,0,114,163,0,0,0,114, - 65,0,0,0,114,225,0,0,0,114,210,0,0,0,114,92, - 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,226,0,0,0,151,5,0,0,115,26,0,0,0, - 8,6,6,1,14,1,8,1,4,1,10,1,6,1,4,1, - 6,3,16,1,4,1,4,2,4,2,122,20,80,97,116,104, - 70,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, - 99,3,0,0,0,0,0,0,0,0,0,0,0,4,0,0, - 0,4,0,0,0,67,0,0,0,115,42,0,0,0,116,0, - 160,1,100,1,116,2,161,2,1,0,124,0,160,3,124,1, - 124,2,161,2,125,3,124,3,100,2,117,0,114,18,100,2, - 83,0,124,3,106,4,83,0,41,3,122,170,102,105,110,100, - 32,116,104,101,32,109,111,100,117,108,101,32,111,110,32,115, - 121,115,46,112,97,116,104,32,111,114,32,39,112,97,116,104, - 39,32,98,97,115,101,100,32,111,110,32,115,121,115,46,112, - 97,116,104,95,104,111,111,107,115,32,97,110,100,10,32,32, - 32,32,32,32,32,32,115,121,115,46,112,97,116,104,95,105, - 109,112,111,114,116,101,114,95,99,97,99,104,101,46,10,10, + 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, + 0,115,24,0,0,0,116,0,160,1,100,1,116,2,161,2, + 1,0,100,2,160,3,124,0,106,4,161,1,83,0,41,3, + 122,115,82,101,116,117,114,110,32,114,101,112,114,32,102,111, + 114,32,116,104,101,32,109,111,100,117,108,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,101,32,109,101,116,104,111, + 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, + 32,32,84,104,101,32,105,109,112,111,114,116,32,109,97,99, + 104,105,110,101,114,121,32,100,111,101,115,32,116,104,101,32, + 106,111,98,32,105,116,115,101,108,102,46,10,10,32,32,32, + 32,32,32,32,32,122,82,95,78,97,109,101,115,112,97,99, + 101,76,111,97,100,101,114,46,109,111,100,117,108,101,95,114, + 101,112,114,40,41,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,32,97,110,100,32,115,108,97,116,101,100,32,102, + 111,114,32,114,101,109,111,118,97,108,32,105,110,32,80,121, + 116,104,111,110,32,51,46,49,50,122,25,60,109,111,100,117, + 108,101,32,123,33,114,125,32,40,110,97,109,101,115,112,97, + 99,101,41,62,41,5,114,99,0,0,0,114,100,0,0,0, + 114,101,0,0,0,114,89,0,0,0,114,150,0,0,0,41, + 1,114,244,0,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,218,11,109,111,100,117,108,101,95,114,101, + 112,114,1,5,0,0,115,8,0,0,0,6,7,2,1,4, + 255,12,2,122,28,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,46,109,111,100,117,108,101,95,114,101,112, + 114,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,114,23,0,0,0,41, + 2,78,84,114,7,0,0,0,114,247,0,0,0,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,114,206,0,0, + 0,12,5,0,0,243,2,0,0,0,4,1,122,27,95,78, + 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,105, + 115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,114,23,0,0,0,41,2,78,114,10,0,0,0,114, + 7,0,0,0,114,247,0,0,0,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,114,1,1,0,0,15,5,0, + 0,114,77,1,0,0,122,27,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,99,2,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,6,0,0,0,67,0,0,0,115,16,0,0, + 0,116,0,100,1,100,2,100,3,100,4,100,5,141,4,83, + 0,41,6,78,114,10,0,0,0,122,8,60,115,116,114,105, + 110,103,62,114,243,0,0,0,84,41,1,114,3,1,0,0, + 41,1,114,4,1,0,0,114,247,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,241,0,0,0, + 18,5,0,0,114,74,1,0,0,122,25,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, + 99,111,100,101,99,2,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,114,23,0, + 0,0,114,237,0,0,0,114,7,0,0,0,114,238,0,0, + 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, + 114,239,0,0,0,21,5,0,0,114,240,0,0,0,122,30, + 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, + 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, + 0,0,0,67,0,0,0,115,4,0,0,0,100,0,83,0, + 114,69,0,0,0,114,7,0,0,0,114,42,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,245, + 0,0,0,24,5,0,0,114,77,1,0,0,122,28,95,78, + 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,101, + 120,101,99,95,109,111,100,117,108,101,99,2,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, + 0,0,0,115,26,0,0,0,116,0,160,1,100,1,124,0, + 106,2,161,2,1,0,116,0,160,3,124,0,124,1,161,2, + 83,0,41,2,122,98,76,111,97,100,32,97,32,110,97,109, + 101,115,112,97,99,101,32,109,111,100,117,108,101,46,10,10, 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,122,101,80,97,116,104,70,105,110,100, - 101,114,46,102,105,110,100,95,109,111,100,117,108,101,40,41, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,32,97, - 110,100,32,115,108,97,116,101,100,32,102,111,114,32,114,101, - 109,111,118,97,108,32,105,110,32,80,121,116,104,111,110,32, - 51,46,49,50,59,32,117,115,101,32,102,105,110,100,95,115, - 112,101,99,40,41,32,105,110,115,116,101,97,100,78,114,227, - 0,0,0,114,228,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,229,0,0,0,175,5,0,0, - 115,14,0,0,0,6,8,2,2,4,254,12,3,8,1,4, - 1,6,1,122,22,80,97,116,104,70,105,110,100,101,114,46, - 102,105,110,100,95,109,111,100,117,108,101,99,0,0,0,0, - 0,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, - 79,0,0,0,115,28,0,0,0,100,1,100,2,108,0,109, - 1,125,2,1,0,124,2,106,2,124,0,105,0,124,1,164, - 1,142,1,83,0,41,3,97,32,1,0,0,10,32,32,32, - 32,32,32,32,32,70,105,110,100,32,100,105,115,116,114,105, - 98,117,116,105,111,110,115,46,10,10,32,32,32,32,32,32, - 32,32,82,101,116,117,114,110,32,97,110,32,105,116,101,114, - 97,98,108,101,32,111,102,32,97,108,108,32,68,105,115,116, - 114,105,98,117,116,105,111,110,32,105,110,115,116,97,110,99, - 101,115,32,99,97,112,97,98,108,101,32,111,102,10,32,32, - 32,32,32,32,32,32,108,111,97,100,105,110,103,32,116,104, - 101,32,109,101,116,97,100,97,116,97,32,102,111,114,32,112, - 97,99,107,97,103,101,115,32,109,97,116,99,104,105,110,103, - 32,96,96,99,111,110,116,101,120,116,46,110,97,109,101,96, - 96,10,32,32,32,32,32,32,32,32,40,111,114,32,97,108, - 108,32,110,97,109,101,115,32,105,102,32,96,96,78,111,110, - 101,96,96,32,105,110,100,105,99,97,116,101,100,41,32,97, - 108,111,110,103,32,116,104,101,32,112,97,116,104,115,32,105, - 110,32,116,104,101,32,108,105,115,116,10,32,32,32,32,32, - 32,32,32,111,102,32,100,105,114,101,99,116,111,114,105,101, - 115,32,96,96,99,111,110,116,101,120,116,46,112,97,116,104, - 96,96,46,10,32,32,32,32,32,32,32,32,114,0,0,0, - 0,41,1,218,18,77,101,116,97,100,97,116,97,80,97,116, - 104,70,105,110,100,101,114,41,3,90,18,105,109,112,111,114, - 116,108,105,98,46,109,101,116,97,100,97,116,97,114,94,1, - 0,0,218,18,102,105,110,100,95,100,105,115,116,114,105,98, - 117,116,105,111,110,115,41,3,114,144,0,0,0,114,145,0, - 0,0,114,94,1,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,95,1,0,0,191,5,0,0,115, - 4,0,0,0,12,10,16,1,122,29,80,97,116,104,70,105, - 110,100,101,114,46,102,105,110,100,95,100,105,115,116,114,105, - 98,117,116,105,111,110,115,114,69,0,0,0,114,230,0,0, - 0,41,14,114,150,0,0,0,114,149,0,0,0,114,151,0, - 0,0,114,152,0,0,0,114,233,0,0,0,114,80,1,0, - 0,114,86,1,0,0,114,234,0,0,0,114,89,1,0,0, - 114,90,1,0,0,114,93,1,0,0,114,226,0,0,0,114, - 229,0,0,0,114,95,1,0,0,114,7,0,0,0,114,7, - 0,0,0,114,7,0,0,0,114,8,0,0,0,114,79,1, - 0,0,46,5,0,0,115,36,0,0,0,8,0,4,2,2, - 2,10,1,2,12,10,1,2,12,10,1,2,21,10,1,2, - 20,12,1,2,31,12,1,2,23,12,1,2,15,14,1,114, - 79,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,64,0,0,0,115,90,0, - 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, - 100,3,132,0,90,4,100,4,100,5,132,0,90,5,101,6, - 90,7,100,6,100,7,132,0,90,8,100,8,100,9,132,0, - 90,9,100,19,100,11,100,12,132,1,90,10,100,13,100,14, - 132,0,90,11,101,12,100,15,100,16,132,0,131,1,90,13, - 100,17,100,18,132,0,90,14,100,10,83,0,41,20,218,10, - 70,105,108,101,70,105,110,100,101,114,122,172,70,105,108,101, - 45,98,97,115,101,100,32,102,105,110,100,101,114,46,10,10, - 32,32,32,32,73,110,116,101,114,97,99,116,105,111,110,115, - 32,119,105,116,104,32,116,104,101,32,102,105,108,101,32,115, - 121,115,116,101,109,32,97,114,101,32,99,97,99,104,101,100, - 32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101, - 44,32,98,101,105,110,103,10,32,32,32,32,114,101,102,114, - 101,115,104,101,100,32,119,104,101,110,32,116,104,101,32,100, - 105,114,101,99,116,111,114,121,32,116,104,101,32,102,105,110, - 100,101,114,32,105,115,32,104,97,110,100,108,105,110,103,32, - 104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101, - 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, - 0,0,0,0,0,5,0,0,0,6,0,0,0,7,0,0, - 0,115,112,0,0,0,103,0,125,3,124,2,68,0,93,16, - 92,2,137,0,125,4,124,3,160,0,135,0,102,1,100,1, - 100,2,132,8,124,4,68,0,131,1,161,1,1,0,113,4, - 124,3,124,0,95,1,124,1,112,27,100,3,124,0,95,2, - 116,3,124,0,106,2,131,1,115,43,116,4,116,5,160,6, - 161,0,124,0,106,2,131,2,124,0,95,2,100,4,124,0, - 95,7,116,8,131,0,124,0,95,9,116,8,131,0,124,0, - 95,10,100,5,83,0,41,6,122,154,73,110,105,116,105,97, - 108,105,122,101,32,119,105,116,104,32,116,104,101,32,112,97, - 116,104,32,116,111,32,115,101,97,114,99,104,32,111,110,32, - 97,110,100,32,97,32,118,97,114,105,97,98,108,101,32,110, - 117,109,98,101,114,32,111,102,10,32,32,32,32,32,32,32, - 32,50,45,116,117,112,108,101,115,32,99,111,110,116,97,105, - 110,105,110,103,32,116,104,101,32,108,111,97,100,101,114,32, - 97,110,100,32,116,104,101,32,102,105,108,101,32,115,117,102, - 102,105,120,101,115,32,116,104,101,32,108,111,97,100,101,114, - 10,32,32,32,32,32,32,32,32,114,101,99,111,103,110,105, - 122,101,115,46,99,1,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,51,0,0,0,115,24,0, - 0,0,129,0,124,0,93,7,125,1,124,1,136,0,102,2, - 86,0,1,0,113,2,100,0,83,0,114,69,0,0,0,114, - 7,0,0,0,114,43,1,0,0,169,1,114,164,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,9,0,0,0,220, - 5,0,0,115,4,0,0,0,2,128,22,0,122,38,70,105, - 108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95, - 95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101, - 120,112,114,62,114,97,0,0,0,114,130,0,0,0,78,41, - 11,114,191,0,0,0,218,8,95,108,111,97,100,101,114,115, - 114,65,0,0,0,114,86,0,0,0,114,67,0,0,0,114, - 18,0,0,0,114,82,0,0,0,218,11,95,112,97,116,104, - 95,109,116,105,109,101,218,3,115,101,116,218,11,95,112,97, - 116,104,95,99,97,99,104,101,218,19,95,114,101,108,97,120, - 101,100,95,112,97,116,104,95,99,97,99,104,101,41,5,114, - 143,0,0,0,114,65,0,0,0,218,14,108,111,97,100,101, - 114,95,100,101,116,97,105,108,115,90,7,108,111,97,100,101, - 114,115,114,212,0,0,0,114,7,0,0,0,114,97,1,0, - 0,114,8,0,0,0,114,236,0,0,0,214,5,0,0,115, - 20,0,0,0,4,4,12,1,26,1,6,1,10,2,10,1, - 18,1,6,1,8,1,12,1,122,19,70,105,108,101,70,105, - 110,100,101,114,46,95,95,105,110,105,116,95,95,99,1,0, - 0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,67,0,0,0,115,10,0,0,0,100,1,124,0,95, - 0,100,2,83,0,41,3,122,31,73,110,118,97,108,105,100, - 97,116,101,32,116,104,101,32,100,105,114,101,99,116,111,114, - 121,32,109,116,105,109,101,46,114,130,0,0,0,78,41,1, - 114,99,1,0,0,114,21,1,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,80,1,0,0,230,5, - 0,0,114,81,0,0,0,122,28,70,105,108,101,70,105,110, - 100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99, - 97,99,104,101,115,99,2,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,4,0,0,0,67,0,0,0,115,54, - 0,0,0,116,0,160,1,100,1,116,2,161,2,1,0,124, - 0,160,3,124,1,161,1,125,2,124,2,100,2,117,0,114, - 19,100,2,103,0,102,2,83,0,124,2,106,4,124,2,106, - 5,112,25,103,0,102,2,83,0,41,3,122,197,84,114,121, - 32,116,111,32,102,105,110,100,32,97,32,108,111,97,100,101, - 114,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102, - 105,101,100,32,109,111,100,117,108,101,44,32,111,114,32,116, - 104,101,32,110,97,109,101,115,112,97,99,101,10,32,32,32, - 32,32,32,32,32,112,97,99,107,97,103,101,32,112,111,114, - 116,105,111,110,115,46,32,82,101,116,117,114,110,115,32,40, - 108,111,97,100,101,114,44,32,108,105,115,116,45,111,102,45, - 112,111,114,116,105,111,110,115,41,46,10,10,32,32,32,32, + 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,122,38,110,97,109,101,115,112, + 97,99,101,32,109,111,100,117,108,101,32,108,111,97,100,101, + 100,32,119,105,116,104,32,112,97,116,104,32,123,33,114,125, + 41,4,114,159,0,0,0,114,173,0,0,0,114,49,1,0, + 0,114,246,0,0,0,114,247,0,0,0,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,248,0,0,0,27, + 5,0,0,115,8,0,0,0,6,7,4,1,4,255,12,3, + 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, + 101,114,46,108,111,97,100,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,2, + 0,0,0,67,0,0,0,115,22,0,0,0,100,1,100,2, + 108,0,109,1,125,2,1,0,124,2,124,0,106,2,131,1, + 83,0,41,3,78,114,0,0,0,0,41,1,218,15,78,97, + 109,101,115,112,97,99,101,82,101,97,100,101,114,41,3,114, + 32,1,0,0,114,78,1,0,0,114,49,1,0,0,41,3, + 114,143,0,0,0,114,244,0,0,0,114,78,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,33, + 1,0,0,39,5,0,0,115,4,0,0,0,12,1,10,1, + 122,36,95,78,97,109,101,115,112,97,99,101,76,111,97,100, + 101,114,46,103,101,116,95,114,101,115,111,117,114,99,101,95, + 114,101,97,100,101,114,78,41,13,114,150,0,0,0,114,149, + 0,0,0,114,151,0,0,0,114,236,0,0,0,114,233,0, + 0,0,114,76,1,0,0,114,206,0,0,0,114,1,1,0, + 0,114,241,0,0,0,114,239,0,0,0,114,245,0,0,0, + 114,248,0,0,0,114,33,1,0,0,114,7,0,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,75, + 1,0,0,253,4,0,0,115,22,0,0,0,8,0,8,1, + 2,3,10,1,8,10,8,3,8,3,8,3,8,3,8,3, + 12,12,114,75,1,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,0, + 115,118,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,101,4,100,2,100,3,132,0,131,1,90,5,101,4,100, + 4,100,5,132,0,131,1,90,6,101,7,100,6,100,7,132, + 0,131,1,90,8,101,7,100,8,100,9,132,0,131,1,90, + 9,101,7,100,19,100,11,100,12,132,1,131,1,90,10,101, + 7,100,20,100,13,100,14,132,1,131,1,90,11,101,7,100, + 19,100,15,100,16,132,1,131,1,90,12,101,4,100,17,100, + 18,132,0,131,1,90,13,100,10,83,0,41,21,218,10,80, + 97,116,104,70,105,110,100,101,114,122,62,77,101,116,97,32, + 112,97,116,104,32,102,105,110,100,101,114,32,102,111,114,32, + 115,121,115,46,112,97,116,104,32,97,110,100,32,112,97,99, + 107,97,103,101,32,95,95,112,97,116,104,95,95,32,97,116, + 116,114,105,98,117,116,101,115,46,99,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, + 0,0,115,78,0,0,0,116,0,116,1,106,2,160,3,161, + 0,131,1,68,0,93,22,92,2,125,0,125,1,124,1,100, + 1,117,0,114,20,116,1,106,2,124,0,61,0,113,7,116, + 4,124,1,100,2,131,2,114,29,124,1,160,5,161,0,1, + 0,113,7,116,6,4,0,106,7,100,3,55,0,2,0,95, + 7,100,1,83,0,41,4,122,125,67,97,108,108,32,116,104, + 101,32,105,110,118,97,108,105,100,97,116,101,95,99,97,99, + 104,101,115,40,41,32,109,101,116,104,111,100,32,111,110,32, + 97,108,108,32,112,97,116,104,32,101,110,116,114,121,32,102, + 105,110,100,101,114,115,10,32,32,32,32,32,32,32,32,115, + 116,111,114,101,100,32,105,110,32,115,121,115,46,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, + 115,32,40,119,104,101,114,101,32,105,109,112,108,101,109,101, + 110,116,101,100,41,46,78,218,17,105,110,118,97,108,105,100, + 97,116,101,95,99,97,99,104,101,115,114,3,0,0,0,41, + 8,218,4,108,105,115,116,114,15,0,0,0,218,19,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,218,5,105,116,101,109,115,114,153,0,0,0,114,80,1, + 0,0,114,47,1,0,0,114,52,1,0,0,41,2,114,141, + 0,0,0,218,6,102,105,110,100,101,114,114,7,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,80,1,0,0,50, + 5,0,0,115,14,0,0,0,22,4,8,1,10,1,10,1, + 8,1,2,128,18,3,122,28,80,97,116,104,70,105,110,100, + 101,114,46,105,110,118,97,108,105,100,97,116,101,95,99,97, + 99,104,101,115,99,1,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,9,0,0,0,67,0,0,0,115,76,0, + 0,0,116,0,106,1,100,1,117,1,114,14,116,0,106,1, + 115,14,116,2,160,3,100,2,116,4,161,2,1,0,116,0, + 106,1,68,0,93,18,125,1,122,7,124,1,124,0,131,1, + 87,0,2,0,1,0,83,0,4,0,116,5,121,35,1,0, + 1,0,1,0,89,0,113,17,119,0,100,1,83,0,41,3, + 122,46,83,101,97,114,99,104,32,115,121,115,46,112,97,116, + 104,95,104,111,111,107,115,32,102,111,114,32,97,32,102,105, + 110,100,101,114,32,102,111,114,32,39,112,97,116,104,39,46, + 78,122,23,115,121,115,46,112,97,116,104,95,104,111,111,107, + 115,32,105,115,32,101,109,112,116,121,41,6,114,15,0,0, + 0,218,10,112,97,116,104,95,104,111,111,107,115,114,99,0, + 0,0,114,100,0,0,0,114,162,0,0,0,114,142,0,0, + 0,41,2,114,65,0,0,0,90,4,104,111,111,107,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,218,11,95, + 112,97,116,104,95,104,111,111,107,115,63,5,0,0,115,18, + 0,0,0,16,3,12,1,10,1,2,1,14,1,12,1,4, + 1,2,255,4,3,122,22,80,97,116,104,70,105,110,100,101, + 114,46,95,112,97,116,104,95,104,111,111,107,115,99,2,0, + 0,0,0,0,0,0,0,0,0,0,3,0,0,0,8,0, + 0,0,67,0,0,0,115,100,0,0,0,124,1,100,1,107, + 2,114,21,122,6,116,0,160,1,161,0,125,1,87,0,110, + 10,4,0,116,2,121,20,1,0,1,0,1,0,89,0,100, + 2,83,0,119,0,122,8,116,3,106,4,124,1,25,0,125, + 2,87,0,124,2,83,0,4,0,116,5,121,49,1,0,1, + 0,1,0,124,0,160,6,124,1,161,1,125,2,124,2,116, + 3,106,4,124,1,60,0,89,0,124,2,83,0,119,0,41, + 3,122,210,71,101,116,32,116,104,101,32,102,105,110,100,101, + 114,32,102,111,114,32,116,104,101,32,112,97,116,104,32,101, + 110,116,114,121,32,102,114,111,109,32,115,121,115,46,112,97, + 116,104,95,105,109,112,111,114,116,101,114,95,99,97,99,104, + 101,46,10,10,32,32,32,32,32,32,32,32,73,102,32,116, + 104,101,32,112,97,116,104,32,101,110,116,114,121,32,105,115, + 32,110,111,116,32,105,110,32,116,104,101,32,99,97,99,104, + 101,44,32,102,105,110,100,32,116,104,101,32,97,112,112,114, + 111,112,114,105,97,116,101,32,102,105,110,100,101,114,10,32, + 32,32,32,32,32,32,32,97,110,100,32,99,97,99,104,101, + 32,105,116,46,32,73,102,32,110,111,32,102,105,110,100,101, + 114,32,105,115,32,97,118,97,105,108,97,98,108,101,44,32, + 115,116,111,114,101,32,78,111,110,101,46,10,10,32,32,32, + 32,32,32,32,32,114,10,0,0,0,78,41,7,114,18,0, + 0,0,114,82,0,0,0,218,17,70,105,108,101,78,111,116, + 70,111,117,110,100,69,114,114,111,114,114,15,0,0,0,114, + 82,1,0,0,218,8,75,101,121,69,114,114,111,114,114,86, + 1,0,0,41,3,114,221,0,0,0,114,65,0,0,0,114, + 84,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,20,95,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,76,5,0,0,115,28,0, + 0,0,8,8,2,1,12,1,12,1,6,3,2,253,2,4, + 12,1,4,4,12,253,10,1,12,1,4,1,2,253,122,31, + 80,97,116,104,70,105,110,100,101,114,46,95,112,97,116,104, + 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,99, + 3,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0, + 4,0,0,0,67,0,0,0,115,138,0,0,0,116,0,124, + 2,100,1,131,2,114,27,116,1,160,2,124,2,161,1,155, + 0,100,2,157,2,125,3,116,3,160,4,124,3,116,5,161, + 2,1,0,124,2,160,6,124,1,161,1,92,2,125,4,125, + 5,110,21,116,1,160,2,124,2,161,1,155,0,100,3,157, + 2,125,3,116,3,160,4,124,3,116,5,161,2,1,0,124, + 2,160,7,124,1,161,1,125,4,103,0,125,5,124,4,100, + 0,117,1,114,58,116,1,160,8,124,1,124,4,161,2,83, + 0,116,1,160,9,124,1,100,0,161,2,125,6,124,5,124, + 6,95,10,124,6,83,0,41,4,78,114,161,0,0,0,122, + 53,46,102,105,110,100,95,115,112,101,99,40,41,32,110,111, + 116,32,102,111,117,110,100,59,32,102,97,108,108,105,110,103, + 32,98,97,99,107,32,116,111,32,102,105,110,100,95,108,111, + 97,100,101,114,40,41,122,53,46,102,105,110,100,95,115,112, + 101,99,40,41,32,110,111,116,32,102,111,117,110,100,59,32, + 102,97,108,108,105,110,103,32,98,97,99,107,32,116,111,32, + 102,105,110,100,95,109,111,100,117,108,101,40,41,41,11,114, + 153,0,0,0,114,159,0,0,0,90,12,95,111,98,106,101, + 99,116,95,110,97,109,101,114,99,0,0,0,114,100,0,0, + 0,114,162,0,0,0,114,161,0,0,0,114,229,0,0,0, + 114,224,0,0,0,114,207,0,0,0,114,202,0,0,0,41, + 7,114,221,0,0,0,114,163,0,0,0,114,84,1,0,0, + 114,166,0,0,0,114,164,0,0,0,114,165,0,0,0,114, + 210,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,218,16,95,108,101,103,97,99,121,95,103,101,116, + 95,115,112,101,99,98,5,0,0,115,26,0,0,0,10,4, + 16,1,12,2,16,1,16,2,12,2,10,1,4,1,8,1, + 12,1,12,1,6,1,4,1,122,27,80,97,116,104,70,105, + 110,100,101,114,46,95,108,101,103,97,99,121,95,103,101,116, + 95,115,112,101,99,78,99,4,0,0,0,0,0,0,0,0, + 0,0,0,9,0,0,0,5,0,0,0,67,0,0,0,115, + 166,0,0,0,103,0,125,4,124,2,68,0,93,67,125,5, + 116,0,124,5,116,1,116,2,102,2,131,2,115,14,113,4, + 124,0,160,3,124,5,161,1,125,6,124,6,100,1,117,1, + 114,71,116,4,124,6,100,2,131,2,114,35,124,6,160,5, + 124,1,124,3,161,2,125,7,110,6,124,0,160,6,124,1, + 124,6,161,2,125,7,124,7,100,1,117,0,114,46,113,4, + 124,7,106,7,100,1,117,1,114,55,124,7,2,0,1,0, + 83,0,124,7,106,8,125,8,124,8,100,1,117,0,114,66, + 116,9,100,3,131,1,130,1,124,4,160,10,124,8,161,1, + 1,0,113,4,116,11,160,12,124,1,100,1,161,2,125,7, + 124,4,124,7,95,8,124,7,83,0,41,4,122,63,70,105, + 110,100,32,116,104,101,32,108,111,97,100,101,114,32,111,114, + 32,110,97,109,101,115,112,97,99,101,95,112,97,116,104,32, + 102,111,114,32,116,104,105,115,32,109,111,100,117,108,101,47, + 112,97,99,107,97,103,101,32,110,97,109,101,46,78,114,226, + 0,0,0,122,19,115,112,101,99,32,109,105,115,115,105,110, + 103,32,108,111,97,100,101,114,41,13,114,185,0,0,0,114, + 109,0,0,0,218,5,98,121,116,101,115,114,89,1,0,0, + 114,153,0,0,0,114,226,0,0,0,114,90,1,0,0,114, + 164,0,0,0,114,202,0,0,0,114,142,0,0,0,114,191, + 0,0,0,114,159,0,0,0,114,207,0,0,0,41,9,114, + 221,0,0,0,114,163,0,0,0,114,65,0,0,0,114,225, + 0,0,0,218,14,110,97,109,101,115,112,97,99,101,95,112, + 97,116,104,90,5,101,110,116,114,121,114,84,1,0,0,114, + 210,0,0,0,114,165,0,0,0,114,7,0,0,0,114,7, + 0,0,0,114,8,0,0,0,218,9,95,103,101,116,95,115, + 112,101,99,119,5,0,0,115,42,0,0,0,4,5,8,1, + 14,1,2,1,10,1,8,1,10,1,14,1,12,2,8,1, + 2,1,10,1,8,1,6,1,8,1,8,1,10,5,2,128, + 12,2,6,1,4,1,122,20,80,97,116,104,70,105,110,100, + 101,114,46,95,103,101,116,95,115,112,101,99,99,4,0,0, + 0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0, + 0,67,0,0,0,115,94,0,0,0,124,2,100,1,117,0, + 114,7,116,0,106,1,125,2,124,0,160,2,124,1,124,2, + 124,3,161,3,125,4,124,4,100,1,117,0,114,20,100,1, + 83,0,124,4,106,3,100,1,117,0,114,45,124,4,106,4, + 125,5,124,5,114,43,100,1,124,4,95,5,116,6,124,1, + 124,5,124,0,106,2,131,3,124,4,95,4,124,4,83,0, + 100,1,83,0,124,4,83,0,41,2,122,141,84,114,121,32, + 116,111,32,102,105,110,100,32,97,32,115,112,101,99,32,102, + 111,114,32,39,102,117,108,108,110,97,109,101,39,32,111,110, + 32,115,121,115,46,112,97,116,104,32,111,114,32,39,112,97, + 116,104,39,46,10,10,32,32,32,32,32,32,32,32,84,104, + 101,32,115,101,97,114,99,104,32,105,115,32,98,97,115,101, + 100,32,111,110,32,115,121,115,46,112,97,116,104,95,104,111, + 111,107,115,32,97,110,100,32,115,121,115,46,112,97,116,104, + 95,105,109,112,111,114,116,101,114,95,99,97,99,104,101,46, + 10,32,32,32,32,32,32,32,32,78,41,7,114,15,0,0, + 0,114,65,0,0,0,114,93,1,0,0,114,164,0,0,0, + 114,202,0,0,0,114,205,0,0,0,114,47,1,0,0,41, + 6,114,221,0,0,0,114,163,0,0,0,114,65,0,0,0, + 114,225,0,0,0,114,210,0,0,0,114,92,1,0,0,114, + 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,226, + 0,0,0,151,5,0,0,115,26,0,0,0,8,6,6,1, + 14,1,8,1,4,1,10,1,6,1,4,1,6,3,16,1, + 4,1,4,2,4,2,122,20,80,97,116,104,70,105,110,100, + 101,114,46,102,105,110,100,95,115,112,101,99,99,3,0,0, + 0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0, + 0,67,0,0,0,115,42,0,0,0,116,0,160,1,100,1, + 116,2,161,2,1,0,124,0,160,3,124,1,124,2,161,2, + 125,3,124,3,100,2,117,0,114,18,100,2,83,0,124,3, + 106,4,83,0,41,3,122,170,102,105,110,100,32,116,104,101, + 32,109,111,100,117,108,101,32,111,110,32,115,121,115,46,112, + 97,116,104,32,111,114,32,39,112,97,116,104,39,32,98,97, + 115,101,100,32,111,110,32,115,121,115,46,112,97,116,104,95, + 104,111,111,107,115,32,97,110,100,10,32,32,32,32,32,32, + 32,32,115,121,115,46,112,97,116,104,95,105,109,112,111,114, + 116,101,114,95,99,97,99,104,101,46,10,10,32,32,32,32, 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, 85,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, - 32,32,122,101,70,105,108,101,70,105,110,100,101,114,46,102, - 105,110,100,95,108,111,97,100,101,114,40,41,32,105,115,32, + 32,32,122,101,80,97,116,104,70,105,110,100,101,114,46,102, + 105,110,100,95,109,111,100,117,108,101,40,41,32,105,115,32, 100,101,112,114,101,99,97,116,101,100,32,97,110,100,32,115, 108,97,116,101,100,32,102,111,114,32,114,101,109,111,118,97, 108,32,105,110,32,80,121,116,104,111,110,32,51,46,49,50, 59,32,117,115,101,32,102,105,110,100,95,115,112,101,99,40, - 41,32,105,110,115,116,101,97,100,78,41,6,114,99,0,0, - 0,114,100,0,0,0,114,101,0,0,0,114,226,0,0,0, - 114,164,0,0,0,114,202,0,0,0,41,3,114,143,0,0, - 0,114,163,0,0,0,114,210,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,161,0,0,0,236, - 5,0,0,115,14,0,0,0,6,7,2,2,4,254,10,3, - 8,1,8,1,16,1,122,22,70,105,108,101,70,105,110,100, - 101,114,46,102,105,110,100,95,108,111,97,100,101,114,99,6, - 0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6, - 0,0,0,67,0,0,0,115,26,0,0,0,124,1,124,2, - 124,3,131,2,125,6,116,0,124,2,124,3,124,6,124,4, - 100,1,141,4,83,0,41,2,78,114,201,0,0,0,41,1, - 114,213,0,0,0,41,7,114,143,0,0,0,114,211,0,0, - 0,114,163,0,0,0,114,65,0,0,0,90,4,115,109,115, - 108,114,225,0,0,0,114,164,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,93,1,0,0,251, - 5,0,0,115,8,0,0,0,10,1,8,1,2,1,6,255, - 122,20,70,105,108,101,70,105,110,100,101,114,46,95,103,101, - 116,95,115,112,101,99,78,99,3,0,0,0,0,0,0,0, - 0,0,0,0,14,0,0,0,9,0,0,0,67,0,0,0, - 115,122,1,0,0,100,1,125,3,124,1,160,0,100,2,161, - 1,100,3,25,0,125,4,122,12,116,1,124,0,106,2,112, - 17,116,3,160,4,161,0,131,1,106,5,125,5,87,0,110, - 11,4,0,116,6,121,32,1,0,1,0,1,0,100,4,125, - 5,89,0,110,1,119,0,124,5,124,0,106,7,107,3,114, - 45,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, - 9,131,0,114,56,124,0,106,10,125,6,124,4,160,11,161, - 0,125,7,110,5,124,0,106,12,125,6,124,4,125,7,124, - 7,124,6,118,0,114,108,116,13,124,0,106,2,124,4,131, - 2,125,8,124,0,106,14,68,0,93,29,92,2,125,9,125, - 10,100,5,124,9,23,0,125,11,116,13,124,8,124,11,131, - 2,125,12,116,15,124,12,131,1,114,103,124,0,160,16,124, - 10,124,1,124,12,124,8,103,1,124,2,161,5,2,0,1, - 0,83,0,113,74,116,17,124,8,131,1,125,3,124,0,106, - 14,68,0,93,55,92,2,125,9,125,10,122,10,116,13,124, - 0,106,2,124,4,124,9,23,0,131,2,125,12,87,0,110, - 11,4,0,116,18,121,136,1,0,1,0,1,0,89,0,1, - 0,100,6,83,0,119,0,116,19,106,20,100,7,124,12,100, - 3,100,8,141,3,1,0,124,7,124,9,23,0,124,6,118, - 0,114,166,116,15,124,12,131,1,114,166,124,0,160,16,124, - 10,124,1,124,12,100,6,124,2,161,5,2,0,1,0,83, - 0,113,111,124,3,114,187,116,19,160,20,100,9,124,8,161, - 2,1,0,116,19,160,21,124,1,100,6,161,2,125,13,124, - 8,103,1,124,13,95,22,124,13,83,0,100,6,83,0,41, - 10,122,111,84,114,121,32,116,111,32,102,105,110,100,32,97, - 32,115,112,101,99,32,102,111,114,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,32,32,32,32,82,101,116,117,114,110,115, - 32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,112, - 101,99,44,32,111,114,32,78,111,110,101,32,105,102,32,110, - 111,116,32,102,111,117,110,100,46,10,32,32,32,32,32,32, - 32,32,70,114,97,0,0,0,114,44,0,0,0,114,130,0, - 0,0,114,236,0,0,0,78,122,9,116,114,121,105,110,103, - 32,123,125,41,1,90,9,118,101,114,98,111,115,105,116,121, - 122,25,112,111,115,115,105,98,108,101,32,110,97,109,101,115, - 112,97,99,101,32,102,111,114,32,123,125,41,23,114,104,0, - 0,0,114,75,0,0,0,114,65,0,0,0,114,18,0,0, - 0,114,82,0,0,0,114,35,1,0,0,114,76,0,0,0, - 114,99,1,0,0,218,11,95,102,105,108,108,95,99,97,99, - 104,101,114,21,0,0,0,114,102,1,0,0,114,131,0,0, - 0,114,101,1,0,0,114,67,0,0,0,114,98,1,0,0, - 114,80,0,0,0,114,93,1,0,0,114,83,0,0,0,114, - 111,0,0,0,114,159,0,0,0,114,173,0,0,0,114,207, - 0,0,0,114,202,0,0,0,41,14,114,143,0,0,0,114, - 163,0,0,0,114,225,0,0,0,90,12,105,115,95,110,97, - 109,101,115,112,97,99,101,90,11,116,97,105,108,95,109,111, - 100,117,108,101,114,193,0,0,0,90,5,99,97,99,104,101, - 90,12,99,97,99,104,101,95,109,111,100,117,108,101,90,9, - 98,97,115,101,95,112,97,116,104,114,44,1,0,0,114,211, - 0,0,0,90,13,105,110,105,116,95,102,105,108,101,110,97, - 109,101,90,9,102,117,108,108,95,112,97,116,104,114,210,0, - 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,226,0,0,0,0,6,0,0,115,86,0,0,0,4, - 5,14,1,2,1,24,1,12,1,8,1,2,255,10,2,8, - 1,6,1,6,2,6,1,10,1,6,2,4,1,8,2,12, - 1,14,1,8,1,10,1,8,1,24,1,2,255,8,5,14, - 2,2,1,20,1,12,1,8,1,2,255,16,2,12,1,8, - 1,10,1,4,1,8,255,2,128,4,2,12,1,12,1,8, - 1,4,1,4,1,122,20,70,105,108,101,70,105,110,100,101, - 114,46,102,105,110,100,95,115,112,101,99,99,1,0,0,0, - 0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0, - 67,0,0,0,115,192,0,0,0,124,0,106,0,125,1,122, - 11,116,1,160,2,124,1,112,11,116,1,160,3,161,0,161, - 1,125,2,87,0,110,14,4,0,116,4,116,5,116,6,102, - 3,121,28,1,0,1,0,1,0,103,0,125,2,89,0,110, - 1,119,0,116,7,106,8,160,9,100,1,161,1,115,41,116, - 10,124,2,131,1,124,0,95,11,110,37,116,10,131,0,125, - 3,124,2,68,0,93,28,125,4,124,4,160,12,100,2,161, - 1,92,3,125,5,125,6,125,7,124,6,114,67,100,3,160, - 13,124,5,124,7,160,14,161,0,161,2,125,8,110,2,124, - 5,125,8,124,3,160,15,124,8,161,1,1,0,113,46,124, - 3,124,0,95,11,116,7,106,8,160,9,116,16,161,1,114, - 94,100,4,100,5,132,0,124,2,68,0,131,1,124,0,95, - 17,100,6,83,0,100,6,83,0,41,7,122,68,70,105,108, - 108,32,116,104,101,32,99,97,99,104,101,32,111,102,32,112, - 111,116,101,110,116,105,97,108,32,109,111,100,117,108,101,115, - 32,97,110,100,32,112,97,99,107,97,103,101,115,32,102,111, - 114,32,116,104,105,115,32,100,105,114,101,99,116,111,114,121, - 46,114,14,0,0,0,114,97,0,0,0,114,88,0,0,0, + 41,32,105,110,115,116,101,97,100,78,114,227,0,0,0,114, + 228,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,229,0,0,0,175,5,0,0,115,14,0,0, + 0,6,8,2,2,4,254,12,3,8,1,4,1,6,1,122, + 22,80,97,116,104,70,105,110,100,101,114,46,102,105,110,100, + 95,109,111,100,117,108,101,99,0,0,0,0,0,0,0,0, + 0,0,0,0,3,0,0,0,4,0,0,0,79,0,0,0, + 115,28,0,0,0,100,1,100,2,108,0,109,1,125,2,1, + 0,124,2,106,2,124,0,105,0,124,1,164,1,142,1,83, + 0,41,3,97,32,1,0,0,10,32,32,32,32,32,32,32, + 32,70,105,110,100,32,100,105,115,116,114,105,98,117,116,105, + 111,110,115,46,10,10,32,32,32,32,32,32,32,32,82,101, + 116,117,114,110,32,97,110,32,105,116,101,114,97,98,108,101, + 32,111,102,32,97,108,108,32,68,105,115,116,114,105,98,117, + 116,105,111,110,32,105,110,115,116,97,110,99,101,115,32,99, + 97,112,97,98,108,101,32,111,102,10,32,32,32,32,32,32, + 32,32,108,111,97,100,105,110,103,32,116,104,101,32,109,101, + 116,97,100,97,116,97,32,102,111,114,32,112,97,99,107,97, + 103,101,115,32,109,97,116,99,104,105,110,103,32,96,96,99, + 111,110,116,101,120,116,46,110,97,109,101,96,96,10,32,32, + 32,32,32,32,32,32,40,111,114,32,97,108,108,32,110,97, + 109,101,115,32,105,102,32,96,96,78,111,110,101,96,96,32, + 105,110,100,105,99,97,116,101,100,41,32,97,108,111,110,103, + 32,116,104,101,32,112,97,116,104,115,32,105,110,32,116,104, + 101,32,108,105,115,116,10,32,32,32,32,32,32,32,32,111, + 102,32,100,105,114,101,99,116,111,114,105,101,115,32,96,96, + 99,111,110,116,101,120,116,46,112,97,116,104,96,96,46,10, + 32,32,32,32,32,32,32,32,114,0,0,0,0,41,1,218, + 18,77,101,116,97,100,97,116,97,80,97,116,104,70,105,110, + 100,101,114,41,3,90,18,105,109,112,111,114,116,108,105,98, + 46,109,101,116,97,100,97,116,97,114,94,1,0,0,218,18, + 102,105,110,100,95,100,105,115,116,114,105,98,117,116,105,111, + 110,115,41,3,114,144,0,0,0,114,145,0,0,0,114,94, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,95,1,0,0,191,5,0,0,115,4,0,0,0, + 12,10,16,1,122,29,80,97,116,104,70,105,110,100,101,114, + 46,102,105,110,100,95,100,105,115,116,114,105,98,117,116,105, + 111,110,115,114,69,0,0,0,114,230,0,0,0,41,14,114, + 150,0,0,0,114,149,0,0,0,114,151,0,0,0,114,152, + 0,0,0,114,233,0,0,0,114,80,1,0,0,114,86,1, + 0,0,114,234,0,0,0,114,89,1,0,0,114,90,1,0, + 0,114,93,1,0,0,114,226,0,0,0,114,229,0,0,0, + 114,95,1,0,0,114,7,0,0,0,114,7,0,0,0,114, + 7,0,0,0,114,8,0,0,0,114,79,1,0,0,46,5, + 0,0,115,36,0,0,0,8,0,4,2,2,2,10,1,2, + 12,10,1,2,12,10,1,2,21,10,1,2,20,12,1,2, + 31,12,1,2,23,12,1,2,15,14,1,114,79,1,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,64,0,0,0,115,90,0,0,0,101,0, + 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, + 90,4,100,4,100,5,132,0,90,5,101,6,90,7,100,6, + 100,7,132,0,90,8,100,8,100,9,132,0,90,9,100,19, + 100,11,100,12,132,1,90,10,100,13,100,14,132,0,90,11, + 101,12,100,15,100,16,132,0,131,1,90,13,100,17,100,18, + 132,0,90,14,100,10,83,0,41,20,218,10,70,105,108,101, + 70,105,110,100,101,114,122,172,70,105,108,101,45,98,97,115, + 101,100,32,102,105,110,100,101,114,46,10,10,32,32,32,32, + 73,110,116,101,114,97,99,116,105,111,110,115,32,119,105,116, + 104,32,116,104,101,32,102,105,108,101,32,115,121,115,116,101, + 109,32,97,114,101,32,99,97,99,104,101,100,32,102,111,114, + 32,112,101,114,102,111,114,109,97,110,99,101,44,32,98,101, + 105,110,103,10,32,32,32,32,114,101,102,114,101,115,104,101, + 100,32,119,104,101,110,32,116,104,101,32,100,105,114,101,99, + 116,111,114,121,32,116,104,101,32,102,105,110,100,101,114,32, + 105,115,32,104,97,110,100,108,105,110,103,32,104,97,115,32, + 98,101,101,110,32,109,111,100,105,102,105,101,100,46,10,10, + 32,32,32,32,99,2,0,0,0,0,0,0,0,0,0,0, + 0,5,0,0,0,6,0,0,0,7,0,0,0,115,112,0, + 0,0,103,0,125,3,124,2,68,0,93,16,92,2,137,0, + 125,4,124,3,160,0,135,0,102,1,100,1,100,2,132,8, + 124,4,68,0,131,1,161,1,1,0,113,4,124,3,124,0, + 95,1,124,1,112,27,100,3,124,0,95,2,116,3,124,0, + 106,2,131,1,115,43,116,4,116,5,160,6,161,0,124,0, + 106,2,131,2,124,0,95,2,100,4,124,0,95,7,116,8, + 131,0,124,0,95,9,116,8,131,0,124,0,95,10,100,5, + 83,0,41,6,122,154,73,110,105,116,105,97,108,105,122,101, + 32,119,105,116,104,32,116,104,101,32,112,97,116,104,32,116, + 111,32,115,101,97,114,99,104,32,111,110,32,97,110,100,32, + 97,32,118,97,114,105,97,98,108,101,32,110,117,109,98,101, + 114,32,111,102,10,32,32,32,32,32,32,32,32,50,45,116, + 117,112,108,101,115,32,99,111,110,116,97,105,110,105,110,103, + 32,116,104,101,32,108,111,97,100,101,114,32,97,110,100,32, + 116,104,101,32,102,105,108,101,32,115,117,102,102,105,120,101, + 115,32,116,104,101,32,108,111,97,100,101,114,10,32,32,32, + 32,32,32,32,32,114,101,99,111,103,110,105,122,101,115,46, 99,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,83,0,0,0,115,20,0,0,0,104,0, - 124,0,93,6,125,1,124,1,160,0,161,0,146,2,113,2, - 83,0,114,7,0,0,0,41,1,114,131,0,0,0,41,2, - 114,5,0,0,0,90,2,102,110,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,13,0,0,0,80,6,0, - 0,115,2,0,0,0,20,0,122,41,70,105,108,101,70,105, - 110,100,101,114,46,95,102,105,108,108,95,99,97,99,104,101, - 46,60,108,111,99,97,108,115,62,46,60,115,101,116,99,111, - 109,112,62,78,41,18,114,65,0,0,0,114,18,0,0,0, - 90,7,108,105,115,116,100,105,114,114,82,0,0,0,114,87, - 1,0,0,218,15,80,101,114,109,105,115,115,105,111,110,69, - 114,114,111,114,218,18,78,111,116,65,68,105,114,101,99,116, - 111,114,121,69,114,114,111,114,114,15,0,0,0,114,25,0, - 0,0,114,26,0,0,0,114,100,1,0,0,114,101,1,0, - 0,114,126,0,0,0,114,89,0,0,0,114,131,0,0,0, - 218,3,97,100,100,114,27,0,0,0,114,102,1,0,0,41, - 9,114,143,0,0,0,114,65,0,0,0,90,8,99,111,110, - 116,101,110,116,115,90,21,108,111,119,101,114,95,115,117,102, - 102,105,120,95,99,111,110,116,101,110,116,115,114,72,1,0, - 0,114,141,0,0,0,114,56,1,0,0,114,44,1,0,0, - 90,8,110,101,119,95,110,97,109,101,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,104,1,0,0,51,6, - 0,0,115,38,0,0,0,6,2,2,1,22,1,18,1,8, - 3,2,253,12,6,12,1,6,7,8,1,16,1,4,1,18, - 1,4,2,12,1,6,1,12,1,20,1,4,255,122,22,70, - 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95, - 99,97,99,104,101,99,1,0,0,0,0,0,0,0,0,0, - 0,0,3,0,0,0,3,0,0,0,7,0,0,0,115,18, - 0,0,0,135,0,135,1,102,2,100,1,100,2,132,8,125, - 2,124,2,83,0,41,3,97,20,1,0,0,65,32,99,108, - 97,115,115,32,109,101,116,104,111,100,32,119,104,105,99,104, - 32,114,101,116,117,114,110,115,32,97,32,99,108,111,115,117, - 114,101,32,116,111,32,117,115,101,32,111,110,32,115,121,115, - 46,112,97,116,104,95,104,111,111,107,10,32,32,32,32,32, - 32,32,32,119,104,105,99,104,32,119,105,108,108,32,114,101, - 116,117,114,110,32,97,110,32,105,110,115,116,97,110,99,101, - 32,117,115,105,110,103,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,32,108,111,97,100,101,114,115,32,97,110,100, - 32,116,104,101,32,112,97,116,104,10,32,32,32,32,32,32, - 32,32,99,97,108,108,101,100,32,111,110,32,116,104,101,32, - 99,108,111,115,117,114,101,46,10,10,32,32,32,32,32,32, - 32,32,73,102,32,116,104,101,32,112,97,116,104,32,99,97, + 0,3,0,0,0,51,0,0,0,115,24,0,0,0,129,0, + 124,0,93,7,125,1,124,1,136,0,102,2,86,0,1,0, + 113,2,100,0,83,0,114,69,0,0,0,114,7,0,0,0, + 114,43,1,0,0,169,1,114,164,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,9,0,0,0,220,5,0,0,115, + 4,0,0,0,2,128,22,0,122,38,70,105,108,101,70,105, + 110,100,101,114,46,95,95,105,110,105,116,95,95,46,60,108, + 111,99,97,108,115,62,46,60,103,101,110,101,120,112,114,62, + 114,97,0,0,0,114,130,0,0,0,78,41,11,114,191,0, + 0,0,218,8,95,108,111,97,100,101,114,115,114,65,0,0, + 0,114,86,0,0,0,114,67,0,0,0,114,18,0,0,0, + 114,82,0,0,0,218,11,95,112,97,116,104,95,109,116,105, + 109,101,218,3,115,101,116,218,11,95,112,97,116,104,95,99, + 97,99,104,101,218,19,95,114,101,108,97,120,101,100,95,112, + 97,116,104,95,99,97,99,104,101,41,5,114,143,0,0,0, + 114,65,0,0,0,218,14,108,111,97,100,101,114,95,100,101, + 116,97,105,108,115,90,7,108,111,97,100,101,114,115,114,212, + 0,0,0,114,7,0,0,0,114,97,1,0,0,114,8,0, + 0,0,114,236,0,0,0,214,5,0,0,115,20,0,0,0, + 4,4,12,1,26,1,6,1,10,2,10,1,18,1,6,1, + 8,1,12,1,122,19,70,105,108,101,70,105,110,100,101,114, + 46,95,95,105,110,105,116,95,95,99,1,0,0,0,0,0, + 0,0,0,0,0,0,1,0,0,0,2,0,0,0,67,0, + 0,0,115,10,0,0,0,100,1,124,0,95,0,100,2,83, + 0,41,3,122,31,73,110,118,97,108,105,100,97,116,101,32, + 116,104,101,32,100,105,114,101,99,116,111,114,121,32,109,116, + 105,109,101,46,114,130,0,0,0,78,41,1,114,99,1,0, + 0,114,21,1,0,0,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,80,1,0,0,230,5,0,0,114,81, + 0,0,0,122,28,70,105,108,101,70,105,110,100,101,114,46, + 105,110,118,97,108,105,100,97,116,101,95,99,97,99,104,101, + 115,99,2,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,4,0,0,0,67,0,0,0,115,54,0,0,0,116, + 0,160,1,100,1,116,2,161,2,1,0,124,0,160,3,124, + 1,161,1,125,2,124,2,100,2,117,0,114,19,100,2,103, + 0,102,2,83,0,124,2,106,4,124,2,106,5,112,25,103, + 0,102,2,83,0,41,3,122,197,84,114,121,32,116,111,32, + 102,105,110,100,32,97,32,108,111,97,100,101,114,32,102,111, + 114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, + 109,111,100,117,108,101,44,32,111,114,32,116,104,101,32,110, + 97,109,101,115,112,97,99,101,10,32,32,32,32,32,32,32, + 32,112,97,99,107,97,103,101,32,112,111,114,116,105,111,110, + 115,46,32,82,101,116,117,114,110,115,32,40,108,111,97,100, + 101,114,44,32,108,105,115,116,45,111,102,45,112,111,114,116, + 105,111,110,115,41,46,10,10,32,32,32,32,32,32,32,32, + 84,104,105,115,32,109,101,116,104,111,100,32,105,115,32,100, + 101,112,114,101,99,97,116,101,100,46,32,32,85,115,101,32, + 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, + 101,97,100,46,10,10,32,32,32,32,32,32,32,32,122,101, + 70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,95, + 108,111,97,100,101,114,40,41,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,32,97,110,100,32,115,108,97,116,101, + 100,32,102,111,114,32,114,101,109,111,118,97,108,32,105,110, + 32,80,121,116,104,111,110,32,51,46,49,50,59,32,117,115, + 101,32,102,105,110,100,95,115,112,101,99,40,41,32,105,110, + 115,116,101,97,100,78,41,6,114,99,0,0,0,114,100,0, + 0,0,114,101,0,0,0,114,226,0,0,0,114,164,0,0, + 0,114,202,0,0,0,41,3,114,143,0,0,0,114,163,0, + 0,0,114,210,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,161,0,0,0,236,5,0,0,115, + 14,0,0,0,6,7,2,2,4,254,10,3,8,1,8,1, + 16,1,122,22,70,105,108,101,70,105,110,100,101,114,46,102, + 105,110,100,95,108,111,97,100,101,114,99,6,0,0,0,0, + 0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,67, + 0,0,0,115,26,0,0,0,124,1,124,2,124,3,131,2, + 125,6,116,0,124,2,124,3,124,6,124,4,100,1,141,4, + 83,0,41,2,78,114,201,0,0,0,41,1,114,213,0,0, + 0,41,7,114,143,0,0,0,114,211,0,0,0,114,163,0, + 0,0,114,65,0,0,0,90,4,115,109,115,108,114,225,0, + 0,0,114,164,0,0,0,114,7,0,0,0,114,7,0,0, + 0,114,8,0,0,0,114,93,1,0,0,251,5,0,0,115, + 8,0,0,0,10,1,8,1,2,1,6,255,122,20,70,105, + 108,101,70,105,110,100,101,114,46,95,103,101,116,95,115,112, + 101,99,78,99,3,0,0,0,0,0,0,0,0,0,0,0, + 14,0,0,0,9,0,0,0,67,0,0,0,115,122,1,0, + 0,100,1,125,3,124,1,160,0,100,2,161,1,100,3,25, + 0,125,4,122,12,116,1,124,0,106,2,112,17,116,3,160, + 4,161,0,131,1,106,5,125,5,87,0,110,11,4,0,116, + 6,121,32,1,0,1,0,1,0,100,4,125,5,89,0,110, + 1,119,0,124,5,124,0,106,7,107,3,114,45,124,0,160, + 8,161,0,1,0,124,5,124,0,95,7,116,9,131,0,114, + 56,124,0,106,10,125,6,124,4,160,11,161,0,125,7,110, + 5,124,0,106,12,125,6,124,4,125,7,124,7,124,6,118, + 0,114,108,116,13,124,0,106,2,124,4,131,2,125,8,124, + 0,106,14,68,0,93,29,92,2,125,9,125,10,100,5,124, + 9,23,0,125,11,116,13,124,8,124,11,131,2,125,12,116, + 15,124,12,131,1,114,103,124,0,160,16,124,10,124,1,124, + 12,124,8,103,1,124,2,161,5,2,0,1,0,83,0,113, + 74,116,17,124,8,131,1,125,3,124,0,106,14,68,0,93, + 55,92,2,125,9,125,10,122,10,116,13,124,0,106,2,124, + 4,124,9,23,0,131,2,125,12,87,0,110,11,4,0,116, + 18,121,136,1,0,1,0,1,0,89,0,1,0,100,6,83, + 0,119,0,116,19,106,20,100,7,124,12,100,3,100,8,141, + 3,1,0,124,7,124,9,23,0,124,6,118,0,114,166,116, + 15,124,12,131,1,114,166,124,0,160,16,124,10,124,1,124, + 12,100,6,124,2,161,5,2,0,1,0,83,0,113,111,124, + 3,114,187,116,19,160,20,100,9,124,8,161,2,1,0,116, + 19,160,21,124,1,100,6,161,2,125,13,124,8,103,1,124, + 13,95,22,124,13,83,0,100,6,83,0,41,10,122,111,84, + 114,121,32,116,111,32,102,105,110,100,32,97,32,115,112,101, + 99,32,102,111,114,32,116,104,101,32,115,112,101,99,105,102, + 105,101,100,32,109,111,100,117,108,101,46,10,10,32,32,32, + 32,32,32,32,32,82,101,116,117,114,110,115,32,116,104,101, + 32,109,97,116,99,104,105,110,103,32,115,112,101,99,44,32, + 111,114,32,78,111,110,101,32,105,102,32,110,111,116,32,102, + 111,117,110,100,46,10,32,32,32,32,32,32,32,32,70,114, + 97,0,0,0,114,44,0,0,0,114,130,0,0,0,114,236, + 0,0,0,78,122,9,116,114,121,105,110,103,32,123,125,41, + 1,90,9,118,101,114,98,111,115,105,116,121,122,25,112,111, + 115,115,105,98,108,101,32,110,97,109,101,115,112,97,99,101, + 32,102,111,114,32,123,125,41,23,114,104,0,0,0,114,75, + 0,0,0,114,65,0,0,0,114,18,0,0,0,114,82,0, + 0,0,114,35,1,0,0,114,76,0,0,0,114,99,1,0, + 0,218,11,95,102,105,108,108,95,99,97,99,104,101,114,21, + 0,0,0,114,102,1,0,0,114,131,0,0,0,114,101,1, + 0,0,114,67,0,0,0,114,98,1,0,0,114,80,0,0, + 0,114,93,1,0,0,114,83,0,0,0,114,111,0,0,0, + 114,159,0,0,0,114,173,0,0,0,114,207,0,0,0,114, + 202,0,0,0,41,14,114,143,0,0,0,114,163,0,0,0, + 114,225,0,0,0,90,12,105,115,95,110,97,109,101,115,112, + 97,99,101,90,11,116,97,105,108,95,109,111,100,117,108,101, + 114,193,0,0,0,90,5,99,97,99,104,101,90,12,99,97, + 99,104,101,95,109,111,100,117,108,101,90,9,98,97,115,101, + 95,112,97,116,104,114,44,1,0,0,114,211,0,0,0,90, + 13,105,110,105,116,95,102,105,108,101,110,97,109,101,90,9, + 102,117,108,108,95,112,97,116,104,114,210,0,0,0,114,7, + 0,0,0,114,7,0,0,0,114,8,0,0,0,114,226,0, + 0,0,0,6,0,0,115,86,0,0,0,4,5,14,1,2, + 1,24,1,12,1,8,1,2,255,10,2,8,1,6,1,6, + 2,6,1,10,1,6,2,4,1,8,2,12,1,14,1,8, + 1,10,1,8,1,24,1,2,255,8,5,14,2,2,1,20, + 1,12,1,8,1,2,255,16,2,12,1,8,1,10,1,4, + 1,8,255,2,128,4,2,12,1,12,1,8,1,4,1,4, + 1,122,20,70,105,108,101,70,105,110,100,101,114,46,102,105, + 110,100,95,115,112,101,99,99,1,0,0,0,0,0,0,0, + 0,0,0,0,9,0,0,0,10,0,0,0,67,0,0,0, + 115,192,0,0,0,124,0,106,0,125,1,122,11,116,1,160, + 2,124,1,112,11,116,1,160,3,161,0,161,1,125,2,87, + 0,110,14,4,0,116,4,116,5,116,6,102,3,121,28,1, + 0,1,0,1,0,103,0,125,2,89,0,110,1,119,0,116, + 7,106,8,160,9,100,1,161,1,115,41,116,10,124,2,131, + 1,124,0,95,11,110,37,116,10,131,0,125,3,124,2,68, + 0,93,28,125,4,124,4,160,12,100,2,161,1,92,3,125, + 5,125,6,125,7,124,6,114,67,100,3,160,13,124,5,124, + 7,160,14,161,0,161,2,125,8,110,2,124,5,125,8,124, + 3,160,15,124,8,161,1,1,0,113,46,124,3,124,0,95, + 11,116,7,106,8,160,9,116,16,161,1,114,94,100,4,100, + 5,132,0,124,2,68,0,131,1,124,0,95,17,100,6,83, + 0,100,6,83,0,41,7,122,68,70,105,108,108,32,116,104, + 101,32,99,97,99,104,101,32,111,102,32,112,111,116,101,110, + 116,105,97,108,32,109,111,100,117,108,101,115,32,97,110,100, + 32,112,97,99,107,97,103,101,115,32,102,111,114,32,116,104, + 105,115,32,100,105,114,101,99,116,111,114,121,46,114,14,0, + 0,0,114,97,0,0,0,114,88,0,0,0,99,1,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, + 0,83,0,0,0,115,20,0,0,0,104,0,124,0,93,6, + 125,1,124,1,160,0,161,0,146,2,113,2,83,0,114,7, + 0,0,0,41,1,114,131,0,0,0,41,2,114,5,0,0, + 0,90,2,102,110,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,114,13,0,0,0,80,6,0,0,115,2,0, + 0,0,20,0,122,41,70,105,108,101,70,105,110,100,101,114, + 46,95,102,105,108,108,95,99,97,99,104,101,46,60,108,111, + 99,97,108,115,62,46,60,115,101,116,99,111,109,112,62,78, + 41,18,114,65,0,0,0,114,18,0,0,0,90,7,108,105, + 115,116,100,105,114,114,82,0,0,0,114,87,1,0,0,218, + 15,80,101,114,109,105,115,115,105,111,110,69,114,114,111,114, + 218,18,78,111,116,65,68,105,114,101,99,116,111,114,121,69, + 114,114,111,114,114,15,0,0,0,114,25,0,0,0,114,26, + 0,0,0,114,100,1,0,0,114,101,1,0,0,114,126,0, + 0,0,114,89,0,0,0,114,131,0,0,0,218,3,97,100, + 100,114,27,0,0,0,114,102,1,0,0,41,9,114,143,0, + 0,0,114,65,0,0,0,90,8,99,111,110,116,101,110,116, + 115,90,21,108,111,119,101,114,95,115,117,102,102,105,120,95, + 99,111,110,116,101,110,116,115,114,72,1,0,0,114,141,0, + 0,0,114,56,1,0,0,114,44,1,0,0,90,8,110,101, + 119,95,110,97,109,101,114,7,0,0,0,114,7,0,0,0, + 114,8,0,0,0,114,104,1,0,0,51,6,0,0,115,38, + 0,0,0,6,2,2,1,22,1,18,1,8,3,2,253,12, + 6,12,1,6,7,8,1,16,1,4,1,18,1,4,2,12, + 1,6,1,12,1,20,1,4,255,122,22,70,105,108,101,70, + 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, + 101,99,1,0,0,0,0,0,0,0,0,0,0,0,3,0, + 0,0,3,0,0,0,7,0,0,0,115,18,0,0,0,135, + 0,135,1,102,2,100,1,100,2,132,8,125,2,124,2,83, + 0,41,3,97,20,1,0,0,65,32,99,108,97,115,115,32, + 109,101,116,104,111,100,32,119,104,105,99,104,32,114,101,116, + 117,114,110,115,32,97,32,99,108,111,115,117,114,101,32,116, + 111,32,117,115,101,32,111,110,32,115,121,115,46,112,97,116, + 104,95,104,111,111,107,10,32,32,32,32,32,32,32,32,119, + 104,105,99,104,32,119,105,108,108,32,114,101,116,117,114,110, + 32,97,110,32,105,110,115,116,97,110,99,101,32,117,115,105, + 110,103,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,108,111,97,100,101,114,115,32,97,110,100,32,116,104,101, + 32,112,97,116,104,10,32,32,32,32,32,32,32,32,99,97, 108,108,101,100,32,111,110,32,116,104,101,32,99,108,111,115, - 117,114,101,32,105,115,32,110,111,116,32,97,32,100,105,114, - 101,99,116,111,114,121,44,32,73,109,112,111,114,116,69,114, - 114,111,114,32,105,115,10,32,32,32,32,32,32,32,32,114, - 97,105,115,101,100,46,10,10,32,32,32,32,32,32,32,32, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,4,0,0,0,19,0,0,0,115,36,0,0,0,116,0, - 124,0,131,1,115,10,116,1,100,1,124,0,100,2,141,2, - 130,1,136,0,124,0,103,1,136,1,162,1,82,0,142,0, - 83,0,41,3,122,45,80,97,116,104,32,104,111,111,107,32, - 102,111,114,32,105,109,112,111,114,116,108,105,98,46,109,97, - 99,104,105,110,101,114,121,46,70,105,108,101,70,105,110,100, - 101,114,46,122,30,111,110,108,121,32,100,105,114,101,99,116, - 111,114,105,101,115,32,97,114,101,32,115,117,112,112,111,114, - 116,101,100,114,71,0,0,0,41,2,114,83,0,0,0,114, - 142,0,0,0,114,71,0,0,0,169,2,114,221,0,0,0, - 114,103,1,0,0,114,7,0,0,0,114,8,0,0,0,218, - 24,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, - 105,108,101,70,105,110,100,101,114,92,6,0,0,115,6,0, - 0,0,8,2,12,1,16,1,122,54,70,105,108,101,70,105, - 110,100,101,114,46,112,97,116,104,95,104,111,111,107,46,60, - 108,111,99,97,108,115,62,46,112,97,116,104,95,104,111,111, - 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, - 114,7,0,0,0,41,3,114,221,0,0,0,114,103,1,0, - 0,114,109,1,0,0,114,7,0,0,0,114,108,1,0,0, - 114,8,0,0,0,218,9,112,97,116,104,95,104,111,111,107, - 82,6,0,0,115,4,0,0,0,14,10,4,6,122,20,70, - 105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104, - 111,111,107,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,114,69,1,0, - 0,41,2,78,122,16,70,105,108,101,70,105,110,100,101,114, - 40,123,33,114,125,41,41,2,114,89,0,0,0,114,65,0, - 0,0,114,21,1,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,70,1,0,0,100,6,0,0,114, - 63,1,0,0,122,19,70,105,108,101,70,105,110,100,101,114, - 46,95,95,114,101,112,114,95,95,114,69,0,0,0,41,15, - 114,150,0,0,0,114,149,0,0,0,114,151,0,0,0,114, - 152,0,0,0,114,236,0,0,0,114,80,1,0,0,114,167, - 0,0,0,114,229,0,0,0,114,161,0,0,0,114,93,1, - 0,0,114,226,0,0,0,114,104,1,0,0,114,234,0,0, - 0,114,110,1,0,0,114,70,1,0,0,114,7,0,0,0, - 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 96,1,0,0,205,5,0,0,115,24,0,0,0,8,0,4, - 2,8,7,8,16,4,4,8,2,8,15,10,5,8,51,2, - 31,10,1,12,17,114,96,1,0,0,99,4,0,0,0,0, - 0,0,0,0,0,0,0,6,0,0,0,8,0,0,0,67, - 0,0,0,115,144,0,0,0,124,0,160,0,100,1,161,1, - 125,4,124,0,160,0,100,2,161,1,125,5,124,4,115,33, - 124,5,114,18,124,5,106,1,125,4,110,15,124,2,124,3, - 107,2,114,28,116,2,124,1,124,2,131,2,125,4,110,5, - 116,3,124,1,124,2,131,2,125,4,124,5,115,42,116,4, - 124,1,124,2,124,4,100,3,141,3,125,5,122,19,124,5, - 124,0,100,2,60,0,124,4,124,0,100,1,60,0,124,2, - 124,0,100,4,60,0,124,3,124,0,100,5,60,0,87,0, - 100,0,83,0,4,0,116,5,121,71,1,0,1,0,1,0, - 89,0,100,0,83,0,119,0,41,6,78,218,10,95,95,108, - 111,97,100,101,114,95,95,218,8,95,95,115,112,101,99,95, - 95,114,97,1,0,0,90,8,95,95,102,105,108,101,95,95, - 90,10,95,95,99,97,99,104,101,100,95,95,41,6,218,3, - 103,101,116,114,164,0,0,0,114,41,1,0,0,114,34,1, - 0,0,114,213,0,0,0,218,9,69,120,99,101,112,116,105, - 111,110,41,6,90,2,110,115,114,141,0,0,0,90,8,112, - 97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,97, - 109,101,114,164,0,0,0,114,210,0,0,0,114,7,0,0, - 0,114,7,0,0,0,114,8,0,0,0,218,14,95,102,105, - 120,95,117,112,95,109,111,100,117,108,101,106,6,0,0,115, - 36,0,0,0,10,2,10,1,4,1,4,1,8,1,8,1, - 12,1,10,2,4,1,14,1,2,1,8,1,8,1,8,1, - 14,1,12,1,6,2,2,254,114,115,1,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,3,0,0,0,3,0, - 0,0,67,0,0,0,115,38,0,0,0,116,0,116,1,160, - 2,161,0,102,2,125,0,116,3,116,4,102,2,125,1,116, - 5,116,6,102,2,125,2,124,0,124,1,124,2,103,3,83, - 0,41,1,122,95,82,101,116,117,114,110,115,32,97,32,108, - 105,115,116,32,111,102,32,102,105,108,101,45,98,97,115,101, - 100,32,109,111,100,117,108,101,32,108,111,97,100,101,114,115, - 46,10,10,32,32,32,32,69,97,99,104,32,105,116,101,109, - 32,105,115,32,97,32,116,117,112,108,101,32,40,108,111,97, - 100,101,114,44,32,115,117,102,102,105,120,101,115,41,46,10, - 32,32,32,32,41,7,114,30,1,0,0,114,187,0,0,0, - 218,18,101,120,116,101,110,115,105,111,110,95,115,117,102,102, - 105,120,101,115,114,34,1,0,0,114,127,0,0,0,114,41, - 1,0,0,114,113,0,0,0,41,3,90,10,101,120,116,101, - 110,115,105,111,110,115,90,6,115,111,117,114,99,101,90,8, - 98,121,116,101,99,111,100,101,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,208,0,0,0,129,6,0,0, - 115,8,0,0,0,12,5,8,1,8,1,10,1,114,208,0, - 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,1,0,0,0,67,0,0,0,115,8,0,0,0, - 124,0,97,0,100,0,83,0,114,69,0,0,0,41,1,114, - 159,0,0,0,41,1,218,17,95,98,111,111,116,115,116,114, - 97,112,95,109,111,100,117,108,101,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,21,95,115,101,116,95,98, - 111,111,116,115,116,114,97,112,95,109,111,100,117,108,101,140, - 6,0,0,115,2,0,0,0,8,2,114,118,1,0,0,99, - 1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,67,0,0,0,115,50,0,0,0,116,0,124, - 0,131,1,1,0,116,1,131,0,125,1,116,2,106,3,160, - 4,116,5,106,6,124,1,142,0,103,1,161,1,1,0,116, - 2,106,7,160,8,116,9,161,1,1,0,100,1,83,0,41, - 2,122,41,73,110,115,116,97,108,108,32,116,104,101,32,112, - 97,116,104,45,98,97,115,101,100,32,105,109,112,111,114,116, - 32,99,111,109,112,111,110,101,110,116,115,46,78,41,10,114, - 118,1,0,0,114,208,0,0,0,114,15,0,0,0,114,85, - 1,0,0,114,191,0,0,0,114,96,1,0,0,114,110,1, - 0,0,218,9,109,101,116,97,95,112,97,116,104,114,61,0, - 0,0,114,79,1,0,0,41,2,114,117,1,0,0,90,17, - 115,117,112,112,111,114,116,101,100,95,108,111,97,100,101,114, - 115,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 218,8,95,105,110,115,116,97,108,108,145,6,0,0,115,8, - 0,0,0,8,2,6,1,20,1,16,1,114,120,1,0,0, - 41,1,114,87,0,0,0,114,69,0,0,0,41,3,78,78, - 78,41,2,114,0,0,0,0,114,0,0,0,0,41,1,84, - 41,85,114,152,0,0,0,114,159,0,0,0,114,187,0,0, - 0,114,91,0,0,0,114,15,0,0,0,114,99,0,0,0, - 114,184,0,0,0,114,25,0,0,0,114,231,0,0,0,90, - 2,110,116,114,18,0,0,0,114,215,0,0,0,90,5,112, - 111,115,105,120,114,50,0,0,0,218,3,97,108,108,114,59, - 0,0,0,114,136,0,0,0,114,57,0,0,0,114,62,0, - 0,0,90,20,95,112,97,116,104,115,101,112,115,95,119,105, - 116,104,95,99,111,108,111,110,114,28,0,0,0,90,37,95, - 67,65,83,69,95,73,78,83,69,78,83,73,84,73,86,69, - 95,80,76,65,84,70,79,82,77,83,95,66,89,84,69,83, - 95,75,69,89,114,27,0,0,0,114,29,0,0,0,114,21, - 0,0,0,114,36,0,0,0,114,42,0,0,0,114,45,0, - 0,0,114,67,0,0,0,114,74,0,0,0,114,75,0,0, - 0,114,79,0,0,0,114,80,0,0,0,114,83,0,0,0, - 114,86,0,0,0,114,95,0,0,0,218,4,116,121,112,101, - 218,8,95,95,99,111,100,101,95,95,114,186,0,0,0,114, - 34,0,0,0,114,172,0,0,0,114,33,0,0,0,114,39, - 0,0,0,114,8,1,0,0,114,116,0,0,0,114,112,0, - 0,0,114,127,0,0,0,114,61,0,0,0,114,116,1,0, - 0,114,232,0,0,0,114,113,0,0,0,90,23,68,69,66, - 85,71,95,66,89,84,69,67,79,68,69,95,83,85,70,70, - 73,88,69,83,90,27,79,80,84,73,77,73,90,69,68,95, - 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, - 83,114,121,0,0,0,114,128,0,0,0,114,135,0,0,0, - 114,137,0,0,0,114,139,0,0,0,114,160,0,0,0,114, - 167,0,0,0,114,176,0,0,0,114,180,0,0,0,114,182, - 0,0,0,114,189,0,0,0,114,194,0,0,0,114,195,0, - 0,0,114,200,0,0,0,218,6,111,98,106,101,99,116,114, - 209,0,0,0,114,213,0,0,0,114,214,0,0,0,114,235, - 0,0,0,114,249,0,0,0,114,11,1,0,0,114,34,1, - 0,0,114,41,1,0,0,114,30,1,0,0,114,47,1,0, - 0,114,75,1,0,0,114,79,1,0,0,114,96,1,0,0, - 114,115,1,0,0,114,208,0,0,0,114,118,1,0,0,114, - 120,1,0,0,114,7,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,218,8,60,109,111,100,117,108, - 101,62,1,0,0,0,115,180,0,0,0,4,0,4,22,8, - 3,8,1,8,1,8,1,8,1,10,3,4,1,8,1,10, - 1,8,2,4,3,10,1,6,2,22,2,8,1,8,1,10, - 1,14,1,4,4,4,1,2,1,2,1,4,255,8,4,6, - 16,8,3,8,5,8,5,4,6,10,1,8,30,8,6,8, - 8,8,10,8,9,8,5,4,7,10,1,8,8,10,5,10, - 22,0,127,16,30,12,1,4,2,4,1,6,2,4,1,10, - 1,8,2,6,2,8,2,16,2,8,71,8,40,8,19,8, - 12,8,12,8,31,8,20,8,33,8,28,10,24,10,13,10, - 10,8,11,6,14,4,3,2,1,12,255,14,73,14,67,16, - 30,0,127,14,17,18,50,18,45,18,25,14,53,14,69,14, - 49,0,127,14,32,0,127,10,30,8,23,8,11,12,5, + 117,114,101,46,10,10,32,32,32,32,32,32,32,32,73,102, + 32,116,104,101,32,112,97,116,104,32,99,97,108,108,101,100, + 32,111,110,32,116,104,101,32,99,108,111,115,117,114,101,32, + 105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111, + 114,121,44,32,73,109,112,111,114,116,69,114,114,111,114,32, + 105,115,10,32,32,32,32,32,32,32,32,114,97,105,115,101, + 100,46,10,10,32,32,32,32,32,32,32,32,99,1,0,0, + 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, + 0,19,0,0,0,115,36,0,0,0,116,0,124,0,131,1, + 115,10,116,1,100,1,124,0,100,2,141,2,130,1,136,0, + 124,0,103,1,136,1,162,1,82,0,142,0,83,0,41,3, + 122,45,80,97,116,104,32,104,111,111,107,32,102,111,114,32, + 105,109,112,111,114,116,108,105,98,46,109,97,99,104,105,110, + 101,114,121,46,70,105,108,101,70,105,110,100,101,114,46,122, + 30,111,110,108,121,32,100,105,114,101,99,116,111,114,105,101, + 115,32,97,114,101,32,115,117,112,112,111,114,116,101,100,114, + 71,0,0,0,41,2,114,83,0,0,0,114,142,0,0,0, + 114,71,0,0,0,169,2,114,221,0,0,0,114,103,1,0, + 0,114,7,0,0,0,114,8,0,0,0,218,24,112,97,116, + 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, + 105,110,100,101,114,92,6,0,0,115,6,0,0,0,8,2, + 12,1,16,1,122,54,70,105,108,101,70,105,110,100,101,114, + 46,112,97,116,104,95,104,111,111,107,46,60,108,111,99,97, + 108,115,62,46,112,97,116,104,95,104,111,111,107,95,102,111, + 114,95,70,105,108,101,70,105,110,100,101,114,114,7,0,0, + 0,41,3,114,221,0,0,0,114,103,1,0,0,114,109,1, + 0,0,114,7,0,0,0,114,108,1,0,0,114,8,0,0, + 0,218,9,112,97,116,104,95,104,111,111,107,82,6,0,0, + 115,4,0,0,0,14,10,4,6,122,20,70,105,108,101,70, + 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,114,69,1,0,0,41,2,78, + 122,16,70,105,108,101,70,105,110,100,101,114,40,123,33,114, + 125,41,41,2,114,89,0,0,0,114,65,0,0,0,114,21, + 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,70,1,0,0,100,6,0,0,114,63,1,0,0, + 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,114, + 101,112,114,95,95,114,69,0,0,0,41,15,114,150,0,0, + 0,114,149,0,0,0,114,151,0,0,0,114,152,0,0,0, + 114,236,0,0,0,114,80,1,0,0,114,167,0,0,0,114, + 229,0,0,0,114,161,0,0,0,114,93,1,0,0,114,226, + 0,0,0,114,104,1,0,0,114,234,0,0,0,114,110,1, + 0,0,114,70,1,0,0,114,7,0,0,0,114,7,0,0, + 0,114,7,0,0,0,114,8,0,0,0,114,96,1,0,0, + 205,5,0,0,115,24,0,0,0,8,0,4,2,8,7,8, + 16,4,4,8,2,8,15,10,5,8,51,2,31,10,1,12, + 17,114,96,1,0,0,99,4,0,0,0,0,0,0,0,0, + 0,0,0,6,0,0,0,8,0,0,0,67,0,0,0,115, + 144,0,0,0,124,0,160,0,100,1,161,1,125,4,124,0, + 160,0,100,2,161,1,125,5,124,4,115,33,124,5,114,18, + 124,5,106,1,125,4,110,15,124,2,124,3,107,2,114,28, + 116,2,124,1,124,2,131,2,125,4,110,5,116,3,124,1, + 124,2,131,2,125,4,124,5,115,42,116,4,124,1,124,2, + 124,4,100,3,141,3,125,5,122,19,124,5,124,0,100,2, + 60,0,124,4,124,0,100,1,60,0,124,2,124,0,100,4, + 60,0,124,3,124,0,100,5,60,0,87,0,100,0,83,0, + 4,0,116,5,121,71,1,0,1,0,1,0,89,0,100,0, + 83,0,119,0,41,6,78,218,10,95,95,108,111,97,100,101, + 114,95,95,218,8,95,95,115,112,101,99,95,95,114,97,1, + 0,0,90,8,95,95,102,105,108,101,95,95,90,10,95,95, + 99,97,99,104,101,100,95,95,41,6,218,3,103,101,116,114, + 164,0,0,0,114,41,1,0,0,114,34,1,0,0,114,213, + 0,0,0,218,9,69,120,99,101,112,116,105,111,110,41,6, + 90,2,110,115,114,141,0,0,0,90,8,112,97,116,104,110, + 97,109,101,90,9,99,112,97,116,104,110,97,109,101,114,164, + 0,0,0,114,210,0,0,0,114,7,0,0,0,114,7,0, + 0,0,114,8,0,0,0,218,14,95,102,105,120,95,117,112, + 95,109,111,100,117,108,101,106,6,0,0,115,36,0,0,0, + 10,2,10,1,4,1,4,1,8,1,8,1,12,1,10,2, + 4,1,14,1,2,1,8,1,8,1,8,1,14,1,12,1, + 6,2,2,254,114,115,1,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, + 0,0,115,38,0,0,0,116,0,116,1,160,2,161,0,102, + 2,125,0,116,3,116,4,102,2,125,1,116,5,116,6,102, + 2,125,2,124,0,124,1,124,2,103,3,83,0,41,1,122, + 95,82,101,116,117,114,110,115,32,97,32,108,105,115,116,32, + 111,102,32,102,105,108,101,45,98,97,115,101,100,32,109,111, + 100,117,108,101,32,108,111,97,100,101,114,115,46,10,10,32, + 32,32,32,69,97,99,104,32,105,116,101,109,32,105,115,32, + 97,32,116,117,112,108,101,32,40,108,111,97,100,101,114,44, + 32,115,117,102,102,105,120,101,115,41,46,10,32,32,32,32, + 41,7,114,30,1,0,0,114,187,0,0,0,218,18,101,120, + 116,101,110,115,105,111,110,95,115,117,102,102,105,120,101,115, + 114,34,1,0,0,114,127,0,0,0,114,41,1,0,0,114, + 113,0,0,0,41,3,90,10,101,120,116,101,110,115,105,111, + 110,115,90,6,115,111,117,114,99,101,90,8,98,121,116,101, + 99,111,100,101,114,7,0,0,0,114,7,0,0,0,114,8, + 0,0,0,114,208,0,0,0,129,6,0,0,115,8,0,0, + 0,12,5,8,1,8,1,10,1,114,208,0,0,0,99,1, + 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1, + 0,0,0,67,0,0,0,115,8,0,0,0,124,0,97,0, + 100,0,83,0,114,69,0,0,0,41,1,114,159,0,0,0, + 41,1,218,17,95,98,111,111,116,115,116,114,97,112,95,109, + 111,100,117,108,101,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,218,21,95,115,101,116,95,98,111,111,116,115, + 116,114,97,112,95,109,111,100,117,108,101,140,6,0,0,115, + 2,0,0,0,8,2,114,118,1,0,0,99,1,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 67,0,0,0,115,50,0,0,0,116,0,124,0,131,1,1, + 0,116,1,131,0,125,1,116,2,106,3,160,4,116,5,106, + 6,124,1,142,0,103,1,161,1,1,0,116,2,106,7,160, + 8,116,9,161,1,1,0,100,1,83,0,41,2,122,41,73, + 110,115,116,97,108,108,32,116,104,101,32,112,97,116,104,45, + 98,97,115,101,100,32,105,109,112,111,114,116,32,99,111,109, + 112,111,110,101,110,116,115,46,78,41,10,114,118,1,0,0, + 114,208,0,0,0,114,15,0,0,0,114,85,1,0,0,114, + 191,0,0,0,114,96,1,0,0,114,110,1,0,0,218,9, + 109,101,116,97,95,112,97,116,104,114,61,0,0,0,114,79, + 1,0,0,41,2,114,117,1,0,0,90,17,115,117,112,112, + 111,114,116,101,100,95,108,111,97,100,101,114,115,114,7,0, + 0,0,114,7,0,0,0,114,8,0,0,0,218,8,95,105, + 110,115,116,97,108,108,145,6,0,0,115,8,0,0,0,8, + 2,6,1,20,1,16,1,114,120,1,0,0,41,1,114,87, + 0,0,0,114,69,0,0,0,41,3,78,78,78,41,2,114, + 0,0,0,0,114,0,0,0,0,41,1,84,41,85,114,152, + 0,0,0,114,159,0,0,0,114,187,0,0,0,114,91,0, + 0,0,114,15,0,0,0,114,99,0,0,0,114,184,0,0, + 0,114,25,0,0,0,114,231,0,0,0,90,2,110,116,114, + 18,0,0,0,114,215,0,0,0,90,5,112,111,115,105,120, + 114,50,0,0,0,218,3,97,108,108,114,59,0,0,0,114, + 136,0,0,0,114,57,0,0,0,114,62,0,0,0,90,20, + 95,112,97,116,104,115,101,112,115,95,119,105,116,104,95,99, + 111,108,111,110,114,28,0,0,0,90,37,95,67,65,83,69, + 95,73,78,83,69,78,83,73,84,73,86,69,95,80,76,65, + 84,70,79,82,77,83,95,66,89,84,69,83,95,75,69,89, + 114,27,0,0,0,114,29,0,0,0,114,21,0,0,0,114, + 36,0,0,0,114,42,0,0,0,114,45,0,0,0,114,67, + 0,0,0,114,74,0,0,0,114,75,0,0,0,114,79,0, + 0,0,114,80,0,0,0,114,83,0,0,0,114,86,0,0, + 0,114,95,0,0,0,218,4,116,121,112,101,218,8,95,95, + 99,111,100,101,95,95,114,186,0,0,0,114,34,0,0,0, + 114,172,0,0,0,114,33,0,0,0,114,39,0,0,0,114, + 8,1,0,0,114,116,0,0,0,114,112,0,0,0,114,127, + 0,0,0,114,61,0,0,0,114,116,1,0,0,114,232,0, + 0,0,114,113,0,0,0,90,23,68,69,66,85,71,95,66, + 89,84,69,67,79,68,69,95,83,85,70,70,73,88,69,83, + 90,27,79,80,84,73,77,73,90,69,68,95,66,89,84,69, + 67,79,68,69,95,83,85,70,70,73,88,69,83,114,121,0, + 0,0,114,128,0,0,0,114,135,0,0,0,114,137,0,0, + 0,114,139,0,0,0,114,160,0,0,0,114,167,0,0,0, + 114,176,0,0,0,114,180,0,0,0,114,182,0,0,0,114, + 189,0,0,0,114,194,0,0,0,114,195,0,0,0,114,200, + 0,0,0,218,6,111,98,106,101,99,116,114,209,0,0,0, + 114,213,0,0,0,114,214,0,0,0,114,235,0,0,0,114, + 249,0,0,0,114,11,1,0,0,114,34,1,0,0,114,41, + 1,0,0,114,30,1,0,0,114,47,1,0,0,114,75,1, + 0,0,114,79,1,0,0,114,96,1,0,0,114,115,1,0, + 0,114,208,0,0,0,114,118,1,0,0,114,120,1,0,0, + 114,7,0,0,0,114,7,0,0,0,114,7,0,0,0,114, + 8,0,0,0,218,8,60,109,111,100,117,108,101,62,1,0, + 0,0,115,180,0,0,0,4,0,4,22,8,3,8,1,8, + 1,8,1,8,1,10,3,4,1,8,1,10,1,8,2,4, + 3,10,1,6,2,22,2,8,1,8,1,10,1,14,1,4, + 4,4,1,2,1,2,1,4,255,8,4,6,16,8,3,8, + 5,8,5,4,6,10,1,8,30,8,6,8,8,8,10,8, + 9,8,5,4,7,10,1,8,8,10,5,10,22,0,127,16, + 30,12,1,4,2,4,1,6,2,4,1,10,1,8,2,6, + 2,8,2,16,2,8,71,8,40,8,19,8,12,8,12,8, + 31,8,20,8,33,8,28,10,24,10,13,10,10,8,11,6, + 14,4,3,2,1,12,255,14,73,14,67,16,30,0,127,14, + 17,18,50,18,45,18,25,14,53,14,69,14,49,0,127,14, + 32,0,127,10,30,8,23,8,11,12,5, }; diff -Nru python3.10-3.10.7/Python/importlib.h python3.10-3.10.12/Python/importlib.h --- python3.10-3.10.7/Python/importlib.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/importlib.h 2023-06-06 22:30:33.000000000 +0000 @@ -1664,222 +1664,222 @@ 0,0,0,114,231,0,0,0,218,1,120,90,5,119,104,101, 114,101,90,9,102,114,111,109,95,110,97,109,101,90,3,101, 120,99,114,5,0,0,0,114,5,0,0,0,114,6,0,0, - 0,114,234,0,0,0,29,4,0,0,115,56,0,0,0,8, + 0,114,234,0,0,0,29,4,0,0,115,54,0,0,0,8, 10,10,1,4,1,12,1,4,2,10,1,8,1,8,255,8, 2,14,1,10,1,2,1,6,255,2,128,10,2,14,1,2, - 1,14,1,14,1,10,4,16,1,2,255,12,2,2,1,8, - 128,2,249,2,252,4,12,114,234,0,0,0,99,1,0,0, - 0,0,0,0,0,0,0,0,0,3,0,0,0,6,0,0, - 0,67,0,0,0,115,146,0,0,0,124,0,160,0,100,1, - 161,1,125,1,124,0,160,0,100,2,161,1,125,2,124,1, - 100,3,117,1,114,41,124,2,100,3,117,1,114,39,124,1, - 124,2,106,1,107,3,114,39,116,2,106,3,100,4,124,1, - 155,2,100,5,124,2,106,1,155,2,100,6,157,5,116,4, - 100,7,100,8,141,3,1,0,124,1,83,0,124,2,100,3, - 117,1,114,48,124,2,106,1,83,0,116,2,106,3,100,9, - 116,4,100,7,100,8,141,3,1,0,124,0,100,10,25,0, - 125,1,100,11,124,0,118,1,114,71,124,1,160,5,100,12, - 161,1,100,13,25,0,125,1,124,1,83,0,41,14,122,167, - 67,97,108,99,117,108,97,116,101,32,119,104,97,116,32,95, - 95,112,97,99,107,97,103,101,95,95,32,115,104,111,117,108, - 100,32,98,101,46,10,10,32,32,32,32,95,95,112,97,99, - 107,97,103,101,95,95,32,105,115,32,110,111,116,32,103,117, - 97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100, - 101,102,105,110,101,100,32,111,114,32,99,111,117,108,100,32, - 98,101,32,115,101,116,32,116,111,32,78,111,110,101,10,32, - 32,32,32,116,111,32,114,101,112,114,101,115,101,110,116,32, - 116,104,97,116,32,105,116,115,32,112,114,111,112,101,114,32, - 118,97,108,117,101,32,105,115,32,117,110,107,110,111,119,110, - 46,10,10,32,32,32,32,114,158,0,0,0,114,113,0,0, - 0,78,122,32,95,95,112,97,99,107,97,103,101,95,95,32, - 33,61,32,95,95,115,112,101,99,95,95,46,112,97,114,101, - 110,116,32,40,122,4,32,33,61,32,250,1,41,233,3,0, - 0,0,41,1,90,10,115,116,97,99,107,108,101,118,101,108, - 122,89,99,97,110,39,116,32,114,101,115,111,108,118,101,32, - 112,97,99,107,97,103,101,32,102,114,111,109,32,95,95,115, - 112,101,99,95,95,32,111,114,32,95,95,112,97,99,107,97, - 103,101,95,95,44,32,102,97,108,108,105,110,103,32,98,97, - 99,107,32,111,110,32,95,95,110,97,109,101,95,95,32,97, - 110,100,32,95,95,112,97,116,104,95,95,114,9,0,0,0, - 114,154,0,0,0,114,141,0,0,0,114,25,0,0,0,41, - 6,114,38,0,0,0,114,143,0,0,0,114,101,0,0,0, - 114,102,0,0,0,114,169,0,0,0,114,142,0,0,0,41, - 3,218,7,103,108,111,98,97,108,115,114,209,0,0,0,114, - 109,0,0,0,114,5,0,0,0,114,5,0,0,0,114,6, - 0,0,0,218,17,95,99,97,108,99,95,95,95,112,97,99, - 107,97,103,101,95,95,66,4,0,0,115,42,0,0,0,10, - 7,10,1,8,1,18,1,6,1,2,1,4,255,4,1,6, - 255,4,2,6,254,4,3,8,1,6,1,6,2,4,2,6, - 254,8,3,8,1,14,1,4,1,114,240,0,0,0,114,5, - 0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0, - 9,0,0,0,5,0,0,0,67,0,0,0,115,174,0,0, - 0,124,4,100,1,107,2,114,9,116,0,124,0,131,1,125, - 5,110,18,124,1,100,2,117,1,114,15,124,1,110,1,105, - 0,125,6,116,1,124,6,131,1,125,7,116,0,124,0,124, - 7,124,4,131,3,125,5,124,3,115,74,124,4,100,1,107, - 2,114,42,116,0,124,0,160,2,100,3,161,1,100,1,25, - 0,131,1,83,0,124,0,115,46,124,5,83,0,116,3,124, - 0,131,1,116,3,124,0,160,2,100,3,161,1,100,1,25, - 0,131,1,24,0,125,8,116,4,106,5,124,5,106,6,100, - 2,116,3,124,5,106,6,131,1,124,8,24,0,133,2,25, - 0,25,0,83,0,116,7,124,5,100,4,131,2,114,85,116, - 8,124,5,124,3,116,0,131,3,83,0,124,5,83,0,41, - 5,97,215,1,0,0,73,109,112,111,114,116,32,97,32,109, - 111,100,117,108,101,46,10,10,32,32,32,32,84,104,101,32, - 39,103,108,111,98,97,108,115,39,32,97,114,103,117,109,101, - 110,116,32,105,115,32,117,115,101,100,32,116,111,32,105,110, - 102,101,114,32,119,104,101,114,101,32,116,104,101,32,105,109, - 112,111,114,116,32,105,115,32,111,99,99,117,114,114,105,110, - 103,32,102,114,111,109,10,32,32,32,32,116,111,32,104,97, - 110,100,108,101,32,114,101,108,97,116,105,118,101,32,105,109, - 112,111,114,116,115,46,32,84,104,101,32,39,108,111,99,97, - 108,115,39,32,97,114,103,117,109,101,110,116,32,105,115,32, - 105,103,110,111,114,101,100,46,32,84,104,101,10,32,32,32, - 32,39,102,114,111,109,108,105,115,116,39,32,97,114,103,117, - 109,101,110,116,32,115,112,101,99,105,102,105,101,115,32,119, - 104,97,116,32,115,104,111,117,108,100,32,101,120,105,115,116, - 32,97,115,32,97,116,116,114,105,98,117,116,101,115,32,111, - 110,32,116,104,101,32,109,111,100,117,108,101,10,32,32,32, - 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, - 40,101,46,103,46,32,96,96,102,114,111,109,32,109,111,100, - 117,108,101,32,105,109,112,111,114,116,32,60,102,114,111,109, - 108,105,115,116,62,96,96,41,46,32,32,84,104,101,32,39, - 108,101,118,101,108,39,10,32,32,32,32,97,114,103,117,109, - 101,110,116,32,114,101,112,114,101,115,101,110,116,115,32,116, - 104,101,32,112,97,99,107,97,103,101,32,108,111,99,97,116, - 105,111,110,32,116,111,32,105,109,112,111,114,116,32,102,114, - 111,109,32,105,110,32,97,32,114,101,108,97,116,105,118,101, - 10,32,32,32,32,105,109,112,111,114,116,32,40,101,46,103, - 46,32,96,96,102,114,111,109,32,46,46,112,107,103,32,105, - 109,112,111,114,116,32,109,111,100,96,96,32,119,111,117,108, - 100,32,104,97,118,101,32,97,32,39,108,101,118,101,108,39, - 32,111,102,32,50,41,46,10,10,32,32,32,32,114,25,0, - 0,0,78,114,141,0,0,0,114,154,0,0,0,41,9,114, - 229,0,0,0,114,240,0,0,0,218,9,112,97,114,116,105, - 116,105,111,110,114,208,0,0,0,114,18,0,0,0,114,105, - 0,0,0,114,9,0,0,0,114,11,0,0,0,114,234,0, - 0,0,41,9,114,20,0,0,0,114,239,0,0,0,218,6, - 108,111,99,97,108,115,114,235,0,0,0,114,210,0,0,0, - 114,110,0,0,0,90,8,103,108,111,98,97,108,115,95,114, - 209,0,0,0,90,7,99,117,116,95,111,102,102,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,218,10,95,95, - 105,109,112,111,114,116,95,95,93,4,0,0,115,30,0,0, - 0,8,11,10,1,16,2,8,1,12,1,4,1,8,3,18, - 1,4,1,4,1,26,4,30,3,10,1,12,1,4,2,114, - 243,0,0,0,99,1,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,67,0,0,0,115,38,0, - 0,0,116,0,160,1,124,0,161,1,125,1,124,1,100,0, - 117,0,114,15,116,2,100,1,124,0,23,0,131,1,130,1, - 116,3,124,1,131,1,83,0,41,2,78,122,25,110,111,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,32, - 110,97,109,101,100,32,41,4,114,175,0,0,0,114,183,0, - 0,0,114,87,0,0,0,114,173,0,0,0,41,2,114,20, - 0,0,0,114,109,0,0,0,114,5,0,0,0,114,5,0, - 0,0,114,6,0,0,0,218,18,95,98,117,105,108,116,105, - 110,95,102,114,111,109,95,110,97,109,101,130,4,0,0,115, - 8,0,0,0,10,1,8,1,12,1,8,1,114,244,0,0, - 0,99,2,0,0,0,0,0,0,0,0,0,0,0,10,0, - 0,0,5,0,0,0,67,0,0,0,115,166,0,0,0,124, - 1,97,0,124,0,97,1,116,2,116,1,131,1,125,2,116, - 1,106,3,160,4,161,0,68,0,93,36,92,2,125,3,125, - 4,116,5,124,4,124,2,131,2,114,49,124,3,116,1,106, - 6,118,0,114,30,116,7,125,5,110,9,116,0,160,8,124, - 3,161,1,114,38,116,9,125,5,110,1,113,13,116,10,124, - 4,124,5,131,2,125,6,116,11,124,6,124,4,131,2,1, - 0,113,13,116,1,106,3,116,12,25,0,125,7,100,1,68, - 0,93,23,125,8,124,8,116,1,106,3,118,1,114,69,116, - 13,124,8,131,1,125,9,110,5,116,1,106,3,124,8,25, - 0,125,9,116,14,124,7,124,8,124,9,131,3,1,0,113, - 57,100,2,83,0,41,3,122,250,83,101,116,117,112,32,105, - 109,112,111,114,116,108,105,98,32,98,121,32,105,109,112,111, - 114,116,105,110,103,32,110,101,101,100,101,100,32,98,117,105, - 108,116,45,105,110,32,109,111,100,117,108,101,115,32,97,110, - 100,32,105,110,106,101,99,116,105,110,103,32,116,104,101,109, - 10,32,32,32,32,105,110,116,111,32,116,104,101,32,103,108, - 111,98,97,108,32,110,97,109,101,115,112,97,99,101,46,10, - 10,32,32,32,32,65,115,32,115,121,115,32,105,115,32,110, - 101,101,100,101,100,32,102,111,114,32,115,121,115,46,109,111, - 100,117,108,101,115,32,97,99,99,101,115,115,32,97,110,100, - 32,95,105,109,112,32,105,115,32,110,101,101,100,101,100,32, - 116,111,32,108,111,97,100,32,98,117,105,108,116,45,105,110, - 10,32,32,32,32,109,111,100,117,108,101,115,44,32,116,104, - 111,115,101,32,116,119,111,32,109,111,100,117,108,101,115,32, - 109,117,115,116,32,98,101,32,101,120,112,108,105,99,105,116, - 108,121,32,112,97,115,115,101,100,32,105,110,46,10,10,32, - 32,32,32,41,3,114,26,0,0,0,114,101,0,0,0,114, - 71,0,0,0,78,41,15,114,64,0,0,0,114,18,0,0, - 0,114,3,0,0,0,114,105,0,0,0,218,5,105,116,101, - 109,115,114,216,0,0,0,114,86,0,0,0,114,175,0,0, - 0,114,98,0,0,0,114,193,0,0,0,114,155,0,0,0, - 114,161,0,0,0,114,9,0,0,0,114,244,0,0,0,114, - 12,0,0,0,41,10,218,10,115,121,115,95,109,111,100,117, - 108,101,218,11,95,105,109,112,95,109,111,100,117,108,101,90, - 11,109,111,100,117,108,101,95,116,121,112,101,114,20,0,0, - 0,114,110,0,0,0,114,122,0,0,0,114,109,0,0,0, - 90,11,115,101,108,102,95,109,111,100,117,108,101,90,12,98, - 117,105,108,116,105,110,95,110,97,109,101,90,14,98,117,105, - 108,116,105,110,95,109,111,100,117,108,101,114,5,0,0,0, - 114,5,0,0,0,114,6,0,0,0,218,6,95,115,101,116, - 117,112,137,4,0,0,115,40,0,0,0,4,9,4,1,8, - 3,18,1,10,1,10,1,6,1,10,1,6,1,2,2,10, - 1,10,1,2,128,10,3,8,1,10,1,10,1,10,2,14, - 1,4,251,114,248,0,0,0,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,38,0,0,0,116,0,124,0,124,1,131,2,1,0, - 116,1,106,2,160,3,116,4,161,1,1,0,116,1,106,2, - 160,3,116,5,161,1,1,0,100,1,83,0,41,2,122,48, - 73,110,115,116,97,108,108,32,105,109,112,111,114,116,101,114, - 115,32,102,111,114,32,98,117,105,108,116,105,110,32,97,110, - 100,32,102,114,111,122,101,110,32,109,111,100,117,108,101,115, - 78,41,6,114,248,0,0,0,114,18,0,0,0,114,214,0, - 0,0,114,132,0,0,0,114,175,0,0,0,114,193,0,0, - 0,41,2,114,246,0,0,0,114,247,0,0,0,114,5,0, - 0,0,114,5,0,0,0,114,6,0,0,0,218,8,95,105, - 110,115,116,97,108,108,172,4,0,0,115,6,0,0,0,10, - 2,12,2,16,1,114,249,0,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,67, - 0,0,0,115,32,0,0,0,100,1,100,2,108,0,125,0, - 124,0,97,1,124,0,160,2,116,3,106,4,116,5,25,0, - 161,1,1,0,100,2,83,0,41,3,122,57,73,110,115,116, - 97,108,108,32,105,109,112,111,114,116,101,114,115,32,116,104, - 97,116,32,114,101,113,117,105,114,101,32,101,120,116,101,114, - 110,97,108,32,102,105,108,101,115,121,115,116,101,109,32,97, - 99,99,101,115,115,114,25,0,0,0,78,41,6,218,26,95, - 102,114,111,122,101,110,95,105,109,112,111,114,116,108,105,98, - 95,101,120,116,101,114,110,97,108,114,139,0,0,0,114,249, - 0,0,0,114,18,0,0,0,114,105,0,0,0,114,9,0, - 0,0,41,1,114,250,0,0,0,114,5,0,0,0,114,5, - 0,0,0,114,6,0,0,0,218,27,95,105,110,115,116,97, - 108,108,95,101,120,116,101,114,110,97,108,95,105,109,112,111, - 114,116,101,114,115,180,4,0,0,115,6,0,0,0,8,3, - 4,1,20,1,114,251,0,0,0,114,190,0,0,0,114,0, - 0,0,0,114,24,0,0,0,41,4,78,78,114,5,0,0, - 0,114,25,0,0,0,41,54,114,10,0,0,0,114,7,0, - 0,0,114,26,0,0,0,114,101,0,0,0,114,71,0,0, - 0,114,139,0,0,0,114,17,0,0,0,114,21,0,0,0, - 114,66,0,0,0,114,37,0,0,0,114,47,0,0,0,114, - 22,0,0,0,114,23,0,0,0,114,55,0,0,0,114,57, - 0,0,0,114,60,0,0,0,114,72,0,0,0,114,74,0, - 0,0,114,83,0,0,0,114,95,0,0,0,114,100,0,0, - 0,114,111,0,0,0,114,124,0,0,0,114,125,0,0,0, - 114,104,0,0,0,114,155,0,0,0,114,161,0,0,0,114, - 165,0,0,0,114,119,0,0,0,114,106,0,0,0,114,172, - 0,0,0,114,173,0,0,0,114,107,0,0,0,114,175,0, - 0,0,114,193,0,0,0,114,200,0,0,0,114,211,0,0, - 0,114,213,0,0,0,114,215,0,0,0,114,221,0,0,0, - 90,15,95,69,82,82,95,77,83,71,95,80,82,69,70,73, - 88,114,223,0,0,0,114,226,0,0,0,218,6,111,98,106, - 101,99,116,114,227,0,0,0,114,228,0,0,0,114,229,0, - 0,0,114,234,0,0,0,114,240,0,0,0,114,243,0,0, - 0,114,244,0,0,0,114,248,0,0,0,114,249,0,0,0, - 114,251,0,0,0,114,5,0,0,0,114,5,0,0,0,114, - 5,0,0,0,114,6,0,0,0,218,8,60,109,111,100,117, - 108,101,62,1,0,0,0,115,104,0,0,0,4,0,8,22, - 4,9,4,1,4,1,4,3,8,3,8,8,4,8,4,2, - 16,3,14,4,14,77,14,21,8,16,8,37,8,17,14,11, - 8,8,8,11,8,12,8,19,14,26,16,101,10,26,14,45, - 8,72,8,17,8,17,8,30,8,36,8,45,14,15,14,80, - 14,85,8,13,8,9,10,10,8,47,4,16,8,1,8,2, - 6,32,8,3,10,16,14,15,8,37,10,27,8,37,8,7, - 8,35,12,8, + 1,14,1,14,1,10,4,18,1,12,1,2,1,8,128,2, + 249,2,252,4,12,114,234,0,0,0,99,1,0,0,0,0, + 0,0,0,0,0,0,0,3,0,0,0,6,0,0,0,67, + 0,0,0,115,146,0,0,0,124,0,160,0,100,1,161,1, + 125,1,124,0,160,0,100,2,161,1,125,2,124,1,100,3, + 117,1,114,41,124,2,100,3,117,1,114,39,124,1,124,2, + 106,1,107,3,114,39,116,2,106,3,100,4,124,1,155,2, + 100,5,124,2,106,1,155,2,100,6,157,5,116,4,100,7, + 100,8,141,3,1,0,124,1,83,0,124,2,100,3,117,1, + 114,48,124,2,106,1,83,0,116,2,106,3,100,9,116,4, + 100,7,100,8,141,3,1,0,124,0,100,10,25,0,125,1, + 100,11,124,0,118,1,114,71,124,1,160,5,100,12,161,1, + 100,13,25,0,125,1,124,1,83,0,41,14,122,167,67,97, + 108,99,117,108,97,116,101,32,119,104,97,116,32,95,95,112, + 97,99,107,97,103,101,95,95,32,115,104,111,117,108,100,32, + 98,101,46,10,10,32,32,32,32,95,95,112,97,99,107,97, + 103,101,95,95,32,105,115,32,110,111,116,32,103,117,97,114, + 97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,102, + 105,110,101,100,32,111,114,32,99,111,117,108,100,32,98,101, + 32,115,101,116,32,116,111,32,78,111,110,101,10,32,32,32, + 32,116,111,32,114,101,112,114,101,115,101,110,116,32,116,104, + 97,116,32,105,116,115,32,112,114,111,112,101,114,32,118,97, + 108,117,101,32,105,115,32,117,110,107,110,111,119,110,46,10, + 10,32,32,32,32,114,158,0,0,0,114,113,0,0,0,78, + 122,32,95,95,112,97,99,107,97,103,101,95,95,32,33,61, + 32,95,95,115,112,101,99,95,95,46,112,97,114,101,110,116, + 32,40,122,4,32,33,61,32,250,1,41,233,3,0,0,0, + 41,1,90,10,115,116,97,99,107,108,101,118,101,108,122,89, + 99,97,110,39,116,32,114,101,115,111,108,118,101,32,112,97, + 99,107,97,103,101,32,102,114,111,109,32,95,95,115,112,101, + 99,95,95,32,111,114,32,95,95,112,97,99,107,97,103,101, + 95,95,44,32,102,97,108,108,105,110,103,32,98,97,99,107, + 32,111,110,32,95,95,110,97,109,101,95,95,32,97,110,100, + 32,95,95,112,97,116,104,95,95,114,9,0,0,0,114,154, + 0,0,0,114,141,0,0,0,114,25,0,0,0,41,6,114, + 38,0,0,0,114,143,0,0,0,114,101,0,0,0,114,102, + 0,0,0,114,169,0,0,0,114,142,0,0,0,41,3,218, + 7,103,108,111,98,97,108,115,114,209,0,0,0,114,109,0, + 0,0,114,5,0,0,0,114,5,0,0,0,114,6,0,0, + 0,218,17,95,99,97,108,99,95,95,95,112,97,99,107,97, + 103,101,95,95,66,4,0,0,115,42,0,0,0,10,7,10, + 1,8,1,18,1,6,1,2,1,4,255,4,1,6,255,4, + 2,6,254,4,3,8,1,6,1,6,2,4,2,6,254,8, + 3,8,1,14,1,4,1,114,240,0,0,0,114,5,0,0, + 0,99,5,0,0,0,0,0,0,0,0,0,0,0,9,0, + 0,0,5,0,0,0,67,0,0,0,115,174,0,0,0,124, + 4,100,1,107,2,114,9,116,0,124,0,131,1,125,5,110, + 18,124,1,100,2,117,1,114,15,124,1,110,1,105,0,125, + 6,116,1,124,6,131,1,125,7,116,0,124,0,124,7,124, + 4,131,3,125,5,124,3,115,74,124,4,100,1,107,2,114, + 42,116,0,124,0,160,2,100,3,161,1,100,1,25,0,131, + 1,83,0,124,0,115,46,124,5,83,0,116,3,124,0,131, + 1,116,3,124,0,160,2,100,3,161,1,100,1,25,0,131, + 1,24,0,125,8,116,4,106,5,124,5,106,6,100,2,116, + 3,124,5,106,6,131,1,124,8,24,0,133,2,25,0,25, + 0,83,0,116,7,124,5,100,4,131,2,114,85,116,8,124, + 5,124,3,116,0,131,3,83,0,124,5,83,0,41,5,97, + 215,1,0,0,73,109,112,111,114,116,32,97,32,109,111,100, + 117,108,101,46,10,10,32,32,32,32,84,104,101,32,39,103, + 108,111,98,97,108,115,39,32,97,114,103,117,109,101,110,116, + 32,105,115,32,117,115,101,100,32,116,111,32,105,110,102,101, + 114,32,119,104,101,114,101,32,116,104,101,32,105,109,112,111, + 114,116,32,105,115,32,111,99,99,117,114,114,105,110,103,32, + 102,114,111,109,10,32,32,32,32,116,111,32,104,97,110,100, + 108,101,32,114,101,108,97,116,105,118,101,32,105,109,112,111, + 114,116,115,46,32,84,104,101,32,39,108,111,99,97,108,115, + 39,32,97,114,103,117,109,101,110,116,32,105,115,32,105,103, + 110,111,114,101,100,46,32,84,104,101,10,32,32,32,32,39, + 102,114,111,109,108,105,115,116,39,32,97,114,103,117,109,101, + 110,116,32,115,112,101,99,105,102,105,101,115,32,119,104,97, + 116,32,115,104,111,117,108,100,32,101,120,105,115,116,32,97, + 115,32,97,116,116,114,105,98,117,116,101,115,32,111,110,32, + 116,104,101,32,109,111,100,117,108,101,10,32,32,32,32,98, + 101,105,110,103,32,105,109,112,111,114,116,101,100,32,40,101, + 46,103,46,32,96,96,102,114,111,109,32,109,111,100,117,108, + 101,32,105,109,112,111,114,116,32,60,102,114,111,109,108,105, + 115,116,62,96,96,41,46,32,32,84,104,101,32,39,108,101, + 118,101,108,39,10,32,32,32,32,97,114,103,117,109,101,110, + 116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101, + 32,112,97,99,107,97,103,101,32,108,111,99,97,116,105,111, + 110,32,116,111,32,105,109,112,111,114,116,32,102,114,111,109, + 32,105,110,32,97,32,114,101,108,97,116,105,118,101,10,32, + 32,32,32,105,109,112,111,114,116,32,40,101,46,103,46,32, + 96,96,102,114,111,109,32,46,46,112,107,103,32,105,109,112, + 111,114,116,32,109,111,100,96,96,32,119,111,117,108,100,32, + 104,97,118,101,32,97,32,39,108,101,118,101,108,39,32,111, + 102,32,50,41,46,10,10,32,32,32,32,114,25,0,0,0, + 78,114,141,0,0,0,114,154,0,0,0,41,9,114,229,0, + 0,0,114,240,0,0,0,218,9,112,97,114,116,105,116,105, + 111,110,114,208,0,0,0,114,18,0,0,0,114,105,0,0, + 0,114,9,0,0,0,114,11,0,0,0,114,234,0,0,0, + 41,9,114,20,0,0,0,114,239,0,0,0,218,6,108,111, + 99,97,108,115,114,235,0,0,0,114,210,0,0,0,114,110, + 0,0,0,90,8,103,108,111,98,97,108,115,95,114,209,0, + 0,0,90,7,99,117,116,95,111,102,102,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,10,95,95,105,109, + 112,111,114,116,95,95,93,4,0,0,115,30,0,0,0,8, + 11,10,1,16,2,8,1,12,1,4,1,8,3,18,1,4, + 1,4,1,26,4,30,3,10,1,12,1,4,2,114,243,0, + 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,38,0,0,0, + 116,0,160,1,124,0,161,1,125,1,124,1,100,0,117,0, + 114,15,116,2,100,1,124,0,23,0,131,1,130,1,116,3, + 124,1,131,1,83,0,41,2,78,122,25,110,111,32,98,117, + 105,108,116,45,105,110,32,109,111,100,117,108,101,32,110,97, + 109,101,100,32,41,4,114,175,0,0,0,114,183,0,0,0, + 114,87,0,0,0,114,173,0,0,0,41,2,114,20,0,0, + 0,114,109,0,0,0,114,5,0,0,0,114,5,0,0,0, + 114,6,0,0,0,218,18,95,98,117,105,108,116,105,110,95, + 102,114,111,109,95,110,97,109,101,130,4,0,0,115,8,0, + 0,0,10,1,8,1,12,1,8,1,114,244,0,0,0,99, + 2,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0, + 5,0,0,0,67,0,0,0,115,166,0,0,0,124,1,97, + 0,124,0,97,1,116,2,116,1,131,1,125,2,116,1,106, + 3,160,4,161,0,68,0,93,36,92,2,125,3,125,4,116, + 5,124,4,124,2,131,2,114,49,124,3,116,1,106,6,118, + 0,114,30,116,7,125,5,110,9,116,0,160,8,124,3,161, + 1,114,38,116,9,125,5,110,1,113,13,116,10,124,4,124, + 5,131,2,125,6,116,11,124,6,124,4,131,2,1,0,113, + 13,116,1,106,3,116,12,25,0,125,7,100,1,68,0,93, + 23,125,8,124,8,116,1,106,3,118,1,114,69,116,13,124, + 8,131,1,125,9,110,5,116,1,106,3,124,8,25,0,125, + 9,116,14,124,7,124,8,124,9,131,3,1,0,113,57,100, + 2,83,0,41,3,122,250,83,101,116,117,112,32,105,109,112, + 111,114,116,108,105,98,32,98,121,32,105,109,112,111,114,116, + 105,110,103,32,110,101,101,100,101,100,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32, + 105,110,106,101,99,116,105,110,103,32,116,104,101,109,10,32, + 32,32,32,105,110,116,111,32,116,104,101,32,103,108,111,98, + 97,108,32,110,97,109,101,115,112,97,99,101,46,10,10,32, + 32,32,32,65,115,32,115,121,115,32,105,115,32,110,101,101, + 100,101,100,32,102,111,114,32,115,121,115,46,109,111,100,117, + 108,101,115,32,97,99,99,101,115,115,32,97,110,100,32,95, + 105,109,112,32,105,115,32,110,101,101,100,101,100,32,116,111, + 32,108,111,97,100,32,98,117,105,108,116,45,105,110,10,32, + 32,32,32,109,111,100,117,108,101,115,44,32,116,104,111,115, + 101,32,116,119,111,32,109,111,100,117,108,101,115,32,109,117, + 115,116,32,98,101,32,101,120,112,108,105,99,105,116,108,121, + 32,112,97,115,115,101,100,32,105,110,46,10,10,32,32,32, + 32,41,3,114,26,0,0,0,114,101,0,0,0,114,71,0, + 0,0,78,41,15,114,64,0,0,0,114,18,0,0,0,114, + 3,0,0,0,114,105,0,0,0,218,5,105,116,101,109,115, + 114,216,0,0,0,114,86,0,0,0,114,175,0,0,0,114, + 98,0,0,0,114,193,0,0,0,114,155,0,0,0,114,161, + 0,0,0,114,9,0,0,0,114,244,0,0,0,114,12,0, + 0,0,41,10,218,10,115,121,115,95,109,111,100,117,108,101, + 218,11,95,105,109,112,95,109,111,100,117,108,101,90,11,109, + 111,100,117,108,101,95,116,121,112,101,114,20,0,0,0,114, + 110,0,0,0,114,122,0,0,0,114,109,0,0,0,90,11, + 115,101,108,102,95,109,111,100,117,108,101,90,12,98,117,105, + 108,116,105,110,95,110,97,109,101,90,14,98,117,105,108,116, + 105,110,95,109,111,100,117,108,101,114,5,0,0,0,114,5, + 0,0,0,114,6,0,0,0,218,6,95,115,101,116,117,112, + 137,4,0,0,115,40,0,0,0,4,9,4,1,8,3,18, + 1,10,1,10,1,6,1,10,1,6,1,2,2,10,1,10, + 1,2,128,10,3,8,1,10,1,10,1,10,2,14,1,4, + 251,114,248,0,0,0,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, + 38,0,0,0,116,0,124,0,124,1,131,2,1,0,116,1, + 106,2,160,3,116,4,161,1,1,0,116,1,106,2,160,3, + 116,5,161,1,1,0,100,1,83,0,41,2,122,48,73,110, + 115,116,97,108,108,32,105,109,112,111,114,116,101,114,115,32, + 102,111,114,32,98,117,105,108,116,105,110,32,97,110,100,32, + 102,114,111,122,101,110,32,109,111,100,117,108,101,115,78,41, + 6,114,248,0,0,0,114,18,0,0,0,114,214,0,0,0, + 114,132,0,0,0,114,175,0,0,0,114,193,0,0,0,41, + 2,114,246,0,0,0,114,247,0,0,0,114,5,0,0,0, + 114,5,0,0,0,114,6,0,0,0,218,8,95,105,110,115, + 116,97,108,108,172,4,0,0,115,6,0,0,0,10,2,12, + 2,16,1,114,249,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,1,0,0,0,4,0,0,0,67,0,0, + 0,115,32,0,0,0,100,1,100,2,108,0,125,0,124,0, + 97,1,124,0,160,2,116,3,106,4,116,5,25,0,161,1, + 1,0,100,2,83,0,41,3,122,57,73,110,115,116,97,108, + 108,32,105,109,112,111,114,116,101,114,115,32,116,104,97,116, + 32,114,101,113,117,105,114,101,32,101,120,116,101,114,110,97, + 108,32,102,105,108,101,115,121,115,116,101,109,32,97,99,99, + 101,115,115,114,25,0,0,0,78,41,6,218,26,95,102,114, + 111,122,101,110,95,105,109,112,111,114,116,108,105,98,95,101, + 120,116,101,114,110,97,108,114,139,0,0,0,114,249,0,0, + 0,114,18,0,0,0,114,105,0,0,0,114,9,0,0,0, + 41,1,114,250,0,0,0,114,5,0,0,0,114,5,0,0, + 0,114,6,0,0,0,218,27,95,105,110,115,116,97,108,108, + 95,101,120,116,101,114,110,97,108,95,105,109,112,111,114,116, + 101,114,115,180,4,0,0,115,6,0,0,0,8,3,4,1, + 20,1,114,251,0,0,0,114,190,0,0,0,114,0,0,0, + 0,114,24,0,0,0,41,4,78,78,114,5,0,0,0,114, + 25,0,0,0,41,54,114,10,0,0,0,114,7,0,0,0, + 114,26,0,0,0,114,101,0,0,0,114,71,0,0,0,114, + 139,0,0,0,114,17,0,0,0,114,21,0,0,0,114,66, + 0,0,0,114,37,0,0,0,114,47,0,0,0,114,22,0, + 0,0,114,23,0,0,0,114,55,0,0,0,114,57,0,0, + 0,114,60,0,0,0,114,72,0,0,0,114,74,0,0,0, + 114,83,0,0,0,114,95,0,0,0,114,100,0,0,0,114, + 111,0,0,0,114,124,0,0,0,114,125,0,0,0,114,104, + 0,0,0,114,155,0,0,0,114,161,0,0,0,114,165,0, + 0,0,114,119,0,0,0,114,106,0,0,0,114,172,0,0, + 0,114,173,0,0,0,114,107,0,0,0,114,175,0,0,0, + 114,193,0,0,0,114,200,0,0,0,114,211,0,0,0,114, + 213,0,0,0,114,215,0,0,0,114,221,0,0,0,90,15, + 95,69,82,82,95,77,83,71,95,80,82,69,70,73,88,114, + 223,0,0,0,114,226,0,0,0,218,6,111,98,106,101,99, + 116,114,227,0,0,0,114,228,0,0,0,114,229,0,0,0, + 114,234,0,0,0,114,240,0,0,0,114,243,0,0,0,114, + 244,0,0,0,114,248,0,0,0,114,249,0,0,0,114,251, + 0,0,0,114,5,0,0,0,114,5,0,0,0,114,5,0, + 0,0,114,6,0,0,0,218,8,60,109,111,100,117,108,101, + 62,1,0,0,0,115,104,0,0,0,4,0,8,22,4,9, + 4,1,4,1,4,3,8,3,8,8,4,8,4,2,16,3, + 14,4,14,77,14,21,8,16,8,37,8,17,14,11,8,8, + 8,11,8,12,8,19,14,26,16,101,10,26,14,45,8,72, + 8,17,8,17,8,30,8,36,8,45,14,15,14,80,14,85, + 8,13,8,9,10,10,8,47,4,16,8,1,8,2,6,32, + 8,3,10,16,14,15,8,37,10,27,8,37,8,7,8,35, + 12,8, }; diff -Nru python3.10-3.10.7/Python/importlib_zipimport.h python3.10-3.10.12/Python/importlib_zipimport.h --- python3.10-3.10.7/Python/importlib_zipimport.h 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/importlib_zipimport.h 2023-06-06 22:30:33.000000000 +0000 @@ -612,452 +612,455 @@ 0,0,0,114,9,0,0,0,114,10,0,0,0,114,38,0, 0,0,115,1,0,0,115,14,0,0,0,10,1,14,1,8, 1,10,1,8,1,2,255,4,2,114,38,0,0,0,99,1, - 0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,9, - 0,0,0,67,0,0,0,115,220,4,0,0,122,7,116,0, + 0,0,0,0,0,0,0,0,0,0,0,27,0,0,0,10, + 0,0,0,67,0,0,0,115,2,5,0,0,122,7,116,0, 160,1,124,0,161,1,125,1,87,0,110,16,4,0,116,2, 121,23,1,0,1,0,1,0,116,3,100,1,124,0,155,2, 157,2,124,0,100,2,141,2,130,1,119,0,124,1,144,2, - 143,65,1,0,122,18,124,1,160,4,116,5,11,0,100,3, - 161,2,1,0,124,1,160,6,161,0,125,2,124,1,160,7, - 116,5,161,1,125,3,87,0,110,16,4,0,116,2,121,62, - 1,0,1,0,1,0,116,3,100,4,124,0,155,2,157,2, - 124,0,100,2,141,2,130,1,119,0,116,8,124,3,131,1, - 116,5,107,3,114,78,116,3,100,4,124,0,155,2,157,2, - 124,0,100,2,141,2,130,1,124,3,100,0,100,5,133,2, - 25,0,116,9,107,3,114,201,122,12,124,1,160,4,100,6, - 100,3,161,2,1,0,124,1,160,6,161,0,125,4,87,0, - 110,16,4,0,116,2,121,114,1,0,1,0,1,0,116,3, - 100,4,124,0,155,2,157,2,124,0,100,2,141,2,130,1, - 119,0,116,10,124,4,116,11,24,0,116,5,24,0,100,6, - 131,2,125,5,122,11,124,1,160,4,124,5,161,1,1,0, - 124,1,160,7,161,0,125,6,87,0,110,16,4,0,116,2, - 121,151,1,0,1,0,1,0,116,3,100,4,124,0,155,2, - 157,2,124,0,100,2,141,2,130,1,119,0,124,6,160,12, - 116,9,161,1,125,7,124,7,100,6,107,0,114,170,116,3, - 100,7,124,0,155,2,157,2,124,0,100,2,141,2,130,1, - 124,6,124,7,124,7,116,5,23,0,133,2,25,0,125,3, - 116,8,124,3,131,1,116,5,107,3,114,193,116,3,100,8, - 124,0,155,2,157,2,124,0,100,2,141,2,130,1,124,4, - 116,8,124,6,131,1,24,0,124,7,23,0,125,2,116,13, - 124,3,100,9,100,10,133,2,25,0,131,1,125,8,116,13, - 124,3,100,10,100,11,133,2,25,0,131,1,125,9,124,2, - 124,8,107,0,114,230,116,3,100,12,124,0,155,2,157,2, - 124,0,100,2,141,2,130,1,124,2,124,9,107,0,114,243, - 116,3,100,13,124,0,155,2,157,2,124,0,100,2,141,2, - 130,1,124,2,124,8,56,0,125,2,124,2,124,9,24,0, - 125,10,124,10,100,6,107,0,144,1,114,9,116,3,100,14, - 124,0,155,2,157,2,124,0,100,2,141,2,130,1,105,0, - 125,11,100,6,125,12,122,7,124,1,160,4,124,2,161,1, - 1,0,87,0,110,17,4,0,116,2,144,1,121,37,1,0, - 1,0,1,0,116,3,100,4,124,0,155,2,157,2,124,0, - 100,2,141,2,130,1,119,0,9,0,124,1,160,7,100,16, - 161,1,125,3,116,8,124,3,131,1,100,5,107,0,144,1, - 114,55,116,14,100,17,131,1,130,1,124,3,100,0,100,5, - 133,2,25,0,100,18,107,3,144,1,114,66,144,1,110,19, - 116,8,124,3,131,1,100,16,107,3,144,1,114,77,116,14, - 100,17,131,1,130,1,116,15,124,3,100,19,100,20,133,2, - 25,0,131,1,125,13,116,15,124,3,100,20,100,9,133,2, - 25,0,131,1,125,14,116,15,124,3,100,9,100,21,133,2, - 25,0,131,1,125,15,116,15,124,3,100,21,100,10,133,2, - 25,0,131,1,125,16,116,13,124,3,100,10,100,11,133,2, - 25,0,131,1,125,17,116,13,124,3,100,11,100,22,133,2, - 25,0,131,1,125,18,116,13,124,3,100,22,100,23,133,2, - 25,0,131,1,125,4,116,15,124,3,100,23,100,24,133,2, - 25,0,131,1,125,19,116,15,124,3,100,24,100,25,133,2, - 25,0,131,1,125,20,116,15,124,3,100,25,100,26,133,2, - 25,0,131,1,125,21,116,13,124,3,100,27,100,16,133,2, - 25,0,131,1,125,22,124,19,124,20,23,0,124,21,23,0, - 125,8,124,22,124,9,107,4,144,1,114,185,116,3,100,28, - 124,0,155,2,157,2,124,0,100,2,141,2,130,1,124,22, - 124,10,55,0,125,22,122,7,124,1,160,7,124,19,161,1, - 125,23,87,0,110,17,4,0,116,2,144,1,121,213,1,0, + 143,84,1,0,124,1,160,4,161,0,125,2,144,2,122,64, + 122,18,124,1,160,5,116,6,11,0,100,3,161,2,1,0, + 124,1,160,4,161,0,125,3,124,1,160,7,116,6,161,1, + 125,4,87,0,110,16,4,0,116,2,121,68,1,0,1,0, + 1,0,116,3,100,4,124,0,155,2,157,2,124,0,100,2, + 141,2,130,1,119,0,116,8,124,4,131,1,116,6,107,3, + 114,84,116,3,100,4,124,0,155,2,157,2,124,0,100,2, + 141,2,130,1,124,4,100,0,100,5,133,2,25,0,116,9, + 107,3,114,207,122,12,124,1,160,5,100,6,100,3,161,2, + 1,0,124,1,160,4,161,0,125,5,87,0,110,16,4,0, + 116,2,121,120,1,0,1,0,1,0,116,3,100,4,124,0, + 155,2,157,2,124,0,100,2,141,2,130,1,119,0,116,10, + 124,5,116,11,24,0,116,6,24,0,100,6,131,2,125,6, + 122,11,124,1,160,5,124,6,161,1,1,0,124,1,160,7, + 161,0,125,7,87,0,110,16,4,0,116,2,121,157,1,0, 1,0,1,0,116,3,100,4,124,0,155,2,157,2,124,0, - 100,2,141,2,130,1,119,0,116,8,124,23,131,1,124,19, - 107,3,144,1,114,230,116,3,100,4,124,0,155,2,157,2, - 124,0,100,2,141,2,130,1,122,25,116,8,124,1,160,7, - 124,8,124,19,24,0,161,1,131,1,124,8,124,19,24,0, - 107,3,144,1,114,254,116,3,100,4,124,0,155,2,157,2, - 124,0,100,2,141,2,130,1,87,0,110,17,4,0,116,2, - 144,2,121,16,1,0,1,0,1,0,116,3,100,4,124,0, - 155,2,157,2,124,0,100,2,141,2,130,1,119,0,124,13, - 100,29,64,0,144,2,114,27,124,23,160,16,161,0,125,23, - 110,26,122,7,124,23,160,16,100,30,161,1,125,23,87,0, - 110,18,4,0,116,17,144,2,121,52,1,0,1,0,1,0, - 124,23,160,16,100,31,161,1,160,18,116,19,161,1,125,23, - 89,0,110,1,119,0,124,23,160,20,100,32,116,21,161,2, - 125,23,116,22,160,23,124,0,124,23,161,2,125,24,124,24, - 124,14,124,18,124,4,124,22,124,15,124,16,124,17,102,8, - 125,25,124,25,124,11,124,23,60,0,124,12,100,33,55,0, - 125,12,144,1,113,39,87,0,100,0,4,0,4,0,131,3, - 1,0,110,9,49,0,144,2,115,96,119,1,1,0,1,0, - 1,0,89,0,1,0,116,24,160,25,100,34,124,12,124,0, - 161,3,1,0,124,11,83,0,41,35,78,122,21,99,97,110, - 39,116,32,111,112,101,110,32,90,105,112,32,102,105,108,101, - 58,32,114,12,0,0,0,114,93,0,0,0,250,21,99,97, - 110,39,116,32,114,101,97,100,32,90,105,112,32,102,105,108, - 101,58,32,233,4,0,0,0,114,0,0,0,0,122,16,110, - 111,116,32,97,32,90,105,112,32,102,105,108,101,58,32,122, - 18,99,111,114,114,117,112,116,32,90,105,112,32,102,105,108, - 101,58,32,233,12,0,0,0,233,16,0,0,0,233,20,0, - 0,0,122,28,98,97,100,32,99,101,110,116,114,97,108,32, - 100,105,114,101,99,116,111,114,121,32,115,105,122,101,58,32, - 122,30,98,97,100,32,99,101,110,116,114,97,108,32,100,105, - 114,101,99,116,111,114,121,32,111,102,102,115,101,116,58,32, - 122,38,98,97,100,32,99,101,110,116,114,97,108,32,100,105, - 114,101,99,116,111,114,121,32,115,105,122,101,32,111,114,32, - 111,102,102,115,101,116,58,32,84,233,46,0,0,0,250,27, - 69,79,70,32,114,101,97,100,32,119,104,101,114,101,32,110, - 111,116,32,101,120,112,101,99,116,101,100,115,4,0,0,0, - 80,75,1,2,233,8,0,0,0,233,10,0,0,0,233,14, - 0,0,0,233,24,0,0,0,233,28,0,0,0,233,30,0, - 0,0,233,32,0,0,0,233,34,0,0,0,233,42,0,0, - 0,122,25,98,97,100,32,108,111,99,97,108,32,104,101,97, - 100,101,114,32,111,102,102,115,101,116,58,32,105,0,8,0, - 0,218,5,97,115,99,105,105,90,6,108,97,116,105,110,49, - 250,1,47,114,5,0,0,0,122,33,122,105,112,105,109,112, - 111,114,116,58,32,102,111,117,110,100,32,123,125,32,110,97, - 109,101,115,32,105,110,32,123,33,114,125,41,26,218,3,95, - 105,111,218,9,111,112,101,110,95,99,111,100,101,114,22,0, - 0,0,114,3,0,0,0,218,4,115,101,101,107,218,20,69, - 78,68,95,67,69,78,84,82,65,76,95,68,73,82,95,83, - 73,90,69,90,4,116,101,108,108,218,4,114,101,97,100,114, - 58,0,0,0,218,18,83,84,82,73,78,71,95,69,78,68, - 95,65,82,67,72,73,86,69,218,3,109,97,120,218,15,77, - 65,88,95,67,79,77,77,69,78,84,95,76,69,78,218,5, - 114,102,105,110,100,114,2,0,0,0,218,8,69,79,70,69, - 114,114,111,114,114,1,0,0,0,114,68,0,0,0,218,18, - 85,110,105,99,111,100,101,68,101,99,111,100,101,69,114,114, - 111,114,218,9,116,114,97,110,115,108,97,116,101,218,11,99, - 112,52,51,55,95,116,97,98,108,101,114,19,0,0,0,114, - 20,0,0,0,114,21,0,0,0,114,30,0,0,0,114,48, - 0,0,0,114,81,0,0,0,41,26,114,29,0,0,0,218, - 2,102,112,90,15,104,101,97,100,101,114,95,112,111,115,105, - 116,105,111,110,218,6,98,117,102,102,101,114,218,9,102,105, - 108,101,95,115,105,122,101,90,17,109,97,120,95,99,111,109, - 109,101,110,116,95,115,116,97,114,116,218,4,100,97,116,97, - 90,3,112,111,115,218,11,104,101,97,100,101,114,95,115,105, - 122,101,90,13,104,101,97,100,101,114,95,111,102,102,115,101, - 116,90,10,97,114,99,95,111,102,102,115,101,116,114,33,0, - 0,0,218,5,99,111,117,110,116,218,5,102,108,97,103,115, - 218,8,99,111,109,112,114,101,115,115,218,4,116,105,109,101, - 218,4,100,97,116,101,218,3,99,114,99,218,9,100,97,116, - 97,95,115,105,122,101,218,9,110,97,109,101,95,115,105,122, - 101,218,10,101,120,116,114,97,95,115,105,122,101,90,12,99, - 111,109,109,101,110,116,95,115,105,122,101,218,11,102,105,108, - 101,95,111,102,102,115,101,116,114,47,0,0,0,114,13,0, - 0,0,218,1,116,114,9,0,0,0,114,9,0,0,0,114, - 10,0,0,0,114,27,0,0,0,146,1,0,0,115,238,0, - 0,0,2,1,14,1,12,1,18,1,2,255,8,3,2,1, - 14,1,8,1,14,1,12,1,18,1,2,255,12,2,18,1, - 16,1,2,3,12,1,12,1,12,1,10,1,2,1,6,255, - 2,255,8,3,2,1,2,255,2,1,4,255,2,2,10,1, - 12,1,12,1,10,1,2,1,6,255,2,255,10,3,8,1, - 10,1,2,1,6,255,16,2,12,1,10,1,2,1,6,255, - 16,2,16,2,16,1,8,1,18,1,8,1,18,1,8,1, - 8,1,10,1,18,1,4,2,4,2,2,1,14,1,14,1, - 18,1,2,255,2,2,10,1,14,1,8,1,18,2,4,1, - 14,1,8,1,16,1,16,1,16,1,16,1,16,1,16,1, - 16,1,16,1,16,1,16,1,16,1,12,1,10,1,18,1, - 8,1,2,2,14,1,14,1,18,1,2,255,14,2,18,1, - 2,4,28,1,18,1,4,255,14,2,18,1,2,255,10,3, - 10,2,2,3,14,1,14,1,20,1,2,255,12,3,12,1, - 20,1,8,1,8,1,4,202,2,6,30,196,14,109,4,1, - 114,27,0,0,0,117,190,1,0,0,0,1,2,3,4,5, - 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21, - 22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37, - 38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53, - 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69, - 70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85, - 86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101, - 102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117, - 118,119,120,121,122,123,124,125,126,127,195,135,195,188,195,169, - 195,162,195,164,195,160,195,165,195,167,195,170,195,171,195,168, - 195,175,195,174,195,172,195,132,195,133,195,137,195,166,195,134, - 195,180,195,182,195,178,195,187,195,185,195,191,195,150,195,156, - 194,162,194,163,194,165,226,130,167,198,146,195,161,195,173,195, - 179,195,186,195,177,195,145,194,170,194,186,194,191,226,140,144, - 194,172,194,189,194,188,194,161,194,171,194,187,226,150,145,226, - 150,146,226,150,147,226,148,130,226,148,164,226,149,161,226,149, - 162,226,149,150,226,149,149,226,149,163,226,149,145,226,149,151, - 226,149,157,226,149,156,226,149,155,226,148,144,226,148,148,226, - 148,180,226,148,172,226,148,156,226,148,128,226,148,188,226,149, - 158,226,149,159,226,149,154,226,149,148,226,149,169,226,149,166, - 226,149,160,226,149,144,226,149,172,226,149,167,226,149,168,226, - 149,164,226,149,165,226,149,153,226,149,152,226,149,146,226,149, - 147,226,149,171,226,149,170,226,148,152,226,148,140,226,150,136, - 226,150,132,226,150,140,226,150,144,226,150,128,206,177,195,159, - 206,147,207,128,206,163,207,131,194,181,207,132,206,166,206,152, - 206,169,206,180,226,136,158,207,134,206,181,226,136,169,226,137, - 161,194,177,226,137,165,226,137,164,226,140,160,226,140,161,195, - 183,226,137,136,194,176,226,136,153,194,183,226,136,154,226,129, - 191,194,178,226,150,160,194,160,99,0,0,0,0,0,0,0, - 0,0,0,0,0,1,0,0,0,8,0,0,0,67,0,0, - 0,115,106,0,0,0,116,0,114,11,116,1,160,2,100,1, - 161,1,1,0,116,3,100,2,131,1,130,1,100,3,97,0, - 122,29,122,8,100,4,100,5,108,4,109,5,125,0,1,0, - 87,0,110,16,4,0,116,6,121,38,1,0,1,0,1,0, - 116,1,160,2,100,1,161,1,1,0,116,3,100,2,131,1, - 130,1,119,0,87,0,100,6,97,0,110,3,100,6,97,0, - 119,0,116,1,160,2,100,7,161,1,1,0,124,0,83,0, - 41,8,78,122,27,122,105,112,105,109,112,111,114,116,58,32, - 122,108,105,98,32,85,78,65,86,65,73,76,65,66,76,69, - 250,41,99,97,110,39,116,32,100,101,99,111,109,112,114,101, - 115,115,32,100,97,116,97,59,32,122,108,105,98,32,110,111, - 116,32,97,118,97,105,108,97,98,108,101,84,114,0,0,0, - 0,169,1,218,10,100,101,99,111,109,112,114,101,115,115,70, - 122,25,122,105,112,105,109,112,111,114,116,58,32,122,108,105, - 98,32,97,118,97,105,108,97,98,108,101,41,7,218,15,95, - 105,109,112,111,114,116,105,110,103,95,122,108,105,98,114,48, - 0,0,0,114,81,0,0,0,114,3,0,0,0,90,4,122, - 108,105,98,114,147,0,0,0,218,9,69,120,99,101,112,116, - 105,111,110,114,146,0,0,0,114,9,0,0,0,114,9,0, - 0,0,114,10,0,0,0,218,20,95,103,101,116,95,100,101, - 99,111,109,112,114,101,115,115,95,102,117,110,99,48,2,0, - 0,115,28,0,0,0,4,2,10,3,8,1,4,2,4,1, - 16,1,12,1,10,1,8,1,2,254,2,255,12,5,10,2, - 4,1,114,150,0,0,0,99,2,0,0,0,0,0,0,0, - 0,0,0,0,17,0,0,0,9,0,0,0,67,0,0,0, - 115,120,1,0,0,124,1,92,8,125,2,125,3,125,4,125, - 5,125,6,125,7,125,8,125,9,124,4,100,1,107,0,114, - 18,116,0,100,2,131,1,130,1,116,1,160,2,124,0,161, - 1,143,129,125,10,122,7,124,10,160,3,124,6,161,1,1, - 0,87,0,110,16,4,0,116,4,121,47,1,0,1,0,1, - 0,116,0,100,3,124,0,155,2,157,2,124,0,100,4,141, - 2,130,1,119,0,124,10,160,5,100,5,161,1,125,11,116, - 6,124,11,131,1,100,5,107,3,114,63,116,7,100,6,131, - 1,130,1,124,11,100,0,100,7,133,2,25,0,100,8,107, - 3,114,80,116,0,100,9,124,0,155,2,157,2,124,0,100, - 4,141,2,130,1,116,8,124,11,100,10,100,11,133,2,25, - 0,131,1,125,12,116,8,124,11,100,11,100,5,133,2,25, - 0,131,1,125,13,100,5,124,12,23,0,124,13,23,0,125, - 14,124,6,124,14,55,0,125,6,122,7,124,10,160,3,124, - 6,161,1,1,0,87,0,110,16,4,0,116,4,121,129,1, - 0,1,0,1,0,116,0,100,3,124,0,155,2,157,2,124, - 0,100,4,141,2,130,1,119,0,124,10,160,5,124,4,161, - 1,125,15,116,6,124,15,131,1,124,4,107,3,114,145,116, - 4,100,12,131,1,130,1,87,0,100,0,4,0,4,0,131, - 3,1,0,110,8,49,0,115,155,119,1,1,0,1,0,1, - 0,89,0,1,0,124,3,100,1,107,2,114,166,124,15,83, - 0,122,5,116,9,131,0,125,16,87,0,110,11,4,0,116, - 10,121,182,1,0,1,0,1,0,116,0,100,13,131,1,130, - 1,119,0,124,16,124,15,100,14,131,2,83,0,41,15,78, - 114,0,0,0,0,122,18,110,101,103,97,116,105,118,101,32, - 100,97,116,97,32,115,105,122,101,114,98,0,0,0,114,12, - 0,0,0,114,110,0,0,0,114,104,0,0,0,114,99,0, - 0,0,115,4,0,0,0,80,75,3,4,122,23,98,97,100, - 32,108,111,99,97,108,32,102,105,108,101,32,104,101,97,100, - 101,114,58,32,233,26,0,0,0,114,109,0,0,0,122,26, - 122,105,112,105,109,112,111,114,116,58,32,99,97,110,39,116, - 32,114,101,97,100,32,100,97,116,97,114,145,0,0,0,105, - 241,255,255,255,41,11,114,3,0,0,0,114,116,0,0,0, - 114,117,0,0,0,114,118,0,0,0,114,22,0,0,0,114, - 120,0,0,0,114,58,0,0,0,114,125,0,0,0,114,1, - 0,0,0,114,150,0,0,0,114,149,0,0,0,41,17,114, - 29,0,0,0,114,61,0,0,0,90,8,100,97,116,97,112, - 97,116,104,114,136,0,0,0,114,140,0,0,0,114,131,0, - 0,0,114,143,0,0,0,114,137,0,0,0,114,138,0,0, - 0,114,139,0,0,0,114,129,0,0,0,114,130,0,0,0, - 114,141,0,0,0,114,142,0,0,0,114,133,0,0,0,90, - 8,114,97,119,95,100,97,116,97,114,147,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,114,59,0, - 0,0,69,2,0,0,115,72,0,0,0,20,1,8,1,8, - 1,12,2,2,2,14,1,12,1,18,1,2,255,10,2,12, - 1,8,1,16,2,18,2,16,2,16,1,12,1,8,1,2, - 1,14,1,12,1,18,1,2,255,10,2,12,1,8,1,2, - 255,28,233,8,26,4,2,2,3,10,1,12,1,8,1,2, - 255,10,2,114,59,0,0,0,99,2,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,16,0,0,0,116,0,124,0,124,1,24,0,131,1, - 100,1,107,1,83,0,41,2,78,114,5,0,0,0,41,1, - 218,3,97,98,115,41,2,90,2,116,49,90,2,116,50,114, - 9,0,0,0,114,9,0,0,0,114,10,0,0,0,218,9, - 95,101,113,95,109,116,105,109,101,115,2,0,0,115,2,0, - 0,0,16,2,114,153,0,0,0,99,5,0,0,0,0,0, - 0,0,0,0,0,0,14,0,0,0,6,0,0,0,67,0, - 0,0,115,254,0,0,0,124,3,124,2,100,1,156,2,125, - 5,116,0,160,1,124,4,124,3,124,5,161,3,125,6,124, - 6,100,2,64,0,100,3,107,3,125,7,124,7,114,63,124, - 6,100,4,64,0,100,3,107,3,125,8,116,2,106,3,100, - 5,107,3,114,62,124,8,115,38,116,2,106,3,100,6,107, - 2,114,62,116,4,124,0,124,2,131,2,125,9,124,9,100, - 0,117,1,114,62,116,2,160,5,116,0,106,6,124,9,161, - 2,125,10,116,0,160,7,124,4,124,10,124,3,124,5,161, - 4,1,0,110,40,116,8,124,0,124,2,131,2,92,2,125, - 11,125,12,124,11,114,103,116,9,116,10,124,4,100,7,100, - 8,133,2,25,0,131,1,124,11,131,2,114,93,116,10,124, - 4,100,8,100,9,133,2,25,0,131,1,124,12,107,3,114, - 103,116,11,160,12,100,10,124,3,155,2,157,2,161,1,1, - 0,100,0,83,0,116,13,160,14,124,4,100,9,100,0,133, - 2,25,0,161,1,125,13,116,15,124,13,116,16,131,2,115, - 125,116,17,100,11,124,1,155,2,100,12,157,3,131,1,130, - 1,124,13,83,0,41,13,78,41,2,114,47,0,0,0,114, - 13,0,0,0,114,5,0,0,0,114,0,0,0,0,114,93, - 0,0,0,90,5,110,101,118,101,114,90,6,97,108,119,97, - 121,115,114,105,0,0,0,114,100,0,0,0,114,101,0,0, - 0,122,22,98,121,116,101,99,111,100,101,32,105,115,32,115, - 116,97,108,101,32,102,111,114,32,122,16,99,111,109,112,105, - 108,101,100,32,109,111,100,117,108,101,32,122,21,32,105,115, - 32,110,111,116,32,97,32,99,111,100,101,32,111,98,106,101, - 99,116,41,18,114,21,0,0,0,90,13,95,99,108,97,115, - 115,105,102,121,95,112,121,99,218,4,95,105,109,112,90,21, - 99,104,101,99,107,95,104,97,115,104,95,98,97,115,101,100, - 95,112,121,99,115,218,15,95,103,101,116,95,112,121,99,95, - 115,111,117,114,99,101,218,11,115,111,117,114,99,101,95,104, - 97,115,104,90,17,95,82,65,87,95,77,65,71,73,67,95, - 78,85,77,66,69,82,90,18,95,118,97,108,105,100,97,116, - 101,95,104,97,115,104,95,112,121,99,218,29,95,103,101,116, - 95,109,116,105,109,101,95,97,110,100,95,115,105,122,101,95, - 111,102,95,115,111,117,114,99,101,114,153,0,0,0,114,2, - 0,0,0,114,48,0,0,0,114,81,0,0,0,218,7,109, - 97,114,115,104,97,108,90,5,108,111,97,100,115,114,15,0, - 0,0,218,10,95,99,111,100,101,95,116,121,112,101,218,9, - 84,121,112,101,69,114,114,111,114,41,14,114,32,0,0,0, - 114,60,0,0,0,114,69,0,0,0,114,41,0,0,0,114, - 132,0,0,0,90,11,101,120,99,95,100,101,116,97,105,108, - 115,114,135,0,0,0,90,10,104,97,115,104,95,98,97,115, - 101,100,90,12,99,104,101,99,107,95,115,111,117,114,99,101, - 90,12,115,111,117,114,99,101,95,98,121,116,101,115,114,156, - 0,0,0,90,12,115,111,117,114,99,101,95,109,116,105,109, - 101,90,11,115,111,117,114,99,101,95,115,105,122,101,114,53, - 0,0,0,114,9,0,0,0,114,9,0,0,0,114,10,0, - 0,0,218,15,95,117,110,109,97,114,115,104,97,108,95,99, - 111,100,101,123,2,0,0,115,72,0,0,0,2,2,2,1, - 6,254,14,5,12,2,4,1,12,1,10,1,2,1,2,255, - 8,1,2,255,10,2,8,1,4,1,4,1,2,1,4,254, - 4,5,8,1,4,255,2,128,8,4,6,255,4,3,22,3, - 18,1,2,255,4,2,8,1,4,255,4,2,18,2,10,1, - 16,1,4,1,114,161,0,0,0,99,1,0,0,0,0,0, - 0,0,0,0,0,0,1,0,0,0,4,0,0,0,67,0, - 0,0,115,28,0,0,0,124,0,160,0,100,1,100,2,161, - 2,125,0,124,0,160,0,100,3,100,2,161,2,125,0,124, - 0,83,0,41,4,78,115,2,0,0,0,13,10,243,1,0, - 0,0,10,243,1,0,0,0,13,41,1,114,19,0,0,0, - 41,1,218,6,115,111,117,114,99,101,114,9,0,0,0,114, - 9,0,0,0,114,10,0,0,0,218,23,95,110,111,114,109, - 97,108,105,122,101,95,108,105,110,101,95,101,110,100,105,110, - 103,115,168,2,0,0,115,6,0,0,0,12,1,12,1,4, - 1,114,165,0,0,0,99,2,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,6,0,0,0,67,0,0,0,115, - 24,0,0,0,116,0,124,1,131,1,125,1,116,1,124,1, - 124,0,100,1,100,2,100,3,141,4,83,0,41,4,78,114, - 79,0,0,0,84,41,1,90,12,100,111,110,116,95,105,110, - 104,101,114,105,116,41,2,114,165,0,0,0,218,7,99,111, - 109,112,105,108,101,41,2,114,60,0,0,0,114,164,0,0, - 0,114,9,0,0,0,114,9,0,0,0,114,10,0,0,0, - 218,15,95,99,111,109,112,105,108,101,95,115,111,117,114,99, - 101,175,2,0,0,115,4,0,0,0,8,1,16,1,114,167, + 100,2,141,2,130,1,119,0,124,7,160,12,116,9,161,1, + 125,8,124,8,100,6,107,0,114,176,116,3,100,7,124,0, + 155,2,157,2,124,0,100,2,141,2,130,1,124,7,124,8, + 124,8,116,6,23,0,133,2,25,0,125,4,116,8,124,4, + 131,1,116,6,107,3,114,199,116,3,100,8,124,0,155,2, + 157,2,124,0,100,2,141,2,130,1,124,5,116,8,124,7, + 131,1,24,0,124,8,23,0,125,3,116,13,124,4,100,9, + 100,10,133,2,25,0,131,1,125,9,116,13,124,4,100,10, + 100,11,133,2,25,0,131,1,125,10,124,3,124,9,107,0, + 114,236,116,3,100,12,124,0,155,2,157,2,124,0,100,2, + 141,2,130,1,124,3,124,10,107,0,114,249,116,3,100,13, + 124,0,155,2,157,2,124,0,100,2,141,2,130,1,124,3, + 124,9,56,0,125,3,124,3,124,10,24,0,125,11,124,11, + 100,6,107,0,144,1,114,15,116,3,100,14,124,0,155,2, + 157,2,124,0,100,2,141,2,130,1,105,0,125,12,100,6, + 125,13,122,7,124,1,160,5,124,3,161,1,1,0,87,0, + 110,17,4,0,116,2,144,1,121,43,1,0,1,0,1,0, + 116,3,100,4,124,0,155,2,157,2,124,0,100,2,141,2, + 130,1,119,0,9,0,124,1,160,7,100,16,161,1,125,4, + 116,8,124,4,131,1,100,5,107,0,144,1,114,61,116,14, + 100,17,131,1,130,1,124,4,100,0,100,5,133,2,25,0, + 100,18,107,3,144,1,114,72,144,1,110,19,116,8,124,4, + 131,1,100,16,107,3,144,1,114,83,116,14,100,17,131,1, + 130,1,116,15,124,4,100,19,100,20,133,2,25,0,131,1, + 125,14,116,15,124,4,100,20,100,9,133,2,25,0,131,1, + 125,15,116,15,124,4,100,9,100,21,133,2,25,0,131,1, + 125,16,116,15,124,4,100,21,100,10,133,2,25,0,131,1, + 125,17,116,13,124,4,100,10,100,11,133,2,25,0,131,1, + 125,18,116,13,124,4,100,11,100,22,133,2,25,0,131,1, + 125,19,116,13,124,4,100,22,100,23,133,2,25,0,131,1, + 125,5,116,15,124,4,100,23,100,24,133,2,25,0,131,1, + 125,20,116,15,124,4,100,24,100,25,133,2,25,0,131,1, + 125,21,116,15,124,4,100,25,100,26,133,2,25,0,131,1, + 125,22,116,13,124,4,100,27,100,16,133,2,25,0,131,1, + 125,23,124,20,124,21,23,0,124,22,23,0,125,9,124,23, + 124,10,107,4,144,1,114,191,116,3,100,28,124,0,155,2, + 157,2,124,0,100,2,141,2,130,1,124,23,124,11,55,0, + 125,23,122,7,124,1,160,7,124,20,161,1,125,24,87,0, + 110,17,4,0,116,2,144,1,121,219,1,0,1,0,1,0, + 116,3,100,4,124,0,155,2,157,2,124,0,100,2,141,2, + 130,1,119,0,116,8,124,24,131,1,124,20,107,3,144,1, + 114,236,116,3,100,4,124,0,155,2,157,2,124,0,100,2, + 141,2,130,1,122,25,116,8,124,1,160,7,124,9,124,20, + 24,0,161,1,131,1,124,9,124,20,24,0,107,3,144,2, + 114,4,116,3,100,4,124,0,155,2,157,2,124,0,100,2, + 141,2,130,1,87,0,110,17,4,0,116,2,144,2,121,22, + 1,0,1,0,1,0,116,3,100,4,124,0,155,2,157,2, + 124,0,100,2,141,2,130,1,119,0,124,14,100,29,64,0, + 144,2,114,33,124,24,160,16,161,0,125,24,110,26,122,7, + 124,24,160,16,100,30,161,1,125,24,87,0,110,18,4,0, + 116,17,144,2,121,58,1,0,1,0,1,0,124,24,160,16, + 100,31,161,1,160,18,116,19,161,1,125,24,89,0,110,1, + 119,0,124,24,160,20,100,32,116,21,161,2,125,24,116,22, + 160,23,124,0,124,24,161,2,125,25,124,25,124,15,124,19, + 124,5,124,23,124,16,124,17,124,18,102,8,125,26,124,26, + 124,12,124,24,60,0,124,13,100,33,55,0,125,13,144,1, + 113,45,87,0,124,1,160,5,124,2,161,1,1,0,110,6, + 124,1,160,5,124,2,161,1,1,0,119,0,87,0,100,0, + 4,0,4,0,131,3,1,0,110,9,49,0,144,2,115,115, + 119,1,1,0,1,0,1,0,89,0,1,0,116,24,160,25, + 100,34,124,13,124,0,161,3,1,0,124,12,83,0,41,35, + 78,122,21,99,97,110,39,116,32,111,112,101,110,32,90,105, + 112,32,102,105,108,101,58,32,114,12,0,0,0,114,93,0, + 0,0,250,21,99,97,110,39,116,32,114,101,97,100,32,90, + 105,112,32,102,105,108,101,58,32,233,4,0,0,0,114,0, + 0,0,0,122,16,110,111,116,32,97,32,90,105,112,32,102, + 105,108,101,58,32,122,18,99,111,114,114,117,112,116,32,90, + 105,112,32,102,105,108,101,58,32,233,12,0,0,0,233,16, + 0,0,0,233,20,0,0,0,122,28,98,97,100,32,99,101, + 110,116,114,97,108,32,100,105,114,101,99,116,111,114,121,32, + 115,105,122,101,58,32,122,30,98,97,100,32,99,101,110,116, + 114,97,108,32,100,105,114,101,99,116,111,114,121,32,111,102, + 102,115,101,116,58,32,122,38,98,97,100,32,99,101,110,116, + 114,97,108,32,100,105,114,101,99,116,111,114,121,32,115,105, + 122,101,32,111,114,32,111,102,102,115,101,116,58,32,84,233, + 46,0,0,0,250,27,69,79,70,32,114,101,97,100,32,119, + 104,101,114,101,32,110,111,116,32,101,120,112,101,99,116,101, + 100,115,4,0,0,0,80,75,1,2,233,8,0,0,0,233, + 10,0,0,0,233,14,0,0,0,233,24,0,0,0,233,28, + 0,0,0,233,30,0,0,0,233,32,0,0,0,233,34,0, + 0,0,233,42,0,0,0,122,25,98,97,100,32,108,111,99, + 97,108,32,104,101,97,100,101,114,32,111,102,102,115,101,116, + 58,32,105,0,8,0,0,218,5,97,115,99,105,105,90,6, + 108,97,116,105,110,49,250,1,47,114,5,0,0,0,122,33, + 122,105,112,105,109,112,111,114,116,58,32,102,111,117,110,100, + 32,123,125,32,110,97,109,101,115,32,105,110,32,123,33,114, + 125,41,26,218,3,95,105,111,218,9,111,112,101,110,95,99, + 111,100,101,114,22,0,0,0,114,3,0,0,0,90,4,116, + 101,108,108,218,4,115,101,101,107,218,20,69,78,68,95,67, + 69,78,84,82,65,76,95,68,73,82,95,83,73,90,69,218, + 4,114,101,97,100,114,58,0,0,0,218,18,83,84,82,73, + 78,71,95,69,78,68,95,65,82,67,72,73,86,69,218,3, + 109,97,120,218,15,77,65,88,95,67,79,77,77,69,78,84, + 95,76,69,78,218,5,114,102,105,110,100,114,2,0,0,0, + 218,8,69,79,70,69,114,114,111,114,114,1,0,0,0,114, + 68,0,0,0,218,18,85,110,105,99,111,100,101,68,101,99, + 111,100,101,69,114,114,111,114,218,9,116,114,97,110,115,108, + 97,116,101,218,11,99,112,52,51,55,95,116,97,98,108,101, + 114,19,0,0,0,114,20,0,0,0,114,21,0,0,0,114, + 30,0,0,0,114,48,0,0,0,114,81,0,0,0,41,27, + 114,29,0,0,0,218,2,102,112,90,12,115,116,97,114,116, + 95,111,102,102,115,101,116,90,15,104,101,97,100,101,114,95, + 112,111,115,105,116,105,111,110,218,6,98,117,102,102,101,114, + 218,9,102,105,108,101,95,115,105,122,101,90,17,109,97,120, + 95,99,111,109,109,101,110,116,95,115,116,97,114,116,218,4, + 100,97,116,97,90,3,112,111,115,218,11,104,101,97,100,101, + 114,95,115,105,122,101,90,13,104,101,97,100,101,114,95,111, + 102,102,115,101,116,90,10,97,114,99,95,111,102,102,115,101, + 116,114,33,0,0,0,218,5,99,111,117,110,116,218,5,102, + 108,97,103,115,218,8,99,111,109,112,114,101,115,115,218,4, + 116,105,109,101,218,4,100,97,116,101,218,3,99,114,99,218, + 9,100,97,116,97,95,115,105,122,101,218,9,110,97,109,101, + 95,115,105,122,101,218,10,101,120,116,114,97,95,115,105,122, + 101,90,12,99,111,109,109,101,110,116,95,115,105,122,101,218, + 11,102,105,108,101,95,111,102,102,115,101,116,114,47,0,0, + 0,114,13,0,0,0,218,1,116,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,114,27,0,0,0,146,1,0, + 0,115,244,0,0,0,2,1,14,1,12,1,18,1,2,255, + 8,3,8,4,4,1,2,1,14,1,8,1,14,1,12,1, + 18,1,2,255,12,2,18,1,16,1,2,3,12,1,12,1, + 12,1,10,1,2,1,6,255,2,255,8,3,2,1,2,255, + 2,1,4,255,2,2,10,1,12,1,12,1,10,1,2,1, + 6,255,2,255,10,3,8,1,10,1,2,1,6,255,16,2, + 12,1,10,1,2,1,6,255,16,2,16,2,16,1,8,1, + 18,1,8,1,18,1,8,1,8,1,10,1,18,1,4,2, + 4,2,2,1,14,1,14,1,18,1,2,255,2,2,10,1, + 14,1,8,1,18,2,4,1,14,1,8,1,16,1,16,1, + 16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1, + 16,1,12,1,10,1,18,1,8,1,2,2,14,1,14,1, + 18,1,2,255,14,2,18,1,2,4,28,1,18,1,4,255, + 14,2,18,1,2,255,10,3,10,2,2,3,14,1,14,1, + 20,1,2,255,12,3,12,1,20,1,8,1,8,1,4,202, + 2,6,26,50,30,141,14,116,4,1,114,27,0,0,0,117, + 190,1,0,0,0,1,2,3,4,5,6,7,8,9,10,11, + 12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, + 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43, + 44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59, + 60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75, + 76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91, + 92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107, + 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123, + 124,125,126,127,195,135,195,188,195,169,195,162,195,164,195,160, + 195,165,195,167,195,170,195,171,195,168,195,175,195,174,195,172, + 195,132,195,133,195,137,195,166,195,134,195,180,195,182,195,178, + 195,187,195,185,195,191,195,150,195,156,194,162,194,163,194,165, + 226,130,167,198,146,195,161,195,173,195,179,195,186,195,177,195, + 145,194,170,194,186,194,191,226,140,144,194,172,194,189,194,188, + 194,161,194,171,194,187,226,150,145,226,150,146,226,150,147,226, + 148,130,226,148,164,226,149,161,226,149,162,226,149,150,226,149, + 149,226,149,163,226,149,145,226,149,151,226,149,157,226,149,156, + 226,149,155,226,148,144,226,148,148,226,148,180,226,148,172,226, + 148,156,226,148,128,226,148,188,226,149,158,226,149,159,226,149, + 154,226,149,148,226,149,169,226,149,166,226,149,160,226,149,144, + 226,149,172,226,149,167,226,149,168,226,149,164,226,149,165,226, + 149,153,226,149,152,226,149,146,226,149,147,226,149,171,226,149, + 170,226,148,152,226,148,140,226,150,136,226,150,132,226,150,140, + 226,150,144,226,150,128,206,177,195,159,206,147,207,128,206,163, + 207,131,194,181,207,132,206,166,206,152,206,169,206,180,226,136, + 158,207,134,206,181,226,136,169,226,137,161,194,177,226,137,165, + 226,137,164,226,140,160,226,140,161,195,183,226,137,136,194,176, + 226,136,153,194,183,226,136,154,226,129,191,194,178,226,150,160, + 194,160,99,0,0,0,0,0,0,0,0,0,0,0,0,1, + 0,0,0,8,0,0,0,67,0,0,0,115,106,0,0,0, + 116,0,114,11,116,1,160,2,100,1,161,1,1,0,116,3, + 100,2,131,1,130,1,100,3,97,0,122,29,122,8,100,4, + 100,5,108,4,109,5,125,0,1,0,87,0,110,16,4,0, + 116,6,121,38,1,0,1,0,1,0,116,1,160,2,100,1, + 161,1,1,0,116,3,100,2,131,1,130,1,119,0,87,0, + 100,6,97,0,110,3,100,6,97,0,119,0,116,1,160,2, + 100,7,161,1,1,0,124,0,83,0,41,8,78,122,27,122, + 105,112,105,109,112,111,114,116,58,32,122,108,105,98,32,85, + 78,65,86,65,73,76,65,66,76,69,250,41,99,97,110,39, + 116,32,100,101,99,111,109,112,114,101,115,115,32,100,97,116, + 97,59,32,122,108,105,98,32,110,111,116,32,97,118,97,105, + 108,97,98,108,101,84,114,0,0,0,0,169,1,218,10,100, + 101,99,111,109,112,114,101,115,115,70,122,25,122,105,112,105, + 109,112,111,114,116,58,32,122,108,105,98,32,97,118,97,105, + 108,97,98,108,101,41,7,218,15,95,105,109,112,111,114,116, + 105,110,103,95,122,108,105,98,114,48,0,0,0,114,81,0, + 0,0,114,3,0,0,0,90,4,122,108,105,98,114,147,0, + 0,0,218,9,69,120,99,101,112,116,105,111,110,114,146,0, + 0,0,114,9,0,0,0,114,9,0,0,0,114,10,0,0, + 0,218,20,95,103,101,116,95,100,101,99,111,109,112,114,101, + 115,115,95,102,117,110,99,55,2,0,0,115,28,0,0,0, + 4,2,10,3,8,1,4,2,4,1,16,1,12,1,10,1, + 8,1,2,254,2,255,12,5,10,2,4,1,114,150,0,0, + 0,99,2,0,0,0,0,0,0,0,0,0,0,0,17,0, + 0,0,9,0,0,0,67,0,0,0,115,120,1,0,0,124, + 1,92,8,125,2,125,3,125,4,125,5,125,6,125,7,125, + 8,125,9,124,4,100,1,107,0,114,18,116,0,100,2,131, + 1,130,1,116,1,160,2,124,0,161,1,143,129,125,10,122, + 7,124,10,160,3,124,6,161,1,1,0,87,0,110,16,4, + 0,116,4,121,47,1,0,1,0,1,0,116,0,100,3,124, + 0,155,2,157,2,124,0,100,4,141,2,130,1,119,0,124, + 10,160,5,100,5,161,1,125,11,116,6,124,11,131,1,100, + 5,107,3,114,63,116,7,100,6,131,1,130,1,124,11,100, + 0,100,7,133,2,25,0,100,8,107,3,114,80,116,0,100, + 9,124,0,155,2,157,2,124,0,100,4,141,2,130,1,116, + 8,124,11,100,10,100,11,133,2,25,0,131,1,125,12,116, + 8,124,11,100,11,100,5,133,2,25,0,131,1,125,13,100, + 5,124,12,23,0,124,13,23,0,125,14,124,6,124,14,55, + 0,125,6,122,7,124,10,160,3,124,6,161,1,1,0,87, + 0,110,16,4,0,116,4,121,129,1,0,1,0,1,0,116, + 0,100,3,124,0,155,2,157,2,124,0,100,4,141,2,130, + 1,119,0,124,10,160,5,124,4,161,1,125,15,116,6,124, + 15,131,1,124,4,107,3,114,145,116,4,100,12,131,1,130, + 1,87,0,100,0,4,0,4,0,131,3,1,0,110,8,49, + 0,115,155,119,1,1,0,1,0,1,0,89,0,1,0,124, + 3,100,1,107,2,114,166,124,15,83,0,122,5,116,9,131, + 0,125,16,87,0,110,11,4,0,116,10,121,182,1,0,1, + 0,1,0,116,0,100,13,131,1,130,1,119,0,124,16,124, + 15,100,14,131,2,83,0,41,15,78,114,0,0,0,0,122, + 18,110,101,103,97,116,105,118,101,32,100,97,116,97,32,115, + 105,122,101,114,98,0,0,0,114,12,0,0,0,114,110,0, + 0,0,114,104,0,0,0,114,99,0,0,0,115,4,0,0, + 0,80,75,3,4,122,23,98,97,100,32,108,111,99,97,108, + 32,102,105,108,101,32,104,101,97,100,101,114,58,32,233,26, + 0,0,0,114,109,0,0,0,122,26,122,105,112,105,109,112, + 111,114,116,58,32,99,97,110,39,116,32,114,101,97,100,32, + 100,97,116,97,114,145,0,0,0,105,241,255,255,255,41,11, + 114,3,0,0,0,114,116,0,0,0,114,117,0,0,0,114, + 118,0,0,0,114,22,0,0,0,114,120,0,0,0,114,58, + 0,0,0,114,125,0,0,0,114,1,0,0,0,114,150,0, + 0,0,114,149,0,0,0,41,17,114,29,0,0,0,114,61, + 0,0,0,90,8,100,97,116,97,112,97,116,104,114,136,0, + 0,0,114,140,0,0,0,114,131,0,0,0,114,143,0,0, + 0,114,137,0,0,0,114,138,0,0,0,114,139,0,0,0, + 114,129,0,0,0,114,130,0,0,0,114,141,0,0,0,114, + 142,0,0,0,114,133,0,0,0,90,8,114,97,119,95,100, + 97,116,97,114,147,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,10,0,0,0,114,59,0,0,0,76,2,0,0, + 115,72,0,0,0,20,1,8,1,8,1,12,2,2,2,14, + 1,12,1,18,1,2,255,10,2,12,1,8,1,16,2,18, + 2,16,2,16,1,12,1,8,1,2,1,14,1,12,1,18, + 1,2,255,10,2,12,1,8,1,2,255,28,233,8,26,4, + 2,2,3,10,1,12,1,8,1,2,255,10,2,114,59,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,16,0,0,0, + 116,0,124,0,124,1,24,0,131,1,100,1,107,1,83,0, + 41,2,78,114,5,0,0,0,41,1,218,3,97,98,115,41, + 2,90,2,116,49,90,2,116,50,114,9,0,0,0,114,9, + 0,0,0,114,10,0,0,0,218,9,95,101,113,95,109,116, + 105,109,101,122,2,0,0,115,2,0,0,0,16,2,114,153, + 0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0, + 14,0,0,0,6,0,0,0,67,0,0,0,115,254,0,0, + 0,124,3,124,2,100,1,156,2,125,5,116,0,160,1,124, + 4,124,3,124,5,161,3,125,6,124,6,100,2,64,0,100, + 3,107,3,125,7,124,7,114,63,124,6,100,4,64,0,100, + 3,107,3,125,8,116,2,106,3,100,5,107,3,114,62,124, + 8,115,38,116,2,106,3,100,6,107,2,114,62,116,4,124, + 0,124,2,131,2,125,9,124,9,100,0,117,1,114,62,116, + 2,160,5,116,0,106,6,124,9,161,2,125,10,116,0,160, + 7,124,4,124,10,124,3,124,5,161,4,1,0,110,40,116, + 8,124,0,124,2,131,2,92,2,125,11,125,12,124,11,114, + 103,116,9,116,10,124,4,100,7,100,8,133,2,25,0,131, + 1,124,11,131,2,114,93,116,10,124,4,100,8,100,9,133, + 2,25,0,131,1,124,12,107,3,114,103,116,11,160,12,100, + 10,124,3,155,2,157,2,161,1,1,0,100,0,83,0,116, + 13,160,14,124,4,100,9,100,0,133,2,25,0,161,1,125, + 13,116,15,124,13,116,16,131,2,115,125,116,17,100,11,124, + 1,155,2,100,12,157,3,131,1,130,1,124,13,83,0,41, + 13,78,41,2,114,47,0,0,0,114,13,0,0,0,114,5, + 0,0,0,114,0,0,0,0,114,93,0,0,0,90,5,110, + 101,118,101,114,90,6,97,108,119,97,121,115,114,105,0,0, + 0,114,100,0,0,0,114,101,0,0,0,122,22,98,121,116, + 101,99,111,100,101,32,105,115,32,115,116,97,108,101,32,102, + 111,114,32,122,16,99,111,109,112,105,108,101,100,32,109,111, + 100,117,108,101,32,122,21,32,105,115,32,110,111,116,32,97, + 32,99,111,100,101,32,111,98,106,101,99,116,41,18,114,21, + 0,0,0,90,13,95,99,108,97,115,115,105,102,121,95,112, + 121,99,218,4,95,105,109,112,90,21,99,104,101,99,107,95, + 104,97,115,104,95,98,97,115,101,100,95,112,121,99,115,218, + 15,95,103,101,116,95,112,121,99,95,115,111,117,114,99,101, + 218,11,115,111,117,114,99,101,95,104,97,115,104,90,17,95, + 82,65,87,95,77,65,71,73,67,95,78,85,77,66,69,82, + 90,18,95,118,97,108,105,100,97,116,101,95,104,97,115,104, + 95,112,121,99,218,29,95,103,101,116,95,109,116,105,109,101, + 95,97,110,100,95,115,105,122,101,95,111,102,95,115,111,117, + 114,99,101,114,153,0,0,0,114,2,0,0,0,114,48,0, + 0,0,114,81,0,0,0,218,7,109,97,114,115,104,97,108, + 90,5,108,111,97,100,115,114,15,0,0,0,218,10,95,99, + 111,100,101,95,116,121,112,101,218,9,84,121,112,101,69,114, + 114,111,114,41,14,114,32,0,0,0,114,60,0,0,0,114, + 69,0,0,0,114,41,0,0,0,114,132,0,0,0,90,11, + 101,120,99,95,100,101,116,97,105,108,115,114,135,0,0,0, + 90,10,104,97,115,104,95,98,97,115,101,100,90,12,99,104, + 101,99,107,95,115,111,117,114,99,101,90,12,115,111,117,114, + 99,101,95,98,121,116,101,115,114,156,0,0,0,90,12,115, + 111,117,114,99,101,95,109,116,105,109,101,90,11,115,111,117, + 114,99,101,95,115,105,122,101,114,53,0,0,0,114,9,0, + 0,0,114,9,0,0,0,114,10,0,0,0,218,15,95,117, + 110,109,97,114,115,104,97,108,95,99,111,100,101,130,2,0, + 0,115,68,0,0,0,2,2,2,1,6,254,14,5,12,2, + 4,1,12,1,10,1,2,1,2,255,10,1,10,1,8,1, + 4,1,4,1,2,1,4,254,4,5,8,1,4,255,2,128, + 8,4,6,255,4,3,22,3,20,1,4,1,8,1,4,255, + 4,2,18,2,10,1,16,1,4,1,114,161,0,0,0,99, + 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, + 4,0,0,0,67,0,0,0,115,28,0,0,0,124,0,160, + 0,100,1,100,2,161,2,125,0,124,0,160,0,100,3,100, + 2,161,2,125,0,124,0,83,0,41,4,78,115,2,0,0, + 0,13,10,243,1,0,0,0,10,243,1,0,0,0,13,41, + 1,114,19,0,0,0,41,1,218,6,115,111,117,114,99,101, + 114,9,0,0,0,114,9,0,0,0,114,10,0,0,0,218, + 23,95,110,111,114,109,97,108,105,122,101,95,108,105,110,101, + 95,101,110,100,105,110,103,115,175,2,0,0,115,6,0,0, + 0,12,1,12,1,4,1,114,165,0,0,0,99,2,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,6,0,0, + 0,67,0,0,0,115,24,0,0,0,116,0,124,1,131,1, + 125,1,116,1,124,1,124,0,100,1,100,2,100,3,141,4, + 83,0,41,4,78,114,79,0,0,0,84,41,1,90,12,100, + 111,110,116,95,105,110,104,101,114,105,116,41,2,114,165,0, + 0,0,218,7,99,111,109,112,105,108,101,41,2,114,60,0, + 0,0,114,164,0,0,0,114,9,0,0,0,114,9,0,0, + 0,114,10,0,0,0,218,15,95,99,111,109,112,105,108,101, + 95,115,111,117,114,99,101,182,2,0,0,115,4,0,0,0, + 8,1,16,1,114,167,0,0,0,99,2,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,11,0,0,0,67,0, + 0,0,115,68,0,0,0,116,0,160,1,124,0,100,1,63, + 0,100,2,23,0,124,0,100,3,63,0,100,4,64,0,124, + 0,100,5,64,0,124,1,100,6,63,0,124,1,100,3,63, + 0,100,7,64,0,124,1,100,5,64,0,100,8,20,0,100, + 9,100,9,100,9,102,9,161,1,83,0,41,10,78,233,9, + 0,0,0,105,188,7,0,0,233,5,0,0,0,233,15,0, + 0,0,233,31,0,0,0,233,11,0,0,0,233,63,0,0, + 0,114,93,0,0,0,114,14,0,0,0,41,2,114,137,0, + 0,0,90,6,109,107,116,105,109,101,41,2,218,1,100,114, + 144,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,218,14,95,112,97,114,115,101,95,100,111,115,116, + 105,109,101,188,2,0,0,115,18,0,0,0,4,1,10,1, + 10,1,6,1,6,1,10,1,10,1,6,1,6,249,114,175, 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,11,0,0,0,67,0,0,0,115,68,0,0, - 0,116,0,160,1,124,0,100,1,63,0,100,2,23,0,124, - 0,100,3,63,0,100,4,64,0,124,0,100,5,64,0,124, - 1,100,6,63,0,124,1,100,3,63,0,100,7,64,0,124, - 1,100,5,64,0,100,8,20,0,100,9,100,9,100,9,102, - 9,161,1,83,0,41,10,78,233,9,0,0,0,105,188,7, - 0,0,233,5,0,0,0,233,15,0,0,0,233,31,0,0, - 0,233,11,0,0,0,233,63,0,0,0,114,93,0,0,0, - 114,14,0,0,0,41,2,114,137,0,0,0,90,6,109,107, - 116,105,109,101,41,2,218,1,100,114,144,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,218,14,95, - 112,97,114,115,101,95,100,111,115,116,105,109,101,181,2,0, - 0,115,18,0,0,0,4,1,10,1,10,1,6,1,6,1, - 10,1,10,1,6,1,6,249,114,175,0,0,0,99,2,0, - 0,0,0,0,0,0,0,0,0,0,6,0,0,0,10,0, - 0,0,67,0,0,0,115,110,0,0,0,122,41,124,1,100, - 1,100,0,133,2,25,0,100,2,118,0,115,11,74,0,130, - 1,124,1,100,0,100,1,133,2,25,0,125,1,124,0,106, - 0,124,1,25,0,125,2,124,2,100,3,25,0,125,3,124, - 2,100,4,25,0,125,4,124,2,100,5,25,0,125,5,116, - 1,124,4,124,3,131,2,124,5,102,2,87,0,83,0,4, - 0,116,2,116,3,116,4,102,3,121,54,1,0,1,0,1, - 0,89,0,100,6,83,0,119,0,41,7,78,114,14,0,0, - 0,169,2,218,1,99,218,1,111,114,169,0,0,0,233,6, - 0,0,0,233,3,0,0,0,41,2,114,0,0,0,0,114, - 0,0,0,0,41,5,114,28,0,0,0,114,175,0,0,0, - 114,26,0,0,0,218,10,73,110,100,101,120,69,114,114,111, - 114,114,160,0,0,0,41,6,114,32,0,0,0,114,13,0, - 0,0,114,61,0,0,0,114,137,0,0,0,114,138,0,0, - 0,90,17,117,110,99,111,109,112,114,101,115,115,101,100,95, - 115,105,122,101,114,9,0,0,0,114,9,0,0,0,114,10, - 0,0,0,114,157,0,0,0,194,2,0,0,115,22,0,0, - 0,2,1,20,2,12,1,10,1,8,3,8,1,8,1,16, - 1,18,1,6,1,2,255,114,157,0,0,0,99,2,0,0, - 0,0,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,67,0,0,0,115,80,0,0,0,124,1,100,1,100,0, - 133,2,25,0,100,2,118,0,115,10,74,0,130,1,124,1, - 100,0,100,1,133,2,25,0,125,1,122,7,124,0,106,0, - 124,1,25,0,125,2,87,0,110,10,4,0,116,1,121,33, - 1,0,1,0,1,0,89,0,100,0,83,0,119,0,116,2, - 124,0,106,3,124,2,131,2,83,0,41,3,78,114,14,0, - 0,0,114,176,0,0,0,41,4,114,28,0,0,0,114,26, - 0,0,0,114,59,0,0,0,114,29,0,0,0,41,3,114, - 32,0,0,0,114,13,0,0,0,114,61,0,0,0,114,9, - 0,0,0,114,9,0,0,0,114,10,0,0,0,114,155,0, - 0,0,213,2,0,0,115,16,0,0,0,20,2,12,1,2, - 2,14,1,12,1,6,1,2,255,12,3,114,155,0,0,0, - 99,2,0,0,0,0,0,0,0,0,0,0,0,14,0,0, - 0,11,0,0,0,67,0,0,0,115,14,1,0,0,116,0, - 124,0,124,1,131,2,125,2,100,0,125,3,116,1,68,0, - 93,102,92,3,125,4,125,5,125,6,124,2,124,4,23,0, - 125,7,116,2,106,3,100,1,124,0,106,4,116,5,124,7, - 100,2,100,3,141,5,1,0,122,7,124,0,106,6,124,7, - 25,0,125,8,87,0,110,9,4,0,116,7,121,45,1,0, - 1,0,1,0,89,0,113,9,119,0,124,8,100,4,25,0, - 125,9,116,8,124,0,106,4,124,8,131,2,125,10,100,0, - 125,11,124,5,114,91,122,10,116,9,124,0,124,9,124,7, - 124,1,124,10,131,5,125,11,87,0,110,25,4,0,116,10, - 121,90,1,0,125,12,1,0,122,8,124,12,125,3,87,0, - 89,0,100,0,125,12,126,12,110,10,100,0,125,12,126,12, - 119,1,119,0,116,11,124,9,124,10,131,2,125,11,124,11, - 100,0,117,0,114,101,113,9,124,8,100,4,25,0,125,9, - 124,11,124,6,124,9,102,3,2,0,1,0,83,0,124,3, - 114,126,100,5,124,3,155,0,157,2,125,13,116,12,124,13, - 124,1,100,6,141,2,124,3,130,2,116,12,100,7,124,1, - 155,2,157,2,124,1,100,6,141,2,130,1,41,8,78,122, - 13,116,114,121,105,110,103,32,123,125,123,125,123,125,114,93, - 0,0,0,41,1,90,9,118,101,114,98,111,115,105,116,121, - 114,0,0,0,0,122,20,109,111,100,117,108,101,32,108,111, - 97,100,32,102,97,105,108,101,100,58,32,114,65,0,0,0, - 114,64,0,0,0,41,13,114,39,0,0,0,114,95,0,0, - 0,114,48,0,0,0,114,81,0,0,0,114,29,0,0,0, - 114,20,0,0,0,114,28,0,0,0,114,26,0,0,0,114, - 59,0,0,0,114,161,0,0,0,114,80,0,0,0,114,167, - 0,0,0,114,3,0,0,0,41,14,114,32,0,0,0,114, - 41,0,0,0,114,13,0,0,0,90,12,105,109,112,111,114, - 116,95,101,114,114,111,114,114,96,0,0,0,114,97,0,0, - 0,114,54,0,0,0,114,69,0,0,0,114,61,0,0,0, - 114,43,0,0,0,114,132,0,0,0,114,53,0,0,0,90, - 3,101,120,99,114,82,0,0,0,114,9,0,0,0,114,9, - 0,0,0,114,10,0,0,0,114,51,0,0,0,228,2,0, - 0,115,58,0,0,0,10,1,4,1,14,1,8,1,22,1, - 2,1,14,1,12,1,4,1,2,255,8,3,12,1,4,1, - 4,1,2,1,20,1,14,1,16,1,8,128,2,255,10,3, - 8,1,2,3,8,1,14,1,4,2,10,1,14,1,18,2, - 114,51,0,0,0,41,46,114,91,0,0,0,90,26,95,102, - 114,111,122,101,110,95,105,109,112,111,114,116,108,105,98,95, - 101,120,116,101,114,110,97,108,114,21,0,0,0,114,1,0, - 0,0,114,2,0,0,0,90,17,95,102,114,111,122,101,110, - 95,105,109,112,111,114,116,108,105,98,114,48,0,0,0,114, - 154,0,0,0,114,116,0,0,0,114,158,0,0,0,114,72, - 0,0,0,114,137,0,0,0,114,35,0,0,0,90,7,95, - 95,97,108,108,95,95,114,20,0,0,0,90,15,112,97,116, - 104,95,115,101,112,97,114,97,116,111,114,115,114,18,0,0, - 0,114,80,0,0,0,114,3,0,0,0,114,25,0,0,0, - 218,4,116,121,112,101,114,75,0,0,0,114,119,0,0,0, - 114,121,0,0,0,114,123,0,0,0,90,13,95,76,111,97, - 100,101,114,66,97,115,105,99,115,114,4,0,0,0,114,95, - 0,0,0,114,39,0,0,0,114,40,0,0,0,114,38,0, - 0,0,114,27,0,0,0,114,128,0,0,0,114,148,0,0, - 0,114,150,0,0,0,114,59,0,0,0,114,153,0,0,0, - 114,161,0,0,0,218,8,95,95,99,111,100,101,95,95,114, - 159,0,0,0,114,165,0,0,0,114,167,0,0,0,114,175, - 0,0,0,114,157,0,0,0,114,155,0,0,0,114,51,0, - 0,0,114,9,0,0,0,114,9,0,0,0,114,9,0,0, - 0,114,10,0,0,0,218,8,60,109,111,100,117,108,101,62, - 1,0,0,0,115,90,0,0,0,4,0,8,16,16,1,8, - 1,8,1,8,1,8,1,8,1,8,1,8,1,8,2,6, - 3,14,1,16,3,4,4,8,2,4,2,4,1,4,1,18, - 2,0,127,0,127,12,50,12,1,2,1,2,1,4,252,8, - 9,8,4,8,9,8,31,2,126,2,254,4,29,8,5,8, - 21,8,46,8,8,10,40,8,5,8,7,8,6,8,13,8, - 19,12,15, + 6,0,0,0,10,0,0,0,67,0,0,0,115,110,0,0, + 0,122,41,124,1,100,1,100,0,133,2,25,0,100,2,118, + 0,115,11,74,0,130,1,124,1,100,0,100,1,133,2,25, + 0,125,1,124,0,106,0,124,1,25,0,125,2,124,2,100, + 3,25,0,125,3,124,2,100,4,25,0,125,4,124,2,100, + 5,25,0,125,5,116,1,124,4,124,3,131,2,124,5,102, + 2,87,0,83,0,4,0,116,2,116,3,116,4,102,3,121, + 54,1,0,1,0,1,0,89,0,100,6,83,0,119,0,41, + 7,78,114,14,0,0,0,169,2,218,1,99,218,1,111,114, + 169,0,0,0,233,6,0,0,0,233,3,0,0,0,41,2, + 114,0,0,0,0,114,0,0,0,0,41,5,114,28,0,0, + 0,114,175,0,0,0,114,26,0,0,0,218,10,73,110,100, + 101,120,69,114,114,111,114,114,160,0,0,0,41,6,114,32, + 0,0,0,114,13,0,0,0,114,61,0,0,0,114,137,0, + 0,0,114,138,0,0,0,90,17,117,110,99,111,109,112,114, + 101,115,115,101,100,95,115,105,122,101,114,9,0,0,0,114, + 9,0,0,0,114,10,0,0,0,114,157,0,0,0,201,2, + 0,0,115,22,0,0,0,2,1,20,2,12,1,10,1,8, + 3,8,1,8,1,16,1,18,1,6,1,2,255,114,157,0, + 0,0,99,2,0,0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,8,0,0,0,67,0,0,0,115,80,0,0,0, + 124,1,100,1,100,0,133,2,25,0,100,2,118,0,115,10, + 74,0,130,1,124,1,100,0,100,1,133,2,25,0,125,1, + 122,7,124,0,106,0,124,1,25,0,125,2,87,0,110,10, + 4,0,116,1,121,33,1,0,1,0,1,0,89,0,100,0, + 83,0,119,0,116,2,124,0,106,3,124,2,131,2,83,0, + 41,3,78,114,14,0,0,0,114,176,0,0,0,41,4,114, + 28,0,0,0,114,26,0,0,0,114,59,0,0,0,114,29, + 0,0,0,41,3,114,32,0,0,0,114,13,0,0,0,114, + 61,0,0,0,114,9,0,0,0,114,9,0,0,0,114,10, + 0,0,0,114,155,0,0,0,220,2,0,0,115,16,0,0, + 0,20,2,12,1,2,2,14,1,12,1,6,1,2,255,12, + 3,114,155,0,0,0,99,2,0,0,0,0,0,0,0,0, + 0,0,0,14,0,0,0,11,0,0,0,67,0,0,0,115, + 14,1,0,0,116,0,124,0,124,1,131,2,125,2,100,0, + 125,3,116,1,68,0,93,102,92,3,125,4,125,5,125,6, + 124,2,124,4,23,0,125,7,116,2,106,3,100,1,124,0, + 106,4,116,5,124,7,100,2,100,3,141,5,1,0,122,7, + 124,0,106,6,124,7,25,0,125,8,87,0,110,9,4,0, + 116,7,121,45,1,0,1,0,1,0,89,0,113,9,119,0, + 124,8,100,4,25,0,125,9,116,8,124,0,106,4,124,8, + 131,2,125,10,100,0,125,11,124,5,114,91,122,10,116,9, + 124,0,124,9,124,7,124,1,124,10,131,5,125,11,87,0, + 110,25,4,0,116,10,121,90,1,0,125,12,1,0,122,8, + 124,12,125,3,87,0,89,0,100,0,125,12,126,12,110,10, + 100,0,125,12,126,12,119,1,119,0,116,11,124,9,124,10, + 131,2,125,11,124,11,100,0,117,0,114,101,113,9,124,8, + 100,4,25,0,125,9,124,11,124,6,124,9,102,3,2,0, + 1,0,83,0,124,3,114,126,100,5,124,3,155,0,157,2, + 125,13,116,12,124,13,124,1,100,6,141,2,124,3,130,2, + 116,12,100,7,124,1,155,2,157,2,124,1,100,6,141,2, + 130,1,41,8,78,122,13,116,114,121,105,110,103,32,123,125, + 123,125,123,125,114,93,0,0,0,41,1,90,9,118,101,114, + 98,111,115,105,116,121,114,0,0,0,0,122,20,109,111,100, + 117,108,101,32,108,111,97,100,32,102,97,105,108,101,100,58, + 32,114,65,0,0,0,114,64,0,0,0,41,13,114,39,0, + 0,0,114,95,0,0,0,114,48,0,0,0,114,81,0,0, + 0,114,29,0,0,0,114,20,0,0,0,114,28,0,0,0, + 114,26,0,0,0,114,59,0,0,0,114,161,0,0,0,114, + 80,0,0,0,114,167,0,0,0,114,3,0,0,0,41,14, + 114,32,0,0,0,114,41,0,0,0,114,13,0,0,0,90, + 12,105,109,112,111,114,116,95,101,114,114,111,114,114,96,0, + 0,0,114,97,0,0,0,114,54,0,0,0,114,69,0,0, + 0,114,61,0,0,0,114,43,0,0,0,114,132,0,0,0, + 114,53,0,0,0,90,3,101,120,99,114,82,0,0,0,114, + 9,0,0,0,114,9,0,0,0,114,10,0,0,0,114,51, + 0,0,0,235,2,0,0,115,58,0,0,0,10,1,4,1, + 14,1,8,1,22,1,2,1,14,1,12,1,4,1,2,255, + 8,3,12,1,4,1,4,1,2,1,20,1,14,1,16,1, + 8,128,2,255,10,3,8,1,2,3,8,1,14,1,4,2, + 10,1,14,1,18,2,114,51,0,0,0,41,46,114,91,0, + 0,0,90,26,95,102,114,111,122,101,110,95,105,109,112,111, + 114,116,108,105,98,95,101,120,116,101,114,110,97,108,114,21, + 0,0,0,114,1,0,0,0,114,2,0,0,0,90,17,95, + 102,114,111,122,101,110,95,105,109,112,111,114,116,108,105,98, + 114,48,0,0,0,114,154,0,0,0,114,116,0,0,0,114, + 158,0,0,0,114,72,0,0,0,114,137,0,0,0,114,35, + 0,0,0,90,7,95,95,97,108,108,95,95,114,20,0,0, + 0,90,15,112,97,116,104,95,115,101,112,97,114,97,116,111, + 114,115,114,18,0,0,0,114,80,0,0,0,114,3,0,0, + 0,114,25,0,0,0,218,4,116,121,112,101,114,75,0,0, + 0,114,119,0,0,0,114,121,0,0,0,114,123,0,0,0, + 90,13,95,76,111,97,100,101,114,66,97,115,105,99,115,114, + 4,0,0,0,114,95,0,0,0,114,39,0,0,0,114,40, + 0,0,0,114,38,0,0,0,114,27,0,0,0,114,128,0, + 0,0,114,148,0,0,0,114,150,0,0,0,114,59,0,0, + 0,114,153,0,0,0,114,161,0,0,0,218,8,95,95,99, + 111,100,101,95,95,114,159,0,0,0,114,165,0,0,0,114, + 167,0,0,0,114,175,0,0,0,114,157,0,0,0,114,155, + 0,0,0,114,51,0,0,0,114,9,0,0,0,114,9,0, + 0,0,114,9,0,0,0,114,10,0,0,0,218,8,60,109, + 111,100,117,108,101,62,1,0,0,0,115,92,0,0,0,4, + 0,8,16,16,1,8,1,8,1,8,1,8,1,8,1,8, + 1,8,1,8,2,6,3,14,1,16,3,4,4,8,2,4, + 2,4,1,4,1,18,2,0,127,0,127,12,50,12,1,2, + 1,2,1,4,252,8,9,8,4,8,9,8,31,0,127,2, + 6,2,254,4,29,8,5,8,21,8,46,8,8,10,40,8, + 5,8,7,8,6,8,13,8,19,12,15, }; diff -Nru python3.10-3.10.7/Python/initconfig.c python3.10-3.10.12/Python/initconfig.c --- python3.10-3.10.7/Python/initconfig.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/initconfig.c 2023-06-06 22:30:33.000000000 +0000 @@ -1774,10 +1774,10 @@ config_init_int_max_str_digits(PyConfig *config) { int maxdigits; - int valid = 0; const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS"); if (env) { + int valid = 0; if (!_Py_str_to_int(env, &maxdigits)) { valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)); } @@ -1795,6 +1795,7 @@ const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits"); if (xoption) { const wchar_t *sep = wcschr(xoption, L'='); + int valid = 0; if (sep) { if (!config_wstr_to_int(sep + 1, &maxdigits)) { valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)); diff -Nru python3.10-3.10.7/Python/marshal.c python3.10-3.10.12/Python/marshal.c --- python3.10-3.10.7/Python/marshal.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/marshal.c 2023-06-06 22:30:33.000000000 +0000 @@ -576,6 +576,10 @@ } /* version currently has no effect for writing ints. */ +/* Note that while the documentation states that this function + * can error, currently it never does. Setting an exception in + * this function should be regarded as an API-breaking change. + */ void PyMarshal_WriteLongToFile(long x, FILE *fp, int version) { diff -Nru python3.10-3.10.7/Python/mysnprintf.c python3.10-3.10.12/Python/mysnprintf.c --- python3.10-3.10.7/Python/mysnprintf.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/mysnprintf.c 2023-06-06 22:30:33.000000000 +0000 @@ -9,6 +9,7 @@ would have been written had the buffer not been too small, and to set the last byte of the buffer to \0. At least MS _vsnprintf returns a negative value instead, and fills the entire buffer with non-\0 data. + Unlike C99, our wrappers do not support passing a null buffer. The wrappers ensure that str[size-1] is always \0 upon return. diff -Nru python3.10-3.10.7/Python/pylifecycle.c python3.10-3.10.12/Python/pylifecycle.c --- python3.10-3.10.7/Python/pylifecycle.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/pylifecycle.c 2023-06-06 22:30:33.000000000 +0000 @@ -1962,10 +1962,10 @@ /* Oops, it didn't work. Undo it all. */ PyErr_PrintEx(0); + PyThreadState_Swap(save_tstate); PyThreadState_Clear(tstate); PyThreadState_Delete(tstate); PyInterpreterState_Delete(interp); - PyThreadState_Swap(save_tstate); return status; } diff -Nru python3.10-3.10.7/Python/pystate.c python3.10-3.10.12/Python/pystate.c --- python3.10-3.10.7/Python/pystate.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/pystate.c 2023-06-06 22:30:33.000000000 +0000 @@ -293,11 +293,19 @@ _PyErr_Clear(tstate); } + // Clear the current/main thread state last. HEAD_LOCK(runtime); - for (PyThreadState *p = interp->tstate_head; p != NULL; p = p->next) { + PyThreadState *p = interp->tstate_head; + HEAD_UNLOCK(runtime); + while (p != NULL) { + // See https://github.com/python/cpython/issues/102126 + // Must be called without HEAD_LOCK held as it can deadlock + // if any finalizer tries to acquire that lock. PyThreadState_Clear(p); + HEAD_LOCK(runtime); + p = p->next; + HEAD_UNLOCK(runtime); } - HEAD_UNLOCK(runtime); Py_CLEAR(interp->audit_hooks); diff -Nru python3.10-3.10.7/Python/pytime.c python3.10-3.10.12/Python/pytime.c --- python3.10-3.10.7/Python/pytime.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/pytime.c 2023-06-06 22:30:33.000000000 +0000 @@ -34,6 +34,25 @@ #define NS_TO_MS (1000 * 1000) #define NS_TO_US (1000) +#if SIZEOF_TIME_T == SIZEOF_LONG_LONG +# define PY_TIME_T_MAX LLONG_MAX +# define PY_TIME_T_MIN LLONG_MIN +#elif SIZEOF_TIME_T == SIZEOF_LONG +# define PY_TIME_T_MAX LONG_MAX +# define PY_TIME_T_MIN LONG_MIN +#else +# error "unsupported time_t size" +#endif + +#if PY_TIME_T_MAX + PY_TIME_T_MIN != -1 +# error "time_t is not a two's complement integer type" +#endif + +#if _PyTime_MIN + _PyTime_MAX != -1 +# error "_PyTime_t is not a two's complement integer type" +#endif + + static void error_time_t_overflow(void) { @@ -157,7 +176,21 @@ } assert(0.0 <= floatpart && floatpart < denominator); - if (!_Py_InIntegralTypeRange(time_t, intpart)) { + /* + Conversion of an out-of-range value to time_t gives undefined behaviour + (C99 §6.3.1.4p1), so we must guard against it. However, checking that + `intpart` is in range is delicate: the obvious expression `intpart <= + PY_TIME_T_MAX` will first convert the value `PY_TIME_T_MAX` to a double, + potentially changing its value and leading to us failing to catch some + UB-inducing values. The code below works correctly under the mild + assumption that time_t is a two's complement integer type with no trap + representation, and that `PY_TIME_T_MIN` is within the representable + range of a C double. + + Note: we want the `if` condition below to be true for NaNs; therefore, + resist any temptation to simplify by applying De Morgan's laws. + */ + if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) { error_time_t_overflow(); return -1; } @@ -210,7 +243,8 @@ d = _PyTime_Round(d, round); (void)modf(d, &intpart); - if (!_Py_InIntegralTypeRange(time_t, intpart)) { + /* See comments in _PyTime_DoubleToDenominator */ + if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) { error_time_t_overflow(); return -1; } @@ -395,7 +429,8 @@ d *= (double)unit_to_ns; d = _PyTime_Round(d, round); - if (!_Py_InIntegralTypeRange(_PyTime_t, d)) { + /* See comments in _PyTime_DoubleToDenominator */ + if (!((double)_PyTime_MIN <= d && d < -(double)_PyTime_MIN)) { _PyTime_overflow(); return -1; } @@ -722,7 +757,9 @@ info->monotonic = 0; info->adjustable = 1; if (clock_getres(CLOCK_REALTIME, &res) == 0) { - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; + /* the explicit (double) casts silence loss-of-precision warnings + on some platforms */ + info->resolution = (double)res.tv_sec + (double)res.tv_nsec * 1e-9; } else { info->resolution = 1e-9; diff -Nru python3.10-3.10.7/Python/sysmodule.c python3.10-3.10.12/Python/sysmodule.c --- python3.10-3.10.7/Python/sysmodule.c 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Python/sysmodule.c 2023-06-06 22:30:33.000000000 +0000 @@ -462,6 +462,8 @@ if (interp->audit_hooks == NULL) { return NULL; } + /* Avoid having our list of hooks show up in the GC module */ + PyObject_GC_UnTrack(interp->audit_hooks); } if (PyList_Append(interp->audit_hooks, hook) < 0) { @@ -1657,12 +1659,12 @@ /*[clinic input] sys.get_int_max_str_digits -Set the maximum string digits limit for non-binary int<->str conversions. +Return the maximum string digits limit for non-binary int<->str conversions. [clinic start generated code]*/ static PyObject * sys_get_int_max_str_digits_impl(PyObject *module) -/*[clinic end generated code: output=0042f5e8ae0e8631 input=8dab13e2023e60d5]*/ +/*[clinic end generated code: output=0042f5e8ae0e8631 input=61bf9f99bc8b112d]*/ { PyInterpreterState *interp = _PyInterpreterState_GET(); return PyLong_FromSsize_t(interp->int_max_str_digits); diff -Nru python3.10-3.10.7/README.rst python3.10-3.10.12/README.rst --- python3.10-3.10.7/README.rst 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/README.rst 2023-06-06 22:30:33.000000000 +0000 @@ -1,5 +1,5 @@ -This is Python version 3.10.7 -============================= +This is Python version 3.10.12 +============================== .. image:: https://travis-ci.com/python/cpython.svg?branch=master :alt: CPython build status on Travis CI @@ -18,7 +18,7 @@ :target: https://discuss.python.org/ -Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. +Copyright © 2001-2023 Python Software Foundation. All rights reserved. See the end of this file for further copyright and license information. @@ -247,14 +247,14 @@ Copyright and License Information --------------------------------- -Copyright (c) 2001-2022 Python Software Foundation. All rights reserved. +Copyright © 2001-2023 Python Software Foundation. All rights reserved. -Copyright (c) 2000 BeOpen.com. All rights reserved. +Copyright © 2000 BeOpen.com. All rights reserved. -Copyright (c) 1995-2001 Corporation for National Research Initiatives. All +Copyright © 1995-2001 Corporation for National Research Initiatives. All rights reserved. -Copyright (c) 1991-1995 Stichting Mathematisch Centrum. All rights reserved. +Copyright © 1991-1995 Stichting Mathematisch Centrum. All rights reserved. See the `LICENSE `_ for information on the history of this software, terms & conditions for usage, and a diff -Nru python3.10-3.10.7/setup.py python3.10-3.10.12/setup.py --- python3.10-3.10.7/setup.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/setup.py 2023-06-06 22:30:33.000000000 +0000 @@ -1043,6 +1043,9 @@ self.add(Extension('_testcapi', ['_testcapimodule.c'], depends=['testcapi_long.h'])) + # Python Argument Clinc functional test module + self.add(Extension('_testclinic', ['_testclinic.c'])) + # Python Internal C API test module self.add(Extension('_testinternalcapi', ['_testinternalcapi.c'], extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) diff -Nru python3.10-3.10.7/Tools/clinic/clinic.py python3.10-3.10.12/Tools/clinic/clinic.py --- python3.10-3.10.7/Tools/clinic/clinic.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/clinic/clinic.py 2023-06-06 22:30:33.000000000 +0000 @@ -346,6 +346,12 @@ # "goto exit" if there are any. self.return_conversion = [] + # The C statements required to do some operations + # after the end of parsing but before cleaning up. + # These operations may be, for example, memory deallocations which + # can only be done without any error happening during argument parsing. + self.post_parsing = [] + # The C statements required to clean up after the impl call. self.cleanup = [] @@ -751,6 +757,7 @@ {modifications} {return_value} = {c_basename}_impl({impl_arguments}); {return_conversion} + {post_parsing} {exit_label} {cleanup} @@ -1343,6 +1350,7 @@ template_dict['impl_parameters'] = ", ".join(data.impl_parameters) template_dict['impl_arguments'] = ", ".join(data.impl_arguments) template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip()) + template_dict['post_parsing'] = format_escape("".join(data.post_parsing).rstrip()) template_dict['cleanup'] = format_escape("".join(data.cleanup)) template_dict['return_value'] = data.return_value @@ -1367,6 +1375,7 @@ return_conversion=template_dict['return_conversion'], initializers=template_dict['initializers'], modifications=template_dict['modifications'], + post_parsing=template_dict['post_parsing'], cleanup=template_dict['cleanup'], ) @@ -2595,6 +2604,10 @@ # parse_arguments self.parse_argument(data.parse_arguments) + # post_parsing + if post_parsing := self.post_parsing(): + data.post_parsing.append('/* Post parse cleanup for ' + name + ' */\n' + post_parsing.rstrip() + '\n') + # cleanup cleanup = self.cleanup() if cleanup: @@ -2686,6 +2699,14 @@ """ return "" + def post_parsing(self): + """ + The C statements required to do some operations after the end of parsing but before cleaning up. + Return a string containing this code indented at column 0. + If no operation is necessary, return an empty string. + """ + return "" + def cleanup(self): """ The C statements required to clean up after this variable. @@ -3278,10 +3299,10 @@ if NoneType in accept and self.c_default == "Py_None": self.c_default = "NULL" - def cleanup(self): + def post_parsing(self): if self.encoding: name = self.name - return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"]) + return f"PyMem_FREE({name});\n" def parse_arg(self, argname, displayname): if self.format_unit == 's': @@ -3449,6 +3470,7 @@ self.converter = '_PyUnicode_WideCharString_Opt_Converter' else: fail("Py_UNICODE_converter: illegal 'accept' argument " + repr(accept)) + self.c_default = "NULL" def cleanup(self): if not self.length: diff -Nru python3.10-3.10.7/Tools/i18n/pygettext.py python3.10-3.10.12/Tools/i18n/pygettext.py --- python3.10-3.10.7/Tools/i18n/pygettext.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/i18n/pygettext.py 2023-06-06 22:30:33.000000000 +0000 @@ -335,9 +335,10 @@ if ttype == tokenize.STRING and is_literal_string(tstring): self.__addentry(safe_eval(tstring), lineno, isdocstring=1) self.__freshmodule = 0 - elif ttype not in (tokenize.COMMENT, tokenize.NL): - self.__freshmodule = 0 - return + return + if ttype in (tokenize.COMMENT, tokenize.NL, tokenize.ENCODING): + return + self.__freshmodule = 0 # class or func/method docstring? if ttype == tokenize.NAME and tstring in ('class', 'def'): self.__state = self.__suiteseen diff -Nru python3.10-3.10.7/Tools/msi/build.bat python3.10-3.10.12/Tools/msi/build.bat --- python3.10-3.10.7/Tools/msi/build.bat 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/msi/build.bat 2023-06-06 22:30:33.000000000 +0000 @@ -27,23 +27,18 @@ call "%PCBUILD%find_msbuild.bat" %MSBUILD% if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable & exit /b 2) -if defined BUILDX86 ( - call "%PCBUILD%build.bat" -p Win32 -d -e %REBUILD% %BUILDTEST% - if errorlevel 1 exit /B %ERRORLEVEL% - call "%PCBUILD%build.bat" -p Win32 -e %REBUILD% %BUILDTEST% - if errorlevel 1 exit /B %ERRORLEVEL% -) -if defined BUILDX64 ( - call "%PCBUILD%build.bat" -p x64 -d -e %REBUILD% %BUILDTEST% - if errorlevel 1 exit /B %ERRORLEVEL% - call "%PCBUILD%build.bat" -p x64 -e %REBUILD% %BUILDTEST% - if errorlevel 1 exit /B %ERRORLEVEL% -) +if defined BUILDX86 call "%PCBUILD%build.bat" -p Win32 -d -e %REBUILD% %BUILDTEST% +if errorlevel 1 exit /B %ERRORLEVEL% +if defined BUILDX86 call "%PCBUILD%build.bat" -p Win32 -e %REBUILD% %BUILDTEST% +if errorlevel 1 exit /B %ERRORLEVEL% -if defined BUILDDOC ( - call "%PCBUILD%..\Doc\make.bat" htmlhelp - if errorlevel 1 exit /B %ERRORLEVEL% -) +if defined BUILDX64 call "%PCBUILD%build.bat" -p x64 -d -e %REBUILD% %BUILDTEST% +if errorlevel 1 exit /B %ERRORLEVEL% +if defined BUILDX64 call "%PCBUILD%build.bat" -p x64 -e %REBUILD% %BUILDTEST% +if errorlevel 1 exit /B %ERRORLEVEL% + +if defined BUILDDOC call "%PCBUILD%..\Doc\make.bat" html +if errorlevel 1 exit /B %ERRORLEVEL% rem Build the launcher MSI separately %MSBUILD% "%D%launcher\launcher.wixproj" /p:Platform=x86 @@ -60,14 +55,11 @@ set BUILD_CMD=%BUILD_CMD% /t:Rebuild ) -if defined BUILDX86 ( - %MSBUILD% /p:Platform=x86 %BUILD_CMD% - if errorlevel 1 exit /B %ERRORLEVEL% -) -if defined BUILDX64 ( - %MSBUILD% /p:Platform=x64 %BUILD_CMD% - if errorlevel 1 exit /B %ERRORLEVEL% -) +if defined BUILDX86 %MSBUILD% /p:Platform=x86 %BUILD_CMD% +if errorlevel 1 exit /B %ERRORLEVEL% + +if defined BUILDX64 %MSBUILD% /p:Platform=x64 %BUILD_CMD% +if errorlevel 1 exit /B %ERRORLEVEL% exit /B 0 diff -Nru python3.10-3.10.7/Tools/msi/buildrelease.bat python3.10-3.10.12/Tools/msi/buildrelease.bat --- python3.10-3.10.7/Tools/msi/buildrelease.bat 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/msi/buildrelease.bat 2023-06-06 22:30:33.000000000 +0000 @@ -12,7 +12,9 @@ rem The following substitutions will be applied to the release URI: rem Variable Description Example rem {arch} architecture amd64, win32 -set RELEASE_URI=https://www.python.org/{arch} +rem Do not change the scheme to https. Otherwise, releases built with this +rem script will not be upgradable to/from official releases of Python. +set RELEASE_URI=http://www.python.org/{arch} rem This is the URL that will be used to download installation files. rem The files available from the default URL *will* conflict with your diff -Nru python3.10-3.10.7/Tools/msi/bundle/bootstrap/pythonba.vcxproj python3.10-3.10.12/Tools/msi/bundle/bootstrap/pythonba.vcxproj --- python3.10-3.10.7/Tools/msi/bundle/bootstrap/pythonba.vcxproj 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/msi/bundle/bootstrap/pythonba.vcxproj 2023-06-06 22:30:33.000000000 +0000 @@ -21,11 +21,11 @@ Release Win32 - v142 + + v143 + v142 v141 - v140 - v140 - v120 + v140 {7A09B132-B3EE-499B-A700-A4B2157FEA3D} PythonBA @@ -50,8 +50,7 @@ comctl32.lib;gdiplus.lib;msimg32.lib;shlwapi.lib;wininet.lib;dutil.lib;balutil.lib;version.lib;uxtheme.lib;%(AdditionalDependencies) - $(WixInstallPath)sdk\vs2017\lib\x86 - $(WixInstallPath)sdk\vs2017\lib\x86 + $(WixInstallPath)sdk\vs2017\lib\x86 $(WixInstallPath)sdk\vs2015\lib\x86 $(WixInstallPath)sdk\vs2013\lib\x86 pythonba.def diff -Nru python3.10-3.10.7/Tools/msi/bundle/Default.wxl python3.10-3.10.12/Tools/msi/bundle/Default.wxl --- python3.10-3.10.7/Tools/msi/bundle/Default.wxl 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/msi/bundle/Default.wxl 2023-06-06 22:30:33.000000000 +0000 @@ -80,13 +80,13 @@ Use Programs and Features to remove the 'py' launcher. Upgrades the global 'py' launcher from the previous version. - Associate &files with Python (requires the py launcher) + Associate &files with Python (requires the 'py' launcher) Create shortcuts for installed applications Add Python to &environment variables - Add &Python [ShortVersion] to PATH - Install for &all users - for &all users (requires elevation) - Install &launcher for all users (recommended) + Add &python.exe to PATH + Install Python [ShortVersion] for &all users + for &all users (requires admin privileges) + Use admin privi&leges when installing py.exe &Precompile standard library Download debugging &symbols Download debu&g binaries (requires VS 2017 or later) diff -Nru python3.10-3.10.7/Tools/peg_generator/pegen/c_generator.py python3.10-3.10.12/Tools/peg_generator/pegen/c_generator.py --- python3.10-3.10.7/Tools/peg_generator/pegen/c_generator.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/peg_generator/pegen/c_generator.py 2023-06-06 22:30:33.000000000 +0000 @@ -604,7 +604,8 @@ self.add_return("_res") self.print("}") self.print("int _mark = p->mark;") - self.print("int _start_mark = p->mark;") + if memoize: + self.print("int _start_mark = p->mark;") self.print("void **_children = PyMem_Malloc(sizeof(void *));") self.out_of_memory_return(f"!_children") self.print("Py_ssize_t _children_capacity = 1;") @@ -624,7 +625,7 @@ self.out_of_memory_return(f"!_seq", cleanup_code="PyMem_Free(_children);") self.print("for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]);") self.print("PyMem_Free(_children);") - if node.name: + if memoize and node.name: self.print(f"_PyPegen_insert_memo(p, _start_mark, {node.name}_type, _seq);") self.add_return("_seq") @@ -783,7 +784,7 @@ self.print( "void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));" ) - self.out_of_memory_return(f"!_new_children") + self.out_of_memory_return(f"!_new_children", cleanup_code="PyMem_Free(_children);") self.print("_children = _new_children;") self.print("}") self.print("_children[_n++] = _res;") diff -Nru python3.10-3.10.7/Tools/scripts/generate_stdlib_module_names.py python3.10-3.10.12/Tools/scripts/generate_stdlib_module_names.py --- python3.10-3.10.7/Tools/scripts/generate_stdlib_module_names.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/scripts/generate_stdlib_module_names.py 2023-06-06 22:30:33.000000000 +0000 @@ -24,6 +24,7 @@ '_ctypes_test', '_testbuffer', '_testcapi', + '_testclinic', '_testconsole', '_testimportmultiple', '_testinternalcapi', diff -Nru python3.10-3.10.7/Tools/scripts/get-remote-certificate.py python3.10-3.10.12/Tools/scripts/get-remote-certificate.py --- python3.10-3.10.7/Tools/scripts/get-remote-certificate.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/scripts/get-remote-certificate.py 2023-06-06 22:30:33.000000000 +0000 @@ -15,8 +15,8 @@ def fetch_server_certificate (host, port): def subproc(cmd): - from subprocess import Popen, PIPE, STDOUT - proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True) + from subprocess import Popen, PIPE, STDOUT, DEVNULL + proc = Popen(cmd, stdout=PIPE, stderr=STDOUT, stdin=DEVNULL) status = proc.wait() output = proc.stdout.read() return status, output @@ -33,8 +33,8 @@ fp.write(m.group(1) + b"\n") try: tn2 = (outfile or tempfile.mktemp()) - status, output = subproc(r'openssl x509 -in "%s" -out "%s"' % - (tn, tn2)) + cmd = ['openssl', 'x509', '-in', tn, '-out', tn2] + status, output = subproc(cmd) if status != 0: raise RuntimeError('OpenSSL x509 failed with status %s and ' 'output: %r' % (status, output)) @@ -45,20 +45,9 @@ finally: os.unlink(tn) - if sys.platform.startswith("win"): - tfile = tempfile.mktemp() - with open(tfile, "w") as fp: - fp.write("quit\n") - try: - status, output = subproc( - 'openssl s_client -connect "%s:%s" -showcerts < "%s"' % - (host, port, tfile)) - finally: - os.unlink(tfile) - else: - status, output = subproc( - 'openssl s_client -connect "%s:%s" -showcerts < /dev/null' % - (host, port)) + cmd = ['openssl', 's_client', '-connect', '%s:%s' % (host, port), '-showcerts'] + status, output = subproc(cmd) + if status != 0: raise RuntimeError('OpenSSL connect failed with status %s and ' 'output: %r' % (status, output)) diff -Nru python3.10-3.10.7/Tools/ssl/multissltests.py python3.10-3.10.12/Tools/ssl/multissltests.py --- python3.10-3.10.7/Tools/ssl/multissltests.py 2022-09-05 13:00:02.000000000 +0000 +++ python3.10-3.10.12/Tools/ssl/multissltests.py 2023-06-06 22:30:33.000000000 +0000 @@ -47,8 +47,9 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.1.1q", - "3.0.5" + "1.1.1u", + "3.0.9", + "3.1.1", ] LIBRESSL_OLD_VERSIONS = [